UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

300 lines (299 loc) 11 kB
import type { BandedReducer } from './data-model/reducers/bandedReducer'; import type { DataChangeDescription } from './dataChangeDescription'; import type { BandedDomain, BandedDomainConfig } from './dataDomain'; import type { DataSet } from './dataSet'; import type { RangeLookup } from './rangeLookup'; import type { SortOrder } from './sortOrder'; export interface ScopeProvider { id: string; } export interface DataGroup { keys: any[]; datumIndices: readonly (readonly number[])[]; aggregation: any[][]; validScopes: Set<ScopeId>; } export interface UngroupedDataItem<I, D, V> { index: I; keys: any[]; values: V; aggValues?: [number, number][]; datum: D; validScopes?: Set<string>; } export declare const KEY_SORT_ORDERS: unique symbol; export declare const COLUMN_SORT_ORDERS: unique symbol; export declare const DOMAIN_RANGES: unique symbol; export declare const DOMAIN_BANDS: unique symbol; export declare const REDUCER_BANDS: unique symbol; export interface BandedReducerStats extends Record<string, number> { totalBands: number; dirtyBands: number; dataSize: number; scanRatio: number; cacheHits: number; } export declare const SHARED_ZERO_INDICES: readonly number[]; export type ScopeId = string; export type ProcessedValue = { value: unknown; missing: boolean; valid: boolean; }; export type SortOrderEntry = { sortOrder: SortOrder; isUnique?: boolean; isDirty?: boolean; }; export type ProcessedValueEntry = { value: any; valid: boolean; }; export interface GroupDatumIteratorOutput { group: DataGroup; groupIndex: number; columnIndex: number; datumIndex: number; } export type InsertionCacheValue = { keys: Map<number, ProcessedValueEntry>; values: Map<number, ProcessedValueEntry>; hasInvalidKey: boolean; hasInvalidValue: boolean; hasMissingValue: boolean; }; export type InsertionCache = Map<number, InsertionCacheValue>; export type ColumnBatch = [ScopeId, number[], unknown[][], Set<ScopeId>, boolean[] | undefined, boolean[] | undefined]; export type MergedColumnBatch = [ ScopeId[], number[], unknown[][], Set<ScopeId>, boolean[] | undefined, boolean[] | undefined ]; export interface CommonMetadata<D> { input: { count: number; }; scopes: Set<ScopeId>; dataSources: Map<ScopeId, DataSet<unknown>>; invalidKeys: Map<ScopeId, boolean[]> | undefined; invalidKeyCount: Map<ScopeId, number> | undefined; invalidData: Map<ScopeId, boolean[]> | undefined; invalidDataCount: Map<ScopeId, number> | undefined; missingData: Map<ScopeId, boolean[]> | undefined; keys: Map<ScopeId, unknown[]>[]; columns: any[][]; columnScopes: Set<ScopeId>[]; columnNeedValueOf?: boolean[]; domain: { keys: any[][]; values: any[][]; groups?: any[][]; aggValues?: [number, number][]; }; reduced?: { diff?: Record<string, ProcessedOutputDiff>; smallestKeyInterval?: number; largestKeyInterval?: number; filteredValueExceedUnfiltered?: boolean; sortedGroupDomain?: any[][]; animationValidation?: { uniqueKeys: boolean; orderedKeys: boolean; }; }; defs: { keys: (Scoped & DatumPropertyDefinition<keyof D>)[]; values: (Scoped & DatumPropertyDefinition<keyof D>)[]; allScopesHaveSameDefs: boolean; }; partialValidDataCount: number; time: number; /** Monotonically increasing version counter, incremented on every processing cycle */ version: number; optimizations?: OptimizationMetadata; [DOMAIN_RANGES]: Map<string, RangeLookup>; [KEY_SORT_ORDERS]: Map<number, SortOrderEntry>; [COLUMN_SORT_ORDERS]: Map<number, SortOrderEntry>; [DOMAIN_BANDS]: Map<InternalDatumPropertyDefinition<any>, BandedDomain>; [REDUCER_BANDS]?: Map<ReducerBandKey, BandedReducer>; changeDescription?: DataChangeDescription; } export interface UngroupedData<D> extends CommonMetadata<D> { type: 'ungrouped'; aggregation?: [number, number][][]; } export interface GroupedData<D> extends CommonMetadata<D> { type: 'grouped'; groups: DataGroup[]; groupsUnique: boolean; } export type ProcessedOutputDiff = { changed: boolean; added: Set<string>; updated: Set<string>; removed: Set<string>; moved: Set<string>; }; export interface ProcessedDataDef { index: number; def: PropertyDefinition<any>; } export type ProcessedData<D> = UngroupedData<D> | GroupedData<D>; /** Metadata about applied/skipped optimizations for debugging */ export interface OptimizationMetadata { /** Was reprocessing path used? */ reprocessing?: { applied: boolean; reason?: string; }; /** Domain banding optimization per definition */ domainBanding?: { keyDefs: Array<{ property: string; applied: boolean; reason?: string; stats?: { totalBands: number; dirtyBands: number; dataSize: number; scanRatio: number; }; }>; valueDefs: Array<{ property: string; applied: boolean; reason?: string; stats?: { totalBands: number; dirtyBands: number; dataSize: number; scanRatio: number; }; }>; }; /** Shared datum indices optimization (grouped data only) */ sharedDatumIndices?: { applied: boolean; sharedGroupCount: number; totalGroupCount: number; }; /** Batch merging optimization */ batchMerging?: { originalBatchCount: number; mergedBatchCount: number; mergeRatio: number; }; /** Reducer banding optimization */ reducerBanding?: { reducers: Array<{ property: string; applied: boolean; reason?: string; stats?: BandedReducerStats; }>; }; /** Overall performance metrics */ performance?: { processingTime: number; pathTaken: 'full-process' | 'reprocess'; }; } export type DatumPropertyType = 'range' | 'category'; export type MissMap = Map<string, number>; export type GroupingFn<K> = (keys: unknown[]) => K[]; export type GroupByFn = (extractedData: UngroupedData<any>) => GroupingFn<any>; export type DataModelOptions<K, Grouped extends boolean | undefined, IsScoped extends boolean = true> = { props: PropertyDefinition<K, IsScoped>[]; groupByKeys?: Grouped; groupByData?: Grouped; groupByFn?: GroupByFn; domainBandingConfig?: BandedDomainConfig; }; export type PropertyDefinition<K, IsScoped = false> = (DatumPropertyDefinition<K> & (IsScoped extends true ? Scoped : unknown)) | AggregatePropertyDefinition<any, any, any> | (PropertyValueProcessorDefinition<any> & (IsScoped extends true ? Scoped : unknown)) | GroupValueProcessorDefinition<any, any> | ReducerOutputPropertyDefinition<any> | ProcessorOutputPropertyDefinition<any>; export type ProcessorFn = (datum: unknown, index: number) => unknown; export type PropertyId<K extends string> = K | { id: string; }; export type Scoped = { /** Scope(s) a property definition belongs to (typically the defining entities unique identifier). */ scopes: ScopeId[]; }; export type PropertyIdentifiers = { id?: string; /** Map<Scope, Set<Id>> */ idsMap?: Map<string, Set<string>>; /** Optional group a property belongs to, for cross-scope combination. */ groupId?: string; }; export type PropertySelectors = { /** Optional group a property belongs to, for cross-scope combination. */ matchGroupIds?: string[]; }; export type DatumPropertyDefinition<K> = PropertyIdentifiers & { type: 'key' | 'value'; valueType: DatumPropertyType; property: K; forceValue?: any; includeProperty?: boolean; invalidValue?: any; missing?: MissMap; missingValue?: any; separateNegative?: boolean; validation?: (value: any, datum: any, index: number) => boolean; processor?: () => ProcessorFn; allowNullKey?: boolean; }; export type InternalDefinition<IsScoped extends boolean> = { index: number; } & (IsScoped extends true ? Scoped : unknown); export type InternalDatumPropertyDefinition<K> = DatumPropertyDefinition<K> & InternalDefinition<true> & { missing: MissMap; }; export type AggregatePropertyDefinition<D, K extends keyof D & string, R = [number, number], R2 = R> = Omit<PropertyIdentifiers, 'scopes'> & PropertySelectors & { type: 'aggregate'; aggregateFunction: (values: D[K][], keys?: D[K][]) => R; groupAggregateFunction?: (next?: R, acc?: R2) => R2; finalFunction?: (result: R2) => [number, number]; }; export type GroupValueAdjustFn<D, K extends keyof D & string> = (columns: D[K][][], indexes: number[], dataGroup: DataGroup, groupIndex: number) => void; export type GroupValueProcessorDefinition<D, K extends keyof D & string> = PropertyIdentifiers & PropertySelectors & { type: 'group-value-processor'; /** * Outer function called once per all data processing; inner function called once per group; * innermost called once per datum. */ adjust: () => () => GroupValueAdjustFn<D, K>; /** * Indicates whether this processor supports incremental reprocessing. * When true, the processor can safely be reapplied to modified data without * causing double-processing issues. */ supportsReprocessing?: boolean; }; export type PropertyValueAdjustFn<D> = (processedData: ProcessedData<D>, valueIndex: number) => void; export type PropertyValueProcessorDefinition<D> = PropertyIdentifiers & { type: 'property-value-processor'; property: string; adjust: () => PropertyValueAdjustFn<D>; }; export type ReducerOutputTypes = NonNullable<UngroupedData<any>['reduced']>; export type ReducerOutputKeys = keyof ReducerOutputTypes; export type ReducerBandKey = Extract<ReducerOutputKeys, string>; export type ReducerOutputPropertyDefinition<P extends ReducerOutputKeys = ReducerOutputKeys> = PropertyIdentifiers & { type: 'reducer'; property: P; initialValue?: ReducerOutputTypes[P]; reducer: () => (acc: ReducerOutputTypes[P], keys: unknown[]) => ReducerOutputTypes[P]; supportsBanding?: boolean; combineResults?: (bandResults: ReducerOutputTypes[P][]) => ReducerOutputTypes[P]; needsOverlap?: boolean; }; export type ProcessorOutputPropertyDefinition<P extends ReducerOutputKeys = ReducerOutputKeys> = PropertyIdentifiers & { type: 'processor'; property: P; calculate: (data: ProcessedData<any>, previousValue: ReducerOutputTypes[P] | undefined) => ReducerOutputTypes[P]; incrementalCalculate?: (data: ProcessedData<any>, previousValue: ReducerOutputTypes[P] | undefined) => ReducerOutputTypes[P]; };