mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	refactor: Extract playground steps (#3966)
This commit is contained in:
		
							parent
							
								
									8daab71219
								
							
						
					
					
						commit
						7d69750f3b
					
				@ -7,7 +7,7 @@ export const splitByComma = <T extends Record<string, string>>(
 | 
				
			|||||||
        Object.entries(obj).map(([key, value]) => [key, value.split(',')]),
 | 
					        Object.entries(obj).map(([key, value]) => [key, value.split(',')]),
 | 
				
			||||||
    ) as Dict<T>;
 | 
					    ) as Dict<T>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const generateCombinations = <T extends Record<string, string>>(
 | 
					export const generateCombinations = <T extends Record<string, any>>(
 | 
				
			||||||
    obj: Dict<T>,
 | 
					    obj: Dict<T>,
 | 
				
			||||||
): T[] => {
 | 
					): T[] => {
 | 
				
			||||||
    const keys = Object.keys(obj) as (keyof T)[];
 | 
					    const keys = Object.keys(obj) as (keyof T)[];
 | 
				
			||||||
@ -21,7 +21,7 @@ export const generateCombinations = <T extends Record<string, string>>(
 | 
				
			|||||||
    ) as T[];
 | 
					    ) as T[];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const generateObjectCombinations = <T extends Record<string, string>>(
 | 
					export const generateObjectCombinations = <T extends Record<string, any>>(
 | 
				
			||||||
    obj: T,
 | 
					    obj: T,
 | 
				
			||||||
): T[] => {
 | 
					): T[] => {
 | 
				
			||||||
    const splitObj = splitByComma(obj);
 | 
					    const splitObj = splitByComma(obj);
 | 
				
			||||||
@ -64,7 +64,7 @@ export const offlineUnleashClient = async ({
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client.start();
 | 
					    await client.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return client;
 | 
					    return client;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -4,11 +4,20 @@ import { IUnleashServices } from 'lib/types/services';
 | 
				
			|||||||
import { ALL } from '../../types/models/api-token';
 | 
					import { ALL } from '../../types/models/api-token';
 | 
				
			||||||
import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema';
 | 
					import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema';
 | 
				
			||||||
import { Logger } from '../../logger';
 | 
					import { Logger } from '../../logger';
 | 
				
			||||||
import { IUnleashConfig } from 'lib/types';
 | 
					import { ISegment, IUnleashConfig } from 'lib/types';
 | 
				
			||||||
import { offlineUnleashClient } from './offline-unleash-client';
 | 
					import { offlineUnleashClient } from './offline-unleash-client';
 | 
				
			||||||
import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature';
 | 
					import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature';
 | 
				
			||||||
import { FeatureStrategiesEvaluationResult } from 'lib/features/playground/feature-evaluator/client';
 | 
					import { FeatureStrategiesEvaluationResult } from 'lib/features/playground/feature-evaluator/client';
 | 
				
			||||||
import { ISegmentService } from 'lib/segments/segment-service-interface';
 | 
					import { ISegmentService } from 'lib/segments/segment-service-interface';
 | 
				
			||||||
 | 
					import { FeatureConfigurationClient } from '../../types/stores/feature-strategies-store';
 | 
				
			||||||
 | 
					import { generateObjectCombinations } from './generateObjectCombinations';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EvaluationInput = {
 | 
				
			||||||
 | 
					    features: FeatureConfigurationClient[];
 | 
				
			||||||
 | 
					    segments: ISegment[];
 | 
				
			||||||
 | 
					    featureProject: Record<string, string>;
 | 
				
			||||||
 | 
					    context: SdkContextSchema;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class PlaygroundService {
 | 
					export class PlaygroundService {
 | 
				
			||||||
    private readonly logger: Logger;
 | 
					    private readonly logger: Logger;
 | 
				
			||||||
@ -29,30 +38,38 @@ export class PlaygroundService {
 | 
				
			|||||||
        this.segmentService = segmentService;
 | 
					        this.segmentService = segmentService;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async evaluateQuery(
 | 
					    async evaluateAdvancedQuery(
 | 
				
			||||||
        projects: typeof ALL | string[],
 | 
					        projects: typeof ALL | string[],
 | 
				
			||||||
        environment: string,
 | 
					        environments: string[],
 | 
				
			||||||
        context: SdkContextSchema,
 | 
					        context: SdkContextSchema,
 | 
				
			||||||
    ): Promise<PlaygroundFeatureSchema[]> {
 | 
					    ): Promise<PlaygroundFeatureSchema[]> {
 | 
				
			||||||
        const [features, segments] = await Promise.all([
 | 
					        const segments = await this.segmentService.getActive();
 | 
				
			||||||
            this.featureToggleService.getClientFeatures(
 | 
					        const environmentFeatures = await Promise.all(
 | 
				
			||||||
                {
 | 
					            environments.map((env) => this.resolveFeatures(projects, env)),
 | 
				
			||||||
                    project: projects === ALL ? undefined : projects,
 | 
					 | 
				
			||||||
                    environment,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                true,
 | 
					 | 
				
			||||||
                false,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            this.segmentService.getActive(),
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
        const featureProject: Record<string, string> = features.reduce(
 | 
					 | 
				
			||||||
            (obj, feature) => {
 | 
					 | 
				
			||||||
                obj[feature.name] = feature.project;
 | 
					 | 
				
			||||||
                return obj;
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {},
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					        const contexts = generateObjectCombinations(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const results = await Promise.all(
 | 
				
			||||||
 | 
					            environmentFeatures.flatMap(({ features, featureProject }) =>
 | 
				
			||||||
 | 
					                contexts.map((singleContext) =>
 | 
				
			||||||
 | 
					                    this.evaluate({
 | 
				
			||||||
 | 
					                        features,
 | 
				
			||||||
 | 
					                        featureProject,
 | 
				
			||||||
 | 
					                        context: singleContext,
 | 
				
			||||||
 | 
					                        segments,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return results.flat();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private async evaluate({
 | 
				
			||||||
 | 
					        featureProject,
 | 
				
			||||||
 | 
					        features,
 | 
				
			||||||
 | 
					        segments,
 | 
				
			||||||
 | 
					        context,
 | 
				
			||||||
 | 
					    }: EvaluationInput): Promise<PlaygroundFeatureSchema[]> {
 | 
				
			||||||
        const [head, ...rest] = features;
 | 
					        const [head, ...rest] = features;
 | 
				
			||||||
        if (!head) {
 | 
					        if (!head) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
@ -102,4 +119,39 @@ export class PlaygroundService {
 | 
				
			|||||||
            return output;
 | 
					            return output;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private async resolveFeatures(
 | 
				
			||||||
 | 
					        projects: typeof ALL | string[],
 | 
				
			||||||
 | 
					        environment: string,
 | 
				
			||||||
 | 
					    ): Promise<Pick<EvaluationInput, 'features' | 'featureProject'>> {
 | 
				
			||||||
 | 
					        const features = await this.featureToggleService.getClientFeatures(
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                project: projects === ALL ? undefined : projects,
 | 
				
			||||||
 | 
					                environment,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            true,
 | 
				
			||||||
 | 
					            false,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        const featureProject: Record<string, string> = features.reduce(
 | 
				
			||||||
 | 
					            (obj, feature) => {
 | 
				
			||||||
 | 
					                obj[feature.name] = feature.project;
 | 
				
			||||||
 | 
					                return obj;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {},
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return { features, featureProject };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async evaluateQuery(
 | 
				
			||||||
 | 
					        projects: typeof ALL | string[],
 | 
				
			||||||
 | 
					        environment: string,
 | 
				
			||||||
 | 
					        context: SdkContextSchema,
 | 
				
			||||||
 | 
					    ): Promise<PlaygroundFeatureSchema[]> {
 | 
				
			||||||
 | 
					        const [{ features, featureProject }, segments] = await Promise.all([
 | 
				
			||||||
 | 
					            this.resolveFeatures(projects, environment),
 | 
				
			||||||
 | 
					            this.segmentService.getActive(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.evaluate({ features, featureProject, segments, context });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user