mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-29 01:15:48 +02:00
chore: refactor segments to stop depending on the implementation (#3315)
## About the changes - Introducing ISegmentService interface to decouple from the actual implementation - Moving UpsertSegmentSchema to OSS to be able to use types - Added comments where our code is coupled with segments just to highlight and have a conversation about some use cases if needed, but they can be removed before merging - Removed segment service from some project features as it was not used
This commit is contained in:
parent
69a11bae8c
commit
1d0bc833b3
@ -20,6 +20,7 @@ import { DEFAULT_ENV } from '../../util';
|
|||||||
import {
|
import {
|
||||||
ContextFieldSchema,
|
ContextFieldSchema,
|
||||||
ImportTogglesSchema,
|
ImportTogglesSchema,
|
||||||
|
UpsertSegmentSchema,
|
||||||
VariantsSchema,
|
VariantsSchema,
|
||||||
} from '../../openapi';
|
} from '../../openapi';
|
||||||
import User from '../../types/user';
|
import User from '../../types/user';
|
||||||
@ -117,7 +118,7 @@ const createProject = async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createSegment = (postData: object): Promise<ISegment> => {
|
const createSegment = (postData: UpsertSegmentSchema): Promise<ISegment> => {
|
||||||
return app.services.segmentService.create(postData, {
|
return app.services.segmentService.create(postData, {
|
||||||
email: 'test@example.com',
|
email: 'test@example.com',
|
||||||
});
|
});
|
||||||
|
@ -117,6 +117,7 @@ import {
|
|||||||
updateTagTypeSchema,
|
updateTagTypeSchema,
|
||||||
updateUserSchema,
|
updateUserSchema,
|
||||||
upsertContextFieldSchema,
|
upsertContextFieldSchema,
|
||||||
|
upsertSegmentSchema,
|
||||||
upsertStrategySchema,
|
upsertStrategySchema,
|
||||||
userSchema,
|
userSchema,
|
||||||
usersGroupsBaseSchema,
|
usersGroupsBaseSchema,
|
||||||
@ -272,6 +273,7 @@ export const schemas = {
|
|||||||
updateUserSchema,
|
updateUserSchema,
|
||||||
updateTagsSchema,
|
updateTagsSchema,
|
||||||
upsertContextFieldSchema,
|
upsertContextFieldSchema,
|
||||||
|
upsertSegmentSchema,
|
||||||
upsertStrategySchema,
|
upsertStrategySchema,
|
||||||
userSchema,
|
userSchema,
|
||||||
usersGroupsBaseSchema,
|
usersGroupsBaseSchema,
|
||||||
|
@ -131,4 +131,5 @@ export * from './import-toggles-validate-schema';
|
|||||||
export * from './import-toggles-schema';
|
export * from './import-toggles-schema';
|
||||||
export * from './stickiness-schema';
|
export * from './stickiness-schema';
|
||||||
export * from './tags-bulk-add-schema';
|
export * from './tags-bulk-add-schema';
|
||||||
|
export * from './upsert-segment-schema';
|
||||||
export * from './batch-features-schema';
|
export * from './batch-features-schema';
|
||||||
|
34
src/lib/openapi/spec/upsert-segment-schema.ts
Normal file
34
src/lib/openapi/spec/upsert-segment-schema.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
import { constraintSchema } from './constraint-schema';
|
||||||
|
|
||||||
|
export const upsertSegmentSchema = {
|
||||||
|
$id: '#/components/schemas/upsertSegmentSchema',
|
||||||
|
type: 'object',
|
||||||
|
required: ['name', 'constraints'],
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
type: 'string',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
constraints: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
$ref: '#/components/schemas/constraintSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
schemas: {
|
||||||
|
constraintSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type UpsertSegmentSchema = FromSchema<typeof upsertSegmentSchema>;
|
@ -139,7 +139,7 @@ export class ProxyRepository
|
|||||||
|
|
||||||
private async segmentsForToken(): Promise<Segment[]> {
|
private async segmentsForToken(): Promise<Segment[]> {
|
||||||
return mapSegmentsForClient(
|
return mapSegmentsForClient(
|
||||||
await this.services.segmentService.getAll(),
|
await this.services.segmentService.getAll(), // TODO coupled with enterprise feature
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,11 +39,7 @@ import {
|
|||||||
UpdateFeatureSchema,
|
UpdateFeatureSchema,
|
||||||
UpdateFeatureStrategySchema,
|
UpdateFeatureStrategySchema,
|
||||||
} from '../../../openapi';
|
} from '../../../openapi';
|
||||||
import {
|
import { OpenApiService, FeatureToggleService } from '../../../services';
|
||||||
OpenApiService,
|
|
||||||
SegmentService,
|
|
||||||
FeatureToggleService,
|
|
||||||
} from '../../../services';
|
|
||||||
import { querySchema } from '../../../schema/feature-schema';
|
import { querySchema } from '../../../schema/feature-schema';
|
||||||
import NotFoundError from '../../../error/notfound-error';
|
import NotFoundError from '../../../error/notfound-error';
|
||||||
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
|
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
|
||||||
@ -97,24 +93,17 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
|
|
||||||
private openApiService: OpenApiService;
|
private openApiService: OpenApiService;
|
||||||
|
|
||||||
private segmentService: SegmentService;
|
|
||||||
|
|
||||||
private flagResolver: IFlagResolver;
|
private flagResolver: IFlagResolver;
|
||||||
|
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{
|
{ featureToggleServiceV2, openApiService }: ProjectFeaturesServices,
|
||||||
featureToggleServiceV2,
|
|
||||||
openApiService,
|
|
||||||
segmentService,
|
|
||||||
}: ProjectFeaturesServices,
|
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.featureService = featureToggleServiceV2;
|
this.featureService = featureToggleServiceV2;
|
||||||
this.openApiService = openApiService;
|
this.openApiService = openApiService;
|
||||||
this.segmentService = segmentService;
|
|
||||||
this.flagResolver = config.flagResolver;
|
this.flagResolver = config.flagResolver;
|
||||||
this.logger = config.getLogger('/admin-api/project/features.ts');
|
this.logger = config.getLogger('/admin-api/project/features.ts');
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import NotFoundError from '../../error/notfound-error';
|
|||||||
import { IAuthRequest } from '../unleash-types';
|
import { IAuthRequest } from '../unleash-types';
|
||||||
import ApiUser from '../../types/api-user';
|
import ApiUser from '../../types/api-user';
|
||||||
import { ALL, isAllProjects } from '../../types/models/api-token';
|
import { ALL, isAllProjects } from '../../types/models/api-token';
|
||||||
import { SegmentService } from '../../services/segment-service';
|
|
||||||
import { FeatureConfigurationClient } from '../../types/stores/feature-strategies-store';
|
import { FeatureConfigurationClient } from '../../types/stores/feature-strategies-store';
|
||||||
import { ClientSpecService } from '../../services/client-spec-service';
|
import { ClientSpecService } from '../../services/client-spec-service';
|
||||||
import { OpenApiService } from '../../services/openapi-service';
|
import { OpenApiService } from '../../services/openapi-service';
|
||||||
@ -25,6 +24,7 @@ import {
|
|||||||
clientFeaturesSchema,
|
clientFeaturesSchema,
|
||||||
ClientFeaturesSchema,
|
ClientFeaturesSchema,
|
||||||
} from '../../openapi/spec/client-features-schema';
|
} from '../../openapi/spec/client-features-schema';
|
||||||
|
import { ISegmentService } from 'lib/segments/segment-service-interface';
|
||||||
|
|
||||||
const version = 2;
|
const version = 2;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ export default class FeatureController extends Controller {
|
|||||||
|
|
||||||
private featureToggleServiceV2: FeatureToggleService;
|
private featureToggleServiceV2: FeatureToggleService;
|
||||||
|
|
||||||
private segmentService: SegmentService;
|
private segmentService: ISegmentService;
|
||||||
|
|
||||||
private clientSpecService: ClientSpecService;
|
private clientSpecService: ClientSpecService;
|
||||||
|
|
||||||
|
29
src/lib/segments/segment-service-interface.ts
Normal file
29
src/lib/segments/segment-service-interface.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { UpsertSegmentSchema } from 'lib/openapi';
|
||||||
|
import { ISegment, IUser } from 'lib/types';
|
||||||
|
|
||||||
|
export interface ISegmentService {
|
||||||
|
updateStrategySegments: (
|
||||||
|
strategyId: string,
|
||||||
|
segmentIds: number[],
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
|
addToStrategy(id: number, strategyId: string): Promise<void>;
|
||||||
|
|
||||||
|
getByStrategy(strategyId: string): Promise<ISegment[]>;
|
||||||
|
|
||||||
|
getActive(): Promise<ISegment[]>;
|
||||||
|
|
||||||
|
getAll(): Promise<ISegment[]>;
|
||||||
|
|
||||||
|
create(
|
||||||
|
data: UpsertSegmentSchema,
|
||||||
|
user: Partial<Pick<IUser, 'username' | 'email'>>,
|
||||||
|
): Promise<ISegment>;
|
||||||
|
|
||||||
|
delete(id: number, user: IUser): Promise<void>;
|
||||||
|
|
||||||
|
cloneStrategySegments(
|
||||||
|
sourceStrategyId: string,
|
||||||
|
targetStrategyId: string,
|
||||||
|
): Promise<void>;
|
||||||
|
}
|
@ -71,7 +71,6 @@ import {
|
|||||||
} from '../util/validators/constraint-types';
|
} from '../util/validators/constraint-types';
|
||||||
import { IContextFieldStore } from 'lib/types/stores/context-field-store';
|
import { IContextFieldStore } from 'lib/types/stores/context-field-store';
|
||||||
import { Saved, Unsaved } from '../types/saved';
|
import { Saved, Unsaved } from '../types/saved';
|
||||||
import { SegmentService } from './segment-service';
|
|
||||||
import { SetStrategySortOrderSchema } from 'lib/openapi/spec/set-strategy-sort-order-schema';
|
import { SetStrategySortOrderSchema } from 'lib/openapi/spec/set-strategy-sort-order-schema';
|
||||||
import { getDefaultStrategy } from '../util/feature-evaluator/helpers';
|
import { getDefaultStrategy } from '../util/feature-evaluator/helpers';
|
||||||
import { AccessService } from './access-service';
|
import { AccessService } from './access-service';
|
||||||
@ -83,6 +82,7 @@ import {
|
|||||||
import NoAccessError from '../error/no-access-error';
|
import NoAccessError from '../error/no-access-error';
|
||||||
import { IFeatureProjectUserParams } from '../routes/admin-api/project/project-features';
|
import { IFeatureProjectUserParams } from '../routes/admin-api/project/project-features';
|
||||||
import { unique } from '../util/unique';
|
import { unique } from '../util/unique';
|
||||||
|
import { ISegmentService } from 'lib/segments/segment-service-interface';
|
||||||
|
|
||||||
interface IFeatureContext {
|
interface IFeatureContext {
|
||||||
featureName: string;
|
featureName: string;
|
||||||
@ -124,7 +124,7 @@ class FeatureToggleService {
|
|||||||
|
|
||||||
private contextFieldStore: IContextFieldStore;
|
private contextFieldStore: IContextFieldStore;
|
||||||
|
|
||||||
private segmentService: SegmentService;
|
private segmentService: ISegmentService;
|
||||||
|
|
||||||
private accessService: AccessService;
|
private accessService: AccessService;
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ class FeatureToggleService {
|
|||||||
getLogger,
|
getLogger,
|
||||||
flagResolver,
|
flagResolver,
|
||||||
}: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
}: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
||||||
segmentService: SegmentService,
|
segmentService: ISegmentService,
|
||||||
accessService: AccessService,
|
accessService: AccessService,
|
||||||
) {
|
) {
|
||||||
this.logger = getLogger('services/feature-toggle-service.ts');
|
this.logger = getLogger('services/feature-toggle-service.ts');
|
||||||
@ -375,7 +375,10 @@ class FeatureToggleService {
|
|||||||
const { featureName, projectId, environment } = context;
|
const { featureName, projectId, environment } = context;
|
||||||
await this.validateFeatureContext(context);
|
await this.validateFeatureContext(context);
|
||||||
|
|
||||||
if (strategyConfig.constraints?.length > 0) {
|
if (
|
||||||
|
strategyConfig.constraints &&
|
||||||
|
strategyConfig.constraints.length > 0
|
||||||
|
) {
|
||||||
strategyConfig.constraints = await this.validateConstraints(
|
strategyConfig.constraints = await this.validateConstraints(
|
||||||
strategyConfig.constraints,
|
strategyConfig.constraints,
|
||||||
);
|
);
|
||||||
@ -406,7 +409,7 @@ class FeatureToggleService {
|
|||||||
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
||||||
const segments = await this.segmentService.getByStrategy(
|
const segments = await this.segmentService.getByStrategy(
|
||||||
newFeatureStrategy.id,
|
newFeatureStrategy.id,
|
||||||
);
|
); // TODO coupled with enterprise feature
|
||||||
const strategy = this.featureStrategyToPublic(
|
const strategy = this.featureStrategyToPublic(
|
||||||
newFeatureStrategy,
|
newFeatureStrategy,
|
||||||
segments,
|
segments,
|
||||||
@ -468,7 +471,7 @@ class FeatureToggleService {
|
|||||||
this.validateFeatureStrategyContext(existingStrategy, context);
|
this.validateFeatureStrategyContext(existingStrategy, context);
|
||||||
|
|
||||||
if (existingStrategy.id === id) {
|
if (existingStrategy.id === id) {
|
||||||
if (updates.constraints?.length > 0) {
|
if (updates.constraints && updates.constraints.length > 0) {
|
||||||
updates.constraints = await this.validateConstraints(
|
updates.constraints = await this.validateConstraints(
|
||||||
updates.constraints,
|
updates.constraints,
|
||||||
);
|
);
|
||||||
@ -488,7 +491,7 @@ class FeatureToggleService {
|
|||||||
|
|
||||||
const segments = await this.segmentService.getByStrategy(
|
const segments = await this.segmentService.getByStrategy(
|
||||||
strategy.id,
|
strategy.id,
|
||||||
);
|
); // TODO coupled with enterprise feature
|
||||||
|
|
||||||
// Store event!
|
// Store event!
|
||||||
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
||||||
@ -534,7 +537,7 @@ class FeatureToggleService {
|
|||||||
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
const tags = await this.tagStore.getAllTagsForFeature(featureName);
|
||||||
const segments = await this.segmentService.getByStrategy(
|
const segments = await this.segmentService.getByStrategy(
|
||||||
strategy.id,
|
strategy.id,
|
||||||
);
|
); // TODO coupled with enterprise feature
|
||||||
const data = this.featureStrategyToPublic(strategy, segments);
|
const data = this.featureStrategyToPublic(strategy, segments);
|
||||||
const preData = this.featureStrategyToPublic(
|
const preData = this.featureStrategyToPublic(
|
||||||
existingStrategy,
|
existingStrategy,
|
||||||
@ -633,7 +636,7 @@ class FeatureToggleService {
|
|||||||
const segments =
|
const segments =
|
||||||
(await this.segmentService.getByStrategy(strat.id)).map(
|
(await this.segmentService.getByStrategy(strat.id)).map(
|
||||||
(segment) => segment.id,
|
(segment) => segment.id,
|
||||||
) ?? [];
|
) ?? []; // TODO coupled with enterprise feature
|
||||||
result.push({
|
result.push({
|
||||||
id: strat.id,
|
id: strat.id,
|
||||||
name: strat.strategyName,
|
name: strat.strategyName,
|
||||||
@ -950,7 +953,7 @@ class FeatureToggleService {
|
|||||||
strategyId,
|
strategyId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const segments = await this.segmentService.getByStrategy(strategyId);
|
const segments = await this.segmentService.getByStrategy(strategyId); // TODO coupled with enterprise feature
|
||||||
let result: Saved<IStrategyConfig> = {
|
let result: Saved<IStrategyConfig> = {
|
||||||
id: strategy.id,
|
id: strategy.id,
|
||||||
name: strategy.strategyName,
|
name: strategy.strategyName,
|
||||||
|
@ -138,7 +138,7 @@ export const createServices = (
|
|||||||
const versionService = new VersionService(stores, config);
|
const versionService = new VersionService(stores, config);
|
||||||
const healthService = new HealthService(stores, config);
|
const healthService = new HealthService(stores, config);
|
||||||
const userFeedbackService = new UserFeedbackService(stores, config);
|
const userFeedbackService = new UserFeedbackService(stores, config);
|
||||||
const segmentService = new SegmentService(stores, config);
|
const segmentService = new SegmentService(stores, config); // TODO coupled with enterprise feature
|
||||||
const featureToggleServiceV2 = new FeatureToggleService(
|
const featureToggleServiceV2 = new FeatureToggleService(
|
||||||
stores,
|
stores,
|
||||||
config,
|
config,
|
||||||
|
@ -193,7 +193,7 @@ export class InstanceStatsService {
|
|||||||
this.groupStore.count(),
|
this.groupStore.count(),
|
||||||
this.roleStore.count(),
|
this.roleStore.count(),
|
||||||
this.environmentStore.count(),
|
this.environmentStore.count(),
|
||||||
this.segmentStore.count(),
|
this.segmentStore.count(), // TODO coupled with enterprise feature
|
||||||
this.strategyStore.count(),
|
this.strategyStore.count(),
|
||||||
this.hasSAML(),
|
this.hasSAML(),
|
||||||
this.hasOIDC(),
|
this.hasOIDC(),
|
||||||
|
@ -8,14 +8,14 @@ import { IUnleashConfig } from 'lib/types';
|
|||||||
import { offlineUnleashClient } from '../util/offline-unleash-client';
|
import { offlineUnleashClient } from '../util/offline-unleash-client';
|
||||||
import { FeatureInterface } from 'lib/util/feature-evaluator/feature';
|
import { FeatureInterface } from 'lib/util/feature-evaluator/feature';
|
||||||
import { FeatureStrategiesEvaluationResult } from 'lib/util/feature-evaluator/client';
|
import { FeatureStrategiesEvaluationResult } from 'lib/util/feature-evaluator/client';
|
||||||
import { SegmentService } from './segment-service';
|
import { ISegmentService } from 'lib/segments/segment-service-interface';
|
||||||
|
|
||||||
export class PlaygroundService {
|
export class PlaygroundService {
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
|
|
||||||
private readonly featureToggleService: FeatureToggleService;
|
private readonly featureToggleService: FeatureToggleService;
|
||||||
|
|
||||||
private readonly segmentService: SegmentService;
|
private readonly segmentService: ISegmentService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
|
@ -14,8 +14,9 @@ import {
|
|||||||
import User from '../types/user';
|
import User from '../types/user';
|
||||||
import { IFeatureStrategiesStore } from '../types/stores/feature-strategies-store';
|
import { IFeatureStrategiesStore } from '../types/stores/feature-strategies-store';
|
||||||
import BadDataError from '../error/bad-data-error';
|
import BadDataError from '../error/bad-data-error';
|
||||||
|
import { ISegmentService } from '../segments/segment-service-interface';
|
||||||
|
|
||||||
export class SegmentService {
|
export class SegmentService implements ISegmentService {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
private segmentStore: ISegmentStore;
|
private segmentStore: ISegmentStore;
|
||||||
|
@ -20,7 +20,6 @@ function getSetup() {
|
|||||||
return {
|
return {
|
||||||
stateService: new StateService(stores, {
|
stateService: new StateService(stores, {
|
||||||
getLogger,
|
getLogger,
|
||||||
flagResolver: { isEnabled: () => true, getAll: () => ({}) },
|
|
||||||
}),
|
}),
|
||||||
stores,
|
stores,
|
||||||
};
|
};
|
||||||
@ -65,10 +64,6 @@ async function setupV3VariantsCompatibilityScenario(
|
|||||||
return {
|
return {
|
||||||
stateService: new StateService(stores, {
|
stateService: new StateService(stores, {
|
||||||
getLogger,
|
getLogger,
|
||||||
flagResolver: {
|
|
||||||
isEnabled: () => true,
|
|
||||||
getAll: () => ({}),
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
stores,
|
stores,
|
||||||
};
|
};
|
||||||
@ -579,7 +574,6 @@ test('exporting to new format works', async () => {
|
|||||||
const stores = createStores();
|
const stores = createStores();
|
||||||
const stateService = new StateService(stores, {
|
const stateService = new StateService(stores, {
|
||||||
getLogger,
|
getLogger,
|
||||||
flagResolver: { isEnabled: () => true, getAll: () => ({}) },
|
|
||||||
});
|
});
|
||||||
await stores.projectStore.create({
|
await stores.projectStore.create({
|
||||||
id: 'fancy',
|
id: 'fancy',
|
||||||
|
@ -50,7 +50,6 @@ import { DEFAULT_ENV } from '../util/constants';
|
|||||||
import { GLOBAL_ENV } from '../types/environment';
|
import { GLOBAL_ENV } from '../types/environment';
|
||||||
import { ISegmentStore } from '../types/stores/segment-store';
|
import { ISegmentStore } from '../types/stores/segment-store';
|
||||||
import { PartialSome } from '../types/partial';
|
import { PartialSome } from '../types/partial';
|
||||||
import { IFlagResolver } from 'lib/types';
|
|
||||||
|
|
||||||
export interface IBackupOption {
|
export interface IBackupOption {
|
||||||
includeFeatureToggles: boolean;
|
includeFeatureToggles: boolean;
|
||||||
@ -93,14 +92,9 @@ export default class StateService {
|
|||||||
|
|
||||||
private segmentStore: ISegmentStore;
|
private segmentStore: ISegmentStore;
|
||||||
|
|
||||||
private flagResolver: IFlagResolver;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
{
|
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
||||||
getLogger,
|
|
||||||
flagResolver,
|
|
||||||
}: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
|
||||||
) {
|
) {
|
||||||
this.eventStore = stores.eventStore;
|
this.eventStore = stores.eventStore;
|
||||||
this.toggleStore = stores.featureToggleStore;
|
this.toggleStore = stores.featureToggleStore;
|
||||||
@ -113,7 +107,6 @@ export default class StateService {
|
|||||||
this.featureTagStore = stores.featureTagStore;
|
this.featureTagStore = stores.featureTagStore;
|
||||||
this.environmentStore = stores.environmentStore;
|
this.environmentStore = stores.environmentStore;
|
||||||
this.segmentStore = stores.segmentStore;
|
this.segmentStore = stores.segmentStore;
|
||||||
this.flagResolver = flagResolver;
|
|
||||||
this.logger = getLogger('services/state-service.js');
|
this.logger = getLogger('services/state-service.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import FeatureTagService from '../services/feature-tag-service';
|
|||||||
import ProjectHealthService from '../services/project-health-service';
|
import ProjectHealthService from '../services/project-health-service';
|
||||||
import ClientMetricsServiceV2 from '../services/client-metrics/metrics-service-v2';
|
import ClientMetricsServiceV2 from '../services/client-metrics/metrics-service-v2';
|
||||||
import UserSplashService from '../services/user-splash-service';
|
import UserSplashService from '../services/user-splash-service';
|
||||||
import { SegmentService } from '../services/segment-service';
|
|
||||||
import { OpenApiService } from '../services/openapi-service';
|
import { OpenApiService } from '../services/openapi-service';
|
||||||
import { ClientSpecService } from '../services/client-spec-service';
|
import { ClientSpecService } from '../services/client-spec-service';
|
||||||
import { PlaygroundService } from 'lib/services/playground-service';
|
import { PlaygroundService } from 'lib/services/playground-service';
|
||||||
@ -41,6 +40,7 @@ import { AccountService } from '../services/account-service';
|
|||||||
import { SchedulerService } from '../services/scheduler-service';
|
import { SchedulerService } from '../services/scheduler-service';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import ExportImportService from '../features/export-import-toggles/export-import-service';
|
import ExportImportService from '../features/export-import-toggles/export-import-service';
|
||||||
|
import { ISegmentService } from 'lib/segments/segment-service-interface';
|
||||||
|
|
||||||
export interface IUnleashServices {
|
export interface IUnleashServices {
|
||||||
accessService: AccessService;
|
accessService: AccessService;
|
||||||
@ -76,7 +76,7 @@ export interface IUnleashServices {
|
|||||||
userService: UserService;
|
userService: UserService;
|
||||||
versionService: VersionService;
|
versionService: VersionService;
|
||||||
userSplashService: UserSplashService;
|
userSplashService: UserSplashService;
|
||||||
segmentService: SegmentService;
|
segmentService: ISegmentService;
|
||||||
openApiService: OpenApiService;
|
openApiService: OpenApiService;
|
||||||
clientSpecService: ClientSpecService;
|
clientSpecService: ClientSpecService;
|
||||||
patService: PatService;
|
patService: PatService;
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
} from '../../../../lib/util/segments';
|
} from '../../../../lib/util/segments';
|
||||||
import { collectIds } from '../../../../lib/util/collect-ids';
|
import { collectIds } from '../../../../lib/util/collect-ids';
|
||||||
import { arraysHaveSameItems } from '../../../../lib/util/arraysHaveSameItems';
|
import { arraysHaveSameItems } from '../../../../lib/util/arraysHaveSameItems';
|
||||||
|
import { UpsertSegmentSchema } from 'lib/openapi';
|
||||||
|
|
||||||
let db: ITestDb;
|
let db: ITestDb;
|
||||||
let app: IUnleashTest;
|
let app: IUnleashTest;
|
||||||
@ -39,7 +40,7 @@ const fetchClientFeatures = (): Promise<IFeatureToggleClient[]> => {
|
|||||||
.then((res) => res.body.features);
|
.then((res) => res.body.features);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createSegment = (postData: object): Promise<unknown> => {
|
const createSegment = (postData: UpsertSegmentSchema): Promise<unknown> => {
|
||||||
return app.services.segmentService.create(postData, {
|
return app.services.segmentService.create(postData, {
|
||||||
email: 'test@example.com',
|
email: 'test@example.com',
|
||||||
});
|
});
|
||||||
|
@ -3993,6 +3993,32 @@ Stats are divided into current and previous **windows**.
|
|||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
},
|
},
|
||||||
|
"upsertSegmentSchema": {
|
||||||
|
"properties": {
|
||||||
|
"constraints": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/constraintSchema",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"constraints",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
"upsertStrategySchema": {
|
"upsertStrategySchema": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"description": {
|
"description": {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
ISegment,
|
ISegment,
|
||||||
} from '../../../lib/types/model';
|
} from '../../../lib/types/model';
|
||||||
import { IUnleashTest, setupApp } from '../helpers/test-helper';
|
import { IUnleashTest, setupApp } from '../helpers/test-helper';
|
||||||
|
import { UpsertSegmentSchema } from 'lib/openapi';
|
||||||
|
|
||||||
interface ISeedSegmentSpec {
|
interface ISeedSegmentSpec {
|
||||||
featuresCount: number;
|
featuresCount: number;
|
||||||
@ -41,7 +42,7 @@ const fetchFeatures = (app: IUnleashTest): Promise<IFeatureToggleClient[]> => {
|
|||||||
|
|
||||||
const createSegment = (
|
const createSegment = (
|
||||||
app: IUnleashTest,
|
app: IUnleashTest,
|
||||||
postData: object,
|
postData: UpsertSegmentSchema,
|
||||||
): Promise<unknown> => {
|
): Promise<unknown> => {
|
||||||
const user = { email: 'test@example.com' } as User;
|
const user = { email: 'test@example.com' } as User;
|
||||||
return app.services.segmentService.create(postData, user);
|
return app.services.segmentService.create(postData, user);
|
||||||
@ -86,7 +87,7 @@ const seedConstraints = (spec: ISeedSegmentSpec): IConstraint[] => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const seedSegments = (spec: ISeedSegmentSpec): Partial<ISegment>[] => {
|
const seedSegments = (spec: ISeedSegmentSpec): UpsertSegmentSchema[] => {
|
||||||
return Array.from({ length: spec.segmentsPerFeature }).map((v, i) => {
|
return Array.from({ length: spec.segmentsPerFeature }).map((v, i) => {
|
||||||
return {
|
return {
|
||||||
name: `${seedSchema}_segment_${i}`,
|
name: `${seedSchema}_segment_${i}`,
|
||||||
|
@ -11,11 +11,12 @@ import { GroupService } from '../../../lib/services/group-service';
|
|||||||
import EnvironmentService from '../../../lib/services/environment-service';
|
import EnvironmentService from '../../../lib/services/environment-service';
|
||||||
import { NoAccessError } from '../../../lib/error';
|
import { NoAccessError } from '../../../lib/error';
|
||||||
import { SKIP_CHANGE_REQUEST } from '../../../lib/types';
|
import { SKIP_CHANGE_REQUEST } from '../../../lib/types';
|
||||||
|
import { ISegmentService } from '../../../lib/segments/segment-service-interface';
|
||||||
|
|
||||||
let stores;
|
let stores;
|
||||||
let db;
|
let db;
|
||||||
let service: FeatureToggleService;
|
let service: FeatureToggleService;
|
||||||
let segmentService: SegmentService;
|
let segmentService: ISegmentService;
|
||||||
let environmentService: EnvironmentService;
|
let environmentService: EnvironmentService;
|
||||||
let unleashConfig;
|
let unleashConfig;
|
||||||
|
|
||||||
|
@ -20,12 +20,13 @@ import { playgroundStrategyEvaluation } from '../../../lib/openapi/spec/playgrou
|
|||||||
import { PlaygroundSegmentSchema } from 'lib/openapi/spec/playground-segment-schema';
|
import { PlaygroundSegmentSchema } from 'lib/openapi/spec/playground-segment-schema';
|
||||||
import { GroupService } from '../../../lib/services/group-service';
|
import { GroupService } from '../../../lib/services/group-service';
|
||||||
import { AccessService } from '../../../lib/services/access-service';
|
import { AccessService } from '../../../lib/services/access-service';
|
||||||
|
import { ISegmentService } from '../../../lib/segments/segment-service-interface';
|
||||||
|
|
||||||
let stores: IUnleashStores;
|
let stores: IUnleashStores;
|
||||||
let db: ITestDb;
|
let db: ITestDb;
|
||||||
let service: PlaygroundService;
|
let service: PlaygroundService;
|
||||||
let featureToggleService: FeatureToggleService;
|
let featureToggleService: FeatureToggleService;
|
||||||
let segmentService: SegmentService;
|
let segmentService: ISegmentService;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const config = createTestConfig();
|
const config = createTestConfig();
|
||||||
@ -147,7 +148,7 @@ export const seedDatabaseForPlaygroundTest = async (
|
|||||||
featureName: feature.name,
|
featureName: feature.name,
|
||||||
environment,
|
environment,
|
||||||
strategyName: strategy.name,
|
strategyName: strategy.name,
|
||||||
projectId: feature.project,
|
projectId: feature.project!,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -156,7 +157,7 @@ export const seedDatabaseForPlaygroundTest = async (
|
|||||||
strategySegments.map((segmentId) =>
|
strategySegments.map((segmentId) =>
|
||||||
database.stores.segmentStore.addToStrategy(
|
database.stores.segmentStore.addToStrategy(
|
||||||
segmentId,
|
segmentId,
|
||||||
strategy.id,
|
strategy.id!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user