mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: validate strategies (#1429)
* feat: validate strategies * fix: optional coalescing on constraints * fix: update test
This commit is contained in:
		
							parent
							
								
									3de044ff97
								
							
						
					
					
						commit
						55469801cf
					
				@ -165,6 +165,14 @@ class FeatureToggleService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async validateConstraints(constraints: IConstraint[]): Promise<void> {
 | 
				
			||||||
 | 
					        const validations = constraints.map((constraint) => {
 | 
				
			||||||
 | 
					            return this.validateConstraint(constraint);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await Promise.all(validations);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async validateConstraint(constraint: IConstraint): Promise<void> {
 | 
					    async validateConstraint(constraint: IConstraint): Promise<void> {
 | 
				
			||||||
        const { operator } = constraint;
 | 
					        const { operator } = constraint;
 | 
				
			||||||
        await constraintSchema.validateAsync(constraint);
 | 
					        await constraintSchema.validateAsync(constraint);
 | 
				
			||||||
@ -272,6 +280,11 @@ class FeatureToggleService {
 | 
				
			|||||||
    ): Promise<IStrategyConfig> {
 | 
					    ): Promise<IStrategyConfig> {
 | 
				
			||||||
        const { featureName, projectId, environment } = context;
 | 
					        const { featureName, projectId, environment } = context;
 | 
				
			||||||
        await this.validateFeatureContext(context);
 | 
					        await this.validateFeatureContext(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strategyConfig.constraints?.length > 0) {
 | 
				
			||||||
 | 
					            await this.validateConstraints(strategyConfig.constraints);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            const newFeatureStrategy =
 | 
					            const newFeatureStrategy =
 | 
				
			||||||
                await this.featureStrategiesStore.createStrategyFeatureEnv({
 | 
					                await this.featureStrategiesStore.createStrategyFeatureEnv({
 | 
				
			||||||
@ -334,6 +347,10 @@ class FeatureToggleService {
 | 
				
			|||||||
                updates,
 | 
					                updates,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (updates.constraints?.length > 0) {
 | 
				
			||||||
 | 
					                await this.validateConstraints(updates.constraints);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Store event!
 | 
					            // Store event!
 | 
				
			||||||
            const tags = await this.tagStore.getAllTagsForFeature(featureName);
 | 
					            const tags = await this.tagStore.getAllTagsForFeature(featureName);
 | 
				
			||||||
            const data = this.featureStrategyToPublic(strategy);
 | 
					            const data = this.featureStrategyToPublic(strategy);
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,19 @@ test('semver validation should fail partial semver', () => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('semver validation should fail with leading v', () => {
 | 
				
			||||||
 | 
					    const leadingV = 'v1.2.0';
 | 
				
			||||||
 | 
					    expect.assertions(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        validateSemver(leadingV);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					        expect(e.message).toBe(
 | 
				
			||||||
 | 
					            `the provided value is not a valid semver format. The value provided was: ${leadingV}`,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Legal values tests */
 | 
					/* Legal values tests */
 | 
				
			||||||
test('should fail validation if value does not exist in single legal value', () => {
 | 
					test('should fail validation if value does not exist in single legal value', () => {
 | 
				
			||||||
    const legalValues = ['100', '200', '300'];
 | 
					    const legalValues = ['100', '200', '300'];
 | 
				
			||||||
 | 
				
			|||||||
@ -16,9 +16,11 @@ export const validateString = async (value: unknown): Promise<void> => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const validateSemver = (value: unknown): void => {
 | 
					export const validateSemver = (value: unknown): void => {
 | 
				
			||||||
 | 
					    const cleanValue = semver.clean(value) === value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const result = semver.valid(value);
 | 
					    const result = semver.valid(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (result) return;
 | 
					    if (result && cleanValue) return;
 | 
				
			||||||
    throw new BadDataError(
 | 
					    throw new BadDataError(
 | 
				
			||||||
        `the provided value is not a valid semver format. The value provided was: ${value}`,
 | 
					        `the provided value is not a valid semver format. The value provided was: ${value}`,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user