2021-07-07 10:46:50 +02:00
|
|
|
import { randomUUID } from 'crypto';
|
|
|
|
import {
|
|
|
|
FeatureToggleWithEnvironment,
|
2021-09-13 10:23:57 +02:00
|
|
|
IFeatureOverview,
|
2021-07-07 10:46:50 +02:00
|
|
|
IFeatureToggleClient,
|
|
|
|
IFeatureToggleQuery,
|
Complete open api schemas for project features controller (#1563)
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* bug fix
* bug fix
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* added emptyResponse, patch feature operation schemas and request
* added emptyResponse, patch feature operation schemas and request
* patch strategy
* patch strategy
* update strategy
* update strategy
* fix pr comment
* fix pr comments
* improvements
* added operationId to schema for better generation
* fix pr comment
* fix pr comment
* fix pr comment
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* Update response types to use inferred types
* Update addTag response status to 201
* refactor: move schema ref destructuring into createSchemaObject
* made serialize date handle deep objects
* made serialize date handle deep objects
* add `name` to IFeatureStrategy nad fix tests
* fix pr comments
* fix pr comments
* Add types to IAuthRequest
* Sync StrategySchema for FE and BE - into the rabbit hole
* Sync model with OAS spec
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* bug fix
* bug fix
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* added emptyResponse, patch feature operation schemas and request
* added emptyResponse, patch feature operation schemas and request
* patch strategy
* patch strategy
* update strategy
* update strategy
* fix pr comment
* fix pr comments
* improvements
* added operationId to schema for better generation
* fix pr comment
* fix pr comment
* fix pr comment
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* Update response types to use inferred types
* Update addTag response status to 201
* refactor: move schema ref destructuring into createSchemaObject
* made serialize date handle deep objects
* made serialize date handle deep objects
* add `name` to IFeatureStrategy nad fix tests
* fix pr comments
* fix pr comments
* Add types to IAuthRequest
* Sync StrategySchema for FE and BE - into the rabbit hole
* Sync model with OAS spec
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* bug fix
* bug fix
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* added emptyResponse, patch feature operation schemas and request
* added emptyResponse, patch feature operation schemas and request
* patch strategy
* patch strategy
* update strategy
* update strategy
* fix pr comment
* fix pr comments
* improvements
* added operationId to schema for better generation
* fix pr comment
* fix pr comment
* fix pr comment
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* Update response types to use inferred types
* Update addTag response status to 201
* refactor: move schema ref destructuring into createSchemaObject
* made serialize date handle deep objects
* made serialize date handle deep objects
* add `name` to IFeatureStrategy nad fix tests
* fix pr comments
* fix pr comments
* Add types to IAuthRequest
* Sync StrategySchema for FE and BE - into the rabbit hole
* Sync model with OAS spec
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* Completed OpenAPI Schemas for ProjectFeatures Controller
Completed OpenAPI Schemas for Feature Controller (tags)
* bug fix
* bug fix
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* fix merge conflicts, some refactoring
* added emptyResponse, patch feature operation schemas and request
* added emptyResponse, patch feature operation schemas and request
* patch strategy
* patch strategy
* update strategy
* update strategy
* fix pr comment
* fix pr comments
* improvements
* added operationId to schema for better generation
* fix pr comment
* fix pr comment
* fix pr comment
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* improvements to generated and dynamic types
* Update response types to use inferred types
* Update addTag response status to 201
* refactor: move schema ref destructuring into createSchemaObject
* made serialize date handle deep objects
* made serialize date handle deep objects
* add `name` to IFeatureStrategy nad fix tests
* fix pr comments
* fix pr comments
* Add types to IAuthRequest
* Sync StrategySchema for FE and BE - into the rabbit hole
* Sync model with OAS spec
* revert
* revert
* revert
* revert
* revert
* mapper
* revert
* revert
* revert
* remove serialize-dates.ts
* remove serialize-dates.ts
* remove serialize-dates.ts
* remove serialize-dates.ts
* remove serialize-dates.ts
* revert
* revert
* add mappers
* add mappers
* fix pr comments
* ignore report.json
* ignore report.json
* Route permission required
Co-authored-by: olav <mail@olav.io>
2022-05-18 15:17:09 +02:00
|
|
|
IFeatureStrategy,
|
|
|
|
FeatureToggle,
|
2021-07-07 10:46:50 +02:00
|
|
|
} from '../../lib/types/model';
|
|
|
|
import NotFoundError from '../../lib/error/notfound-error';
|
2021-08-12 15:04:37 +02:00
|
|
|
import { IFeatureStrategiesStore } from '../../lib/types/stores/feature-strategies-store';
|
2021-07-07 10:46:50 +02:00
|
|
|
|
|
|
|
interface ProjectEnvironment {
|
|
|
|
projectName: string;
|
|
|
|
environment: string;
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
export default class FakeFeatureStrategiesStore
|
|
|
|
implements IFeatureStrategiesStore
|
|
|
|
{
|
2021-07-07 10:46:50 +02:00
|
|
|
environmentAndFeature: Map<string, any[]> = new Map();
|
|
|
|
|
|
|
|
projectToEnvironment: ProjectEnvironment[] = [];
|
|
|
|
|
|
|
|
featureStrategies: IFeatureStrategy[] = [];
|
|
|
|
|
|
|
|
featureToggles: FeatureToggle[] = [];
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async createStrategyFeatureEnv(
|
2021-07-07 10:46:50 +02:00
|
|
|
strategyConfig: Omit<IFeatureStrategy, 'id' | 'createdAt'>,
|
|
|
|
): Promise<IFeatureStrategy> {
|
|
|
|
const newStrat = { ...strategyConfig, id: randomUUID() };
|
|
|
|
this.featureStrategies.push(newStrat);
|
|
|
|
return Promise.resolve(newStrat);
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
2021-07-07 10:46:50 +02:00
|
|
|
async createFeature(feature: any): Promise<void> {
|
|
|
|
this.featureToggles.push({
|
|
|
|
project: feature.project || 'default',
|
|
|
|
createdAt: new Date(),
|
2021-08-12 15:04:37 +02:00
|
|
|
archived: false,
|
2021-07-07 10:46:50 +02:00
|
|
|
...feature,
|
|
|
|
});
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async deleteFeatureStrategies(): Promise<void> {
|
|
|
|
this.featureStrategies = [];
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
async hasStrategy(id: string): Promise<boolean> {
|
|
|
|
return this.featureStrategies.some((s) => s.id === id);
|
|
|
|
}
|
|
|
|
|
|
|
|
async get(id: string): Promise<IFeatureStrategy> {
|
|
|
|
return this.featureStrategies.find((s) => s.id === id);
|
|
|
|
}
|
|
|
|
|
|
|
|
async exists(key: string): Promise<boolean> {
|
|
|
|
return this.featureStrategies.some((s) => s.id === key);
|
|
|
|
}
|
|
|
|
|
|
|
|
async delete(key: string): Promise<void> {
|
|
|
|
this.featureStrategies.splice(
|
|
|
|
this.featureStrategies.findIndex((s) => s.id === key),
|
|
|
|
1,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
async deleteAll(): Promise<void> {
|
|
|
|
this.featureStrategies = [];
|
|
|
|
}
|
|
|
|
|
2022-07-26 14:16:30 +02:00
|
|
|
// FIXME: implement
|
|
|
|
async updateSortOrder(id: string, sortOrder: number): Promise<void> {
|
|
|
|
const found = this.featureStrategies.find((item) => item.id === id);
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
found.sortOrder = sortOrder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
destroy(): void {
|
|
|
|
throw new Error('Method not implemented.');
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async removeAllStrategiesForFeatureEnv(
|
2021-07-07 10:46:50 +02:00
|
|
|
feature_name: string,
|
|
|
|
environment: string,
|
|
|
|
): Promise<void> {
|
|
|
|
const toRemove = this.featureStrategies.filter(
|
2021-08-12 15:04:37 +02:00
|
|
|
(fS) =>
|
2021-07-07 10:46:50 +02:00
|
|
|
fS.featureName === feature_name &&
|
|
|
|
fS.environment === environment,
|
|
|
|
);
|
|
|
|
this.featureStrategies = this.featureStrategies.filter(
|
2021-08-12 15:04:37 +02:00
|
|
|
(f) =>
|
2021-07-07 10:46:50 +02:00
|
|
|
!toRemove.some(
|
2021-08-12 15:04:37 +02:00
|
|
|
(r) =>
|
2021-07-07 10:46:50 +02:00
|
|
|
r.featureName === f.featureName &&
|
|
|
|
r.environment === f.environment,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async getAll(): Promise<IFeatureStrategy[]> {
|
|
|
|
return Promise.resolve(this.featureStrategies);
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async getStrategiesForFeatureEnv(
|
2021-07-07 10:46:50 +02:00
|
|
|
project_name: string,
|
|
|
|
feature_name: string,
|
|
|
|
environment: string,
|
|
|
|
): Promise<IFeatureStrategy[]> {
|
|
|
|
const rows = this.featureStrategies.filter(
|
2021-08-12 15:04:37 +02:00
|
|
|
(fS) =>
|
2021-09-13 10:23:57 +02:00
|
|
|
fS.projectId === project_name &&
|
2021-07-07 10:46:50 +02:00
|
|
|
fS.featureName === feature_name &&
|
|
|
|
fS.environment === environment,
|
|
|
|
);
|
|
|
|
return Promise.resolve(rows);
|
|
|
|
}
|
|
|
|
|
2022-10-28 09:29:00 +02:00
|
|
|
async getFeatureToggleForEnvironment(
|
|
|
|
featureName: string,
|
|
|
|
// eslint-disable-next-line
|
|
|
|
environment: string,
|
|
|
|
): Promise<FeatureToggleWithEnvironment> {
|
|
|
|
const toggle = this.featureToggles.find((f) => f.name === featureName);
|
|
|
|
if (toggle) {
|
|
|
|
return { ...toggle, environments: [] };
|
|
|
|
}
|
|
|
|
throw new NotFoundError(
|
|
|
|
`Could not find feature with name ${featureName}`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async getFeatureToggleWithEnvs(
|
2021-07-07 10:46:50 +02:00
|
|
|
featureName: string,
|
|
|
|
archived: boolean = false,
|
|
|
|
): Promise<FeatureToggleWithEnvironment> {
|
2021-08-12 15:04:37 +02:00
|
|
|
const toggle = this.featureToggles.find(
|
|
|
|
(f) => f.name === featureName && f.archived === archived,
|
|
|
|
);
|
2021-07-07 10:46:50 +02:00
|
|
|
if (toggle) {
|
2021-08-12 15:04:37 +02:00
|
|
|
return { ...toggle, environments: [] };
|
2021-07-07 10:46:50 +02:00
|
|
|
}
|
2021-08-12 15:04:37 +02:00
|
|
|
throw new NotFoundError(
|
|
|
|
`Could not find feature with name ${featureName}`,
|
2021-07-07 10:46:50 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async getFeatureOverview(
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
projectId: string,
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
archived: boolean,
|
|
|
|
): Promise<IFeatureOverview[]> {
|
|
|
|
return Promise.resolve([]);
|
|
|
|
}
|
|
|
|
|
2021-07-07 10:46:50 +02:00
|
|
|
async getFeatures(
|
|
|
|
featureQuery?: IFeatureToggleQuery,
|
|
|
|
archived: boolean = false,
|
|
|
|
): Promise<IFeatureToggleClient[]> {
|
2021-08-12 15:04:37 +02:00
|
|
|
const rows = this.featureToggles.filter((toggle) => {
|
2021-07-07 10:46:50 +02:00
|
|
|
if (featureQuery.namePrefix) {
|
|
|
|
if (featureQuery.project) {
|
|
|
|
return (
|
|
|
|
toggle.name.startsWith(featureQuery.namePrefix) &&
|
2022-04-06 08:11:41 +02:00
|
|
|
featureQuery.project.some((project) =>
|
|
|
|
project.includes(toggle.project),
|
|
|
|
)
|
2021-07-07 10:46:50 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return toggle.name.startsWith(featureQuery.namePrefix);
|
|
|
|
}
|
|
|
|
if (featureQuery.project) {
|
2022-04-06 08:11:41 +02:00
|
|
|
return featureQuery.project.some((project) =>
|
|
|
|
project.includes(toggle.project),
|
|
|
|
);
|
2021-07-07 10:46:50 +02:00
|
|
|
}
|
2021-08-12 15:04:37 +02:00
|
|
|
return toggle.archived === archived;
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-08-12 15:04:37 +02:00
|
|
|
const clientRows: IFeatureToggleClient[] = rows.map((t) => ({
|
2021-07-07 10:46:50 +02:00
|
|
|
...t,
|
|
|
|
enabled: true,
|
|
|
|
strategies: [],
|
|
|
|
description: t.description || '',
|
|
|
|
type: t.type || 'Release',
|
|
|
|
stale: t.stale || false,
|
|
|
|
variants: [],
|
|
|
|
}));
|
|
|
|
return Promise.resolve(clientRows);
|
|
|
|
}
|
|
|
|
|
|
|
|
async getStrategyById(id: string): Promise<IFeatureStrategy> {
|
2021-08-12 15:04:37 +02:00
|
|
|
const strat = this.featureStrategies.find((fS) => fS.id === id);
|
2021-07-07 10:46:50 +02:00
|
|
|
if (strat) {
|
|
|
|
return Promise.resolve(strat);
|
|
|
|
}
|
|
|
|
return Promise.reject(
|
|
|
|
new NotFoundError(`Could not find strategy with id ${id}`),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
async connectEnvironmentAndFeature(
|
|
|
|
feature_name: string,
|
|
|
|
environment: string,
|
|
|
|
enabled: boolean = false,
|
|
|
|
): Promise<void> {
|
|
|
|
if (!this.environmentAndFeature.has(environment)) {
|
|
|
|
this.environmentAndFeature.set(environment, []);
|
|
|
|
}
|
|
|
|
this.environmentAndFeature
|
|
|
|
.get(environment)
|
|
|
|
.push({ feature: feature_name, enabled });
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeEnvironmentForFeature(
|
|
|
|
feature_name: string,
|
|
|
|
environment: string,
|
|
|
|
): Promise<void> {
|
|
|
|
this.environmentAndFeature.set(
|
|
|
|
environment,
|
|
|
|
this.environmentAndFeature
|
|
|
|
.get(environment)
|
2021-08-12 15:04:37 +02:00
|
|
|
.filter((e) => e.featureName !== feature_name),
|
2021-07-07 10:46:50 +02:00
|
|
|
);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async disconnectEnvironmentFromProject(
|
|
|
|
environment: string,
|
|
|
|
project: string,
|
|
|
|
): Promise<void> {
|
|
|
|
this.projectToEnvironment = this.projectToEnvironment.filter(
|
2021-08-12 15:04:37 +02:00
|
|
|
(f) => f.projectName !== project && f.environment !== environment,
|
2021-07-07 10:46:50 +02:00
|
|
|
);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async updateStrategy(
|
|
|
|
id: string,
|
|
|
|
updates: Partial<IFeatureStrategy>,
|
|
|
|
): Promise<IFeatureStrategy> {
|
2021-08-12 15:04:37 +02:00
|
|
|
this.featureStrategies = this.featureStrategies.map((f) => {
|
2021-07-07 10:46:50 +02:00
|
|
|
if (f.id === id) {
|
|
|
|
return { ...f, ...updates };
|
|
|
|
}
|
|
|
|
return f;
|
|
|
|
});
|
2021-08-12 15:04:37 +02:00
|
|
|
return Promise.resolve(this.featureStrategies.find((f) => f.id === id));
|
2021-07-07 10:46:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async deleteConfigurationsForProjectAndEnvironment(
|
2021-08-12 15:04:37 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2021-07-07 10:46:50 +02:00
|
|
|
projectId: String,
|
2021-08-12 15:04:37 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2021-07-07 10:46:50 +02:00
|
|
|
environment: String,
|
|
|
|
): Promise<void> {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
async isEnvironmentEnabled(
|
|
|
|
featureName: string,
|
|
|
|
environment: string,
|
|
|
|
): Promise<boolean> {
|
|
|
|
const enabled =
|
|
|
|
this.environmentAndFeature
|
|
|
|
.get(environment)
|
2021-08-12 15:04:37 +02:00
|
|
|
?.find((f) => f.featureName === featureName)?.enabled || false;
|
2021-07-07 10:46:50 +02:00
|
|
|
return Promise.resolve(enabled);
|
|
|
|
}
|
|
|
|
|
2021-10-19 09:49:43 +02:00
|
|
|
async setProjectForStrategiesBelongingToFeature(
|
|
|
|
featureName: string,
|
|
|
|
newProjectId: string,
|
|
|
|
): Promise<void> {
|
|
|
|
this.featureStrategies = this.featureStrategies.map((f) => {
|
|
|
|
if (f.featureName === featureName) {
|
|
|
|
f.projectId = newProjectId;
|
|
|
|
}
|
|
|
|
return f;
|
|
|
|
});
|
|
|
|
return Promise.resolve(undefined);
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
async setEnvironmentEnabledStatus(
|
2021-07-07 10:46:50 +02:00
|
|
|
environment: string,
|
|
|
|
featureName: string,
|
|
|
|
enabled: boolean,
|
|
|
|
): Promise<boolean> {
|
|
|
|
return Promise.resolve(enabled);
|
|
|
|
}
|
2022-03-29 14:59:14 +02:00
|
|
|
|
|
|
|
getStrategiesBySegment(): Promise<IFeatureStrategy[]> {
|
|
|
|
throw new Error('Method not implemented.');
|
|
|
|
}
|
2021-07-07 10:46:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = FakeFeatureStrategiesStore;
|