All files / src/lib/services feature-tag-service.ts

100% Statements 23/23
100% Branches 1/1
100% Functions 5/5
100% Lines 23/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 9260x   60x 60x     60x                                             147x 147x 147x 147x       5x                 18x 18x 18x 18x   15x           15x       18x 18x   12x 12x 12x                             1x 1x                 60x  
import NotFoundError from '../error/notfound-error';
import { Logger } from '../logger';
import { nameSchema } from '../schema/feature-schema';
import { FEATURE_TAGGED, FEATURE_UNTAGGED, TAG_CREATED } from '../types/events';
import { IUnleashConfig } from '../types/option';
import { IUnleashStores } from '../types/stores';
import { tagSchema } from './tag-schema';
import { IFeatureTagStore } from '../types/stores/feature-tag-store';
import { IEventStore } from '../types/stores/event-store';
import { ITagStore } from '../types/stores/tag-store';
import { ITag } from '../types/model';
 
class FeatureTagService {
    private tagStore: ITagStore;
 
    private featureTagStore: IFeatureTagStore;
 
    private eventStore: IEventStore;
 
    private logger: Logger;
 
    constructor(
        {
            tagStore,
            featureTagStore,
            eventStore,
        }: Pick<IUnleashStores, 'tagStore' | 'featureTagStore' | 'eventStore'>,
        { getLogger }: Pick<IUnleashConfig, 'getLogger'>,
    ) {
        this.logger = getLogger('/services/feature-tag-service.ts');
        this.tagStore = tagStore;
        this.featureTagStore = featureTagStore;
        this.eventStore = eventStore;
    }
 
    async listTags(featureName: string): Promise<ITag[]> {
        return this.featureTagStore.getAllTagsForFeature(featureName);
    }
 
    // TODO: add project Id
    async addTag(
        featureName: string,
        tag: ITag,
        userName: string,
    ): Promise<ITag> {
        await nameSchema.validateAsync({ name: featureName });
        const validatedTag = await tagSchema.validateAsync(tag);
        await this.createTagIfNeeded(validatedTag, userName);
        await this.featureTagStore.tagFeature(featureName, validatedTag);
 
        await this.eventStore.store({
            type: FEATURE_TAGGED,
            createdBy: userName,
            featureName,
            data: validatedTag,
        });
        return validatedTag;
    }
 
    async createTagIfNeeded(tag: ITag, userName: string): Promise<void> {
        try {
            await this.tagStore.getTag(tag.type, tag.value);
        } catch (error) {
            if (error instanceof NotFoundError) {
                await this.tagStore.createTag(tag);
                await this.eventStore.store({
                    type: TAG_CREATED,
                    createdBy: userName,
                    data: tag,
                });
            }
        }
    }
 
    // TODO: add project Id
    async removeTag(
        featureName: string,
        tag: ITag,
        userName: string,
    ): Promise<void> {
        await this.featureTagStore.untagFeature(featureName, tag);
        await this.eventStore.store({
            type: FEATURE_UNTAGGED,
            createdBy: userName,
            featureName,
            data: tag,
        });
    }
}
 
export default FeatureTagService;