1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-24 01:18:01 +02:00

docs: Events tag (#4152)

### What
This PR adds documentation for our endpoints that are covered by our
"Events" tag. It also adds a type for all valid events, and then uses
this as valid values for type argument.
This commit is contained in:
Christopher Kolstad 2023-07-06 10:57:09 +02:00 committed by GitHub
parent 51ffe02cfd
commit b04545c25f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 360 additions and 118 deletions

View File

@ -1,4 +1,9 @@
import { IEvent, IBaseEvent, SEGMENT_UPDATED } from '../types/events'; import {
IEvent,
IBaseEvent,
SEGMENT_UPDATED,
IEventType,
} from '../types/events';
import { LogProvider, Logger } from '../logger'; import { LogProvider, Logger } from '../logger';
import { IEventStore } from '../types/stores/event-store'; import { IEventStore } from '../types/stores/event-store';
import { ITag } from '../types/model'; import { ITag } from '../types/model';
@ -359,7 +364,7 @@ class EventStore implements IEventStore {
rowToEvent(row: IEventTable): IEvent { rowToEvent(row: IEventTable): IEvent {
return { return {
id: row.id, id: row.id,
type: row.type, type: row.type as IEventType,
createdBy: row.created_by, createdBy: row.created_by,
createdAt: row.created_at, createdAt: row.created_at,
data: row.data, data: row.data,

View File

@ -97,10 +97,7 @@ const metaRules: Rule[] = [
'createInvitedUserSchema', 'createInvitedUserSchema',
'environmentsSchema', 'environmentsSchema',
'environmentsProjectSchema', 'environmentsProjectSchema',
'eventSchema',
'eventsSchema',
'featureEnvironmentSchema', 'featureEnvironmentSchema',
'featureEventsSchema',
'featureSchema', 'featureSchema',
'featuresSchema', 'featuresSchema',
'featureStrategySegmentSchema', 'featureStrategySegmentSchema',
@ -126,7 +123,6 @@ const metaRules: Rule[] = [
'resetPasswordSchema', 'resetPasswordSchema',
'requestsPerSecondSchema', 'requestsPerSecondSchema',
'sdkContextSchema', 'sdkContextSchema',
'searchEventsSchema',
'setUiConfigSchema', 'setUiConfigSchema',
'splashSchema', 'splashSchema',
'stateSchema', 'stateSchema',
@ -169,9 +165,6 @@ const metaRules: Rule[] = [
'createInvitedUserSchema', 'createInvitedUserSchema',
'dateSchema', 'dateSchema',
'environmentsSchema', 'environmentsSchema',
'eventSchema',
'eventsSchema',
'featureEventsSchema',
'featureSchema', 'featureSchema',
'featuresSchema', 'featuresSchema',
'featureStrategySegmentSchema', 'featureStrategySegmentSchema',

View File

@ -1,51 +1,152 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { tagSchema } from './tag-schema'; import { tagSchema } from './tag-schema';
import { IEventTypes } from '../../types';
import { variantSchema } from './variant-schema';
const eventDataSchema = {
type: 'object',
additionalProperties: true,
properties: {
name: {
type: 'string',
description:
'Name of the feature toggle/strategy/environment that this event relates to',
example: 'my.first.toggle',
},
description: {
type: 'string',
description: 'The description of the object this event relates to',
example: 'Toggle description',
},
type: {
type: 'string',
description:
'If this event relates to a feature toggle, the type of feature toggle.',
example: 'release',
},
project: {
type: 'string',
description: 'The project this event relates to',
example: 'default',
},
stale: {
description: 'Is the feature toggle this event relates to stale',
type: 'boolean',
example: true,
},
variants: {
description: 'Variants configured for this toggle',
type: 'array',
items: {
$ref: '#/components/schemas/variantSchema',
},
},
createdAt: {
type: 'string',
format: 'date-time',
description:
'The time the event happened as a RFC 3339-conformant timestamp.',
example: '2023-07-05T12:56:00.000Z',
},
lastSeenAt: {
type: 'string',
format: 'date-time',
description: 'The time the feature was last seen',
example: '2023-07-05T12:56:00.000Z',
nullable: true,
},
impressionData: {
description:
'Should [impression events](https://docs.getunleash.io/reference/impression-data) activate for this feature toggle',
type: 'boolean',
example: false,
},
},
description:
'Extra associated data related to the event, such as feature toggle state, segment configuration, etc., if applicable.',
example: {
name: 'new-feature',
description: 'Toggle description',
type: 'release',
project: 'my-project',
stale: false,
variants: [],
createdAt: '2022-05-31T13:32:20.547Z',
lastSeenAt: null,
impressionData: true,
},
} as const;
export const eventSchema = { export const eventSchema = {
$id: '#/components/schemas/eventSchema', $id: '#/components/schemas/eventSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['id', 'createdAt', 'type', 'createdBy'], required: ['id', 'createdAt', 'type', 'createdBy'],
description: 'An event describing something happening in the system',
properties: { properties: {
id: { id: {
type: 'integer', type: 'integer',
minimum: 1, minimum: 1,
description: 'The ID of the event. An increasing natural number.',
}, },
createdAt: { createdAt: {
type: 'string', type: 'string',
format: 'date-time', format: 'date-time',
description:
'The time the event happened as a RFC 3339-conformant timestamp.',
example: '2023-07-05T12:56:00.000Z',
}, },
type: { type: {
type: 'string', type: 'string',
description:
'What [type](https://docs.getunleash.io/reference/api/legacy/unleash/admin/events#event-type-description) of event this is',
enum: IEventTypes,
example: 'feature-created',
}, },
createdBy: { createdBy: {
type: 'string', type: 'string',
description: 'Which user created this event',
example: 'johndoe',
}, },
environment: { environment: {
type: 'string', type: 'string',
description:
'The feature toggle environment the event relates to, if applicable.',
nullable: true, nullable: true,
example: 'development',
}, },
project: { project: {
type: 'string', type: 'string',
nullable: true, nullable: true,
description: 'The project the event relates to, if applicable.',
example: 'default',
}, },
featureName: { featureName: {
type: 'string', type: 'string',
nullable: true, nullable: true,
description:
'The name of the feature toggle the event relates to, if applicable.',
example: 'my.first.feature',
},
data: eventDataSchema,
preData: {
...eventDataSchema,
description:
"Data relating to the previous state of the event's subject.",
nullable: true,
}, },
data: { type: 'object', nullable: true },
preData: { type: 'object', nullable: true },
tags: { tags: {
type: 'array', type: 'array',
items: { items: {
$ref: tagSchema.$id, $ref: tagSchema.$id,
}, },
nullable: true, nullable: true,
description: 'Any tags related to the event, if applicable.',
}, },
}, },
components: { components: {
schemas: { schemas: {
tagSchema, tagSchema,
variantSchema,
}, },
}, },
} as const; } as const;

View File

@ -7,18 +7,26 @@ export const eventsSchema = {
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['version', 'events'], required: ['version', 'events'],
description: 'A list of events that has happened in the system',
properties: { properties: {
version: { version: {
type: 'integer', type: 'integer',
minimum: 1, minimum: 1,
enum: [1],
description:
'The api version of this response. A natural increasing number. Only increases if format changes',
example: 1,
}, },
events: { events: {
description: 'The list of events',
type: 'array', type: 'array',
items: { $ref: eventSchema.$id }, items: { $ref: eventSchema.$id },
}, },
totalEvents: { totalEvents: {
type: 'integer', type: 'integer',
description: 'The total count of events',
minimum: 0, minimum: 0,
example: 842,
}, },
}, },
components: { components: {

View File

@ -7,18 +7,31 @@ export const featureEventsSchema = {
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['events'], required: ['events'],
description: 'One or more events happening to a specific feature toggle',
properties: { properties: {
version: { type: 'number' }, version: {
type: 'integer',
description: 'An API versioning number',
minimum: 1,
enum: [1],
example: 1,
},
toggleName: { toggleName: {
description:
'The name of the feature toggle these events relate to',
type: 'string', type: 'string',
example: 'my.first.feature.toggle',
}, },
events: { events: {
description: 'The list of events',
type: 'array', type: 'array',
items: { $ref: eventSchema.$id }, items: { $ref: eventSchema.$id },
}, },
totalEvents: { totalEvents: {
description: 'How many events are there for this feature toggle',
type: 'integer', type: 'integer',
minimum: 0, minimum: 0,
example: 13,
}, },
}, },
components: { components: {

View File

@ -1,4 +1,5 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { IEventTypes } from '../../types';
export const searchEventsSchema = { export const searchEventsSchema = {
$id: '#/components/schemas/searchEventsSchema', $id: '#/components/schemas/searchEventsSchema',
@ -11,14 +12,18 @@ export const searchEventsSchema = {
type: { type: {
type: 'string', type: 'string',
description: 'Find events by event type (case-sensitive).', description: 'Find events by event type (case-sensitive).',
enum: IEventTypes,
example: 'feature-created',
}, },
project: { project: {
type: 'string', type: 'string',
description: 'Find events by project ID (case-sensitive).', description: 'Find events by project ID (case-sensitive).',
example: 'default',
}, },
feature: { feature: {
type: 'string', type: 'string',
description: 'Find events by feature toggle name (case-sensitive).', description: 'Find events by feature toggle name (case-sensitive).',
example: 'my.first.toggle',
}, },
query: { query: {
type: 'string', type: 'string',
@ -28,17 +33,23 @@ export const searchEventsSchema = {
the username or email that created the event (if any), the username or email that created the event (if any),
and the event data payload (if any). and the event data payload (if any).
`, `,
example: 'admin@example.com',
}, },
limit: { limit: {
type: 'integer', type: 'integer',
description:
'The maximum amount of events to return in the search result',
minimum: 1, minimum: 1,
maximum: 100, maximum: 100,
default: 100, default: 100,
example: 50,
}, },
offset: { offset: {
description: 'Which event id to start listing from',
type: 'integer', type: 'integer',
minimum: 0, minimum: 0,
default: 0, default: 0,
example: 100,
}, },
}, },
components: {}, components: {},

View File

@ -23,7 +23,7 @@ import { SearchEventsSchema } from '../../openapi/spec/search-events-schema';
import { IFlagResolver } from '../../types/experimental'; import { IFlagResolver } from '../../types/experimental';
const ANON_KEYS = ['email', 'username', 'createdBy']; const ANON_KEYS = ['email', 'username', 'createdBy'];
const version = 1; const version = 1 as const;
export default class EventController extends Controller { export default class EventController extends Controller {
private eventService: EventService; private eventService: EventService;
@ -104,6 +104,9 @@ export default class EventController extends Controller {
openApiService.validPath({ openApiService.validPath({
operationId: 'searchEvents', operationId: 'searchEvents',
tags: ['Events'], tags: ['Events'],
summary: 'Search for events',
description:
'Allows searching for events matching the search criteria in the request body',
requestBody: createRequestSchema('searchEventsSchema'), requestBody: createRequestSchema('searchEventsSchema'),
responses: { 200: createResponseSchema('eventsSchema') }, responses: { 200: createResponseSchema('eventsSchema') },
}), }),

View File

@ -3,115 +3,222 @@ import { FeatureToggle, IStrategyConfig, ITag, IVariant } from './model';
import { IApiToken } from './models/api-token'; import { IApiToken } from './models/api-token';
import { IUser } from './user'; import { IUser } from './user';
export const APPLICATION_CREATED = 'application-created'; export const APPLICATION_CREATED = 'application-created' as const;
// feature event types // feature event types
export const FEATURE_CREATED = 'feature-created'; export const FEATURE_CREATED = 'feature-created' as const;
export const FEATURE_DELETED = 'feature-deleted'; export const FEATURE_DELETED = 'feature-deleted' as const;
export const FEATURE_UPDATED = 'feature-updated'; export const FEATURE_UPDATED = 'feature-updated' as const;
export const FEATURE_METADATA_UPDATED = 'feature-metadata-updated'; export const FEATURE_METADATA_UPDATED = 'feature-metadata-updated' as const;
export const FEATURE_VARIANTS_UPDATED = 'feature-variants-updated'; export const FEATURE_VARIANTS_UPDATED = 'feature-variants-updated' as const;
export const FEATURE_ENVIRONMENT_VARIANTS_UPDATED = export const FEATURE_ENVIRONMENT_VARIANTS_UPDATED =
'feature-environment-variants-updated'; 'feature-environment-variants-updated' as const;
export const FEATURE_PROJECT_CHANGE = 'feature-project-change'; export const FEATURE_PROJECT_CHANGE = 'feature-project-change' as const;
export const FEATURE_ARCHIVED = 'feature-archived'; export const FEATURE_ARCHIVED = 'feature-archived' as const;
export const FEATURE_REVIVED = 'feature-revived'; export const FEATURE_REVIVED = 'feature-revived' as const;
export const FEATURE_IMPORT = 'feature-import'; export const FEATURE_IMPORT = 'feature-import' as const;
export const FEATURE_TAGGED = 'feature-tagged'; export const FEATURE_TAGGED = 'feature-tagged' as const;
export const FEATURE_TAG_IMPORT = 'feature-tag-import'; export const FEATURE_TAG_IMPORT = 'feature-tag-import' as const;
export const FEATURE_STRATEGY_UPDATE = 'feature-strategy-update'; export const FEATURE_STRATEGY_UPDATE = 'feature-strategy-update' as const;
export const FEATURE_STRATEGY_ADD = 'feature-strategy-add'; export const FEATURE_STRATEGY_ADD = 'feature-strategy-add' as const;
export const FEATURE_STRATEGY_REMOVE = 'feature-strategy-remove'; export const FEATURE_STRATEGY_REMOVE = 'feature-strategy-remove' as const;
export const DROP_FEATURE_TAGS = 'drop-feature-tags'; export const DROP_FEATURE_TAGS = 'drop-feature-tags' as const;
export const FEATURE_UNTAGGED = 'feature-untagged'; export const FEATURE_UNTAGGED = 'feature-untagged' as const;
export const FEATURE_STALE_ON = 'feature-stale-on'; export const FEATURE_STALE_ON = 'feature-stale-on' as const;
export const FEATURE_STALE_OFF = 'feature-stale-off'; export const FEATURE_STALE_OFF = 'feature-stale-off' as const;
export const DROP_FEATURES = 'drop-features'; export const DROP_FEATURES = 'drop-features' as const;
export const FEATURE_ENVIRONMENT_ENABLED = 'feature-environment-enabled'; export const FEATURE_ENVIRONMENT_ENABLED =
export const FEATURE_ENVIRONMENT_DISABLED = 'feature-environment-disabled'; 'feature-environment-enabled' as const;
export const FEATURE_ENVIRONMENT_DISABLED =
'feature-environment-disabled' as const;
export const STRATEGY_CREATED = 'strategy-created'; export const STRATEGY_CREATED = 'strategy-created' as const;
export const STRATEGY_DELETED = 'strategy-deleted'; export const STRATEGY_DELETED = 'strategy-deleted' as const;
export const STRATEGY_DEPRECATED = 'strategy-deprecated'; export const STRATEGY_DEPRECATED = 'strategy-deprecated' as const;
export const STRATEGY_REACTIVATED = 'strategy-reactivated'; export const STRATEGY_REACTIVATED = 'strategy-reactivated' as const;
export const STRATEGY_UPDATED = 'strategy-updated'; export const STRATEGY_UPDATED = 'strategy-updated' as const;
export const STRATEGY_IMPORT = 'strategy-import'; export const STRATEGY_IMPORT = 'strategy-import' as const;
export const DROP_STRATEGIES = 'drop-strategies'; export const DROP_STRATEGIES = 'drop-strategies' as const;
export const CONTEXT_FIELD_CREATED = 'context-field-created'; export const CONTEXT_FIELD_CREATED = 'context-field-created' as const;
export const CONTEXT_FIELD_UPDATED = 'context-field-updated'; export const CONTEXT_FIELD_UPDATED = 'context-field-updated' as const;
export const CONTEXT_FIELD_DELETED = 'context-field-deleted'; export const CONTEXT_FIELD_DELETED = 'context-field-deleted' as const;
export const PROJECT_ACCESS_ADDED = 'project-access-added'; export const PROJECT_ACCESS_ADDED = 'project-access-added' as const;
export const PROJECT_CREATED = 'project-created'; export const PROJECT_CREATED = 'project-created' as const;
export const PROJECT_UPDATED = 'project-updated'; export const PROJECT_UPDATED = 'project-updated' as const;
export const PROJECT_DELETED = 'project-deleted'; export const PROJECT_DELETED = 'project-deleted' as const;
export const PROJECT_IMPORT = 'project-import'; export const PROJECT_IMPORT = 'project-import' as const;
export const PROJECT_USER_ADDED = 'project-user-added'; export const PROJECT_USER_ADDED = 'project-user-added' as const;
export const PROJECT_USER_REMOVED = 'project-user-removed'; export const PROJECT_USER_REMOVED = 'project-user-removed' as const;
export const PROJECT_USER_ROLE_CHANGED = 'project-user-role-changed'; export const PROJECT_USER_ROLE_CHANGED = 'project-user-role-changed' as const;
export const PROJECT_GROUP_ADDED = 'project-group-added'; export const PROJECT_GROUP_ADDED = 'project-group-added' as const;
export const PROJECT_GROUP_REMOVED = 'project-group-removed'; export const PROJECT_GROUP_REMOVED = 'project-group-removed' as const;
export const PROJECT_GROUP_ROLE_CHANGED = 'project-group-role-changed'; export const PROJECT_GROUP_ROLE_CHANGED = 'project-group-role-changed' as const;
export const DROP_PROJECTS = 'drop-projects'; export const DROP_PROJECTS = 'drop-projects' as const;
export const TAG_CREATED = 'tag-created'; export const TAG_CREATED = 'tag-created' as const;
export const TAG_DELETED = 'tag-deleted'; export const TAG_DELETED = 'tag-deleted' as const;
export const TAG_IMPORT = 'tag-import'; export const TAG_IMPORT = 'tag-import' as const;
export const DROP_TAGS = 'drop-tags'; export const DROP_TAGS = 'drop-tags' as const;
export const TAG_TYPE_CREATED = 'tag-type-created'; export const TAG_TYPE_CREATED = 'tag-type-created' as const;
export const TAG_TYPE_DELETED = 'tag-type-deleted'; export const TAG_TYPE_DELETED = 'tag-type-deleted' as const;
export const TAG_TYPE_UPDATED = 'tag-type-updated'; export const TAG_TYPE_UPDATED = 'tag-type-updated' as const;
export const TAG_TYPE_IMPORT = 'tag-type-import'; export const TAG_TYPE_IMPORT = 'tag-type-import' as const;
export const DROP_TAG_TYPES = 'drop-tag-types'; export const DROP_TAG_TYPES = 'drop-tag-types' as const;
export const ADDON_CONFIG_CREATED = 'addon-config-created'; export const ADDON_CONFIG_CREATED = 'addon-config-created' as const;
export const ADDON_CONFIG_UPDATED = 'addon-config-updated'; export const ADDON_CONFIG_UPDATED = 'addon-config-updated' as const;
export const ADDON_CONFIG_DELETED = 'addon-config-deleted'; export const ADDON_CONFIG_DELETED = 'addon-config-deleted' as const;
export const DB_POOL_UPDATE = 'db-pool-update'; export const DB_POOL_UPDATE = 'db-pool-update' as const;
export const USER_CREATED = 'user-created'; export const USER_CREATED = 'user-created' as const;
export const USER_UPDATED = 'user-updated'; export const USER_UPDATED = 'user-updated' as const;
export const USER_DELETED = 'user-deleted'; export const USER_DELETED = 'user-deleted' as const;
export const DROP_ENVIRONMENTS = 'drop-environments'; export const DROP_ENVIRONMENTS = 'drop-environments' as const;
export const ENVIRONMENT_IMPORT = 'environment-import'; export const ENVIRONMENT_IMPORT = 'environment-import' as const;
export const SEGMENT_CREATED = 'segment-created'; export const SEGMENT_CREATED = 'segment-created' as const;
export const SEGMENT_UPDATED = 'segment-updated'; export const SEGMENT_UPDATED = 'segment-updated' as const;
export const SEGMENT_DELETED = 'segment-deleted'; export const SEGMENT_DELETED = 'segment-deleted' as const;
export const GROUP_CREATED = 'group-created'; export const GROUP_CREATED = 'group-created' as const;
export const GROUP_UPDATED = 'group-updated'; export const GROUP_UPDATED = 'group-updated' as const;
export const SETTING_CREATED = 'setting-created'; export const SETTING_CREATED = 'setting-created' as const;
export const SETTING_UPDATED = 'setting-updated'; export const SETTING_UPDATED = 'setting-updated' as const;
export const SETTING_DELETED = 'setting-deleted'; export const SETTING_DELETED = 'setting-deleted' as const;
export const CLIENT_METRICS = 'client-metrics'; export const CLIENT_METRICS = 'client-metrics' as const;
export const CLIENT_REGISTER = 'client-register'; export const CLIENT_REGISTER = 'client-register' as const;
export const PAT_CREATED = 'pat-created'; export const PAT_CREATED = 'pat-created' as const;
export const PAT_DELETED = 'pat-deleted'; export const PAT_DELETED = 'pat-deleted' as const;
export const PUBLIC_SIGNUP_TOKEN_CREATED = 'public-signup-token-created'; export const PUBLIC_SIGNUP_TOKEN_CREATED =
export const PUBLIC_SIGNUP_TOKEN_USER_ADDED = 'public-signup-token-user-added'; 'public-signup-token-created' as const;
export const PUBLIC_SIGNUP_TOKEN_TOKEN_UPDATED = 'public-signup-token-updated'; export const PUBLIC_SIGNUP_TOKEN_USER_ADDED =
'public-signup-token-user-added' as const;
export const PUBLIC_SIGNUP_TOKEN_TOKEN_UPDATED =
'public-signup-token-updated' as const;
export const CHANGE_REQUEST_CREATED = 'change-request-created'; export const CHANGE_REQUEST_CREATED = 'change-request-created' as const;
export const CHANGE_REQUEST_DISCARDED = 'change-request-discarded'; export const CHANGE_REQUEST_DISCARDED = 'change-request-discarded' as const;
export const CHANGE_ADDED = 'change-added'; export const CHANGE_ADDED = 'change-added' as const;
export const CHANGE_DISCARDED = 'change-discarded'; export const CHANGE_DISCARDED = 'change-discarded' as const;
export const CHANGE_REQUEST_APPROVED = 'change-request-approved'; export const CHANGE_REQUEST_APPROVED = 'change-request-approved' as const;
export const CHANGE_REQUEST_APPROVAL_ADDED = 'change-request-approval-added'; export const CHANGE_REQUEST_APPROVAL_ADDED =
export const CHANGE_REQUEST_CANCELLED = 'change-request-cancelled'; 'change-request-approval-added' as const;
export const CHANGE_REQUEST_SENT_TO_REVIEW = 'change-request-sent-to-review'; export const CHANGE_REQUEST_CANCELLED = 'change-request-cancelled' as const;
export const CHANGE_REQUEST_APPLIED = 'change-request-applied'; export const CHANGE_REQUEST_SENT_TO_REVIEW =
'change-request-sent-to-review' as const;
export const CHANGE_REQUEST_APPLIED = 'change-request-applied' as const;
export const API_TOKEN_CREATED = 'api-token-created'; export const API_TOKEN_CREATED = 'api-token-created' as const;
export const API_TOKEN_UPDATED = 'api-token-updated'; export const API_TOKEN_UPDATED = 'api-token-updated' as const;
export const API_TOKEN_DELETED = 'api-token-deleted'; export const API_TOKEN_DELETED = 'api-token-deleted' as const;
export const FEATURE_FAVORITED = 'feature-favorited'; export const FEATURE_FAVORITED = 'feature-favorited' as const;
export const FEATURE_UNFAVORITED = 'feature-unfavorited'; export const FEATURE_UNFAVORITED = 'feature-unfavorited' as const;
export const PROJECT_FAVORITED = 'project-favorited'; export const PROJECT_FAVORITED = 'project-favorited' as const;
export const PROJECT_UNFAVORITED = 'project-unfavorited'; export const PROJECT_UNFAVORITED = 'project-unfavorited' as const;
export const FEATURES_EXPORTED = 'features-exported'; export const FEATURES_EXPORTED = 'features-exported' as const;
export const FEATURES_IMPORTED = 'features-imported'; export const FEATURES_IMPORTED = 'features-imported' as const;
export const IEventTypes = [
APPLICATION_CREATED,
FEATURE_CREATED,
FEATURE_DELETED,
FEATURE_UPDATED,
FEATURE_METADATA_UPDATED,
FEATURE_VARIANTS_UPDATED,
FEATURE_ENVIRONMENT_VARIANTS_UPDATED,
FEATURE_PROJECT_CHANGE,
FEATURE_ARCHIVED,
FEATURE_REVIVED,
FEATURE_IMPORT,
FEATURE_TAGGED,
FEATURE_TAG_IMPORT,
FEATURE_STRATEGY_UPDATE,
FEATURE_STRATEGY_ADD,
FEATURE_STRATEGY_REMOVE,
DROP_FEATURE_TAGS,
FEATURE_UNTAGGED,
FEATURE_STALE_ON,
FEATURE_STALE_OFF,
DROP_FEATURES,
FEATURE_ENVIRONMENT_ENABLED,
FEATURE_ENVIRONMENT_DISABLED,
STRATEGY_CREATED,
STRATEGY_DELETED,
STRATEGY_DEPRECATED,
STRATEGY_REACTIVATED,
STRATEGY_UPDATED,
STRATEGY_IMPORT,
DROP_STRATEGIES,
CONTEXT_FIELD_CREATED,
CONTEXT_FIELD_UPDATED,
CONTEXT_FIELD_DELETED,
PROJECT_ACCESS_ADDED,
PROJECT_CREATED,
PROJECT_UPDATED,
PROJECT_DELETED,
PROJECT_IMPORT,
PROJECT_USER_ADDED,
PROJECT_USER_REMOVED,
PROJECT_USER_ROLE_CHANGED,
PROJECT_GROUP_ROLE_CHANGED,
PROJECT_GROUP_ADDED,
PROJECT_GROUP_REMOVED,
DROP_PROJECTS,
TAG_CREATED,
TAG_DELETED,
TAG_IMPORT,
DROP_TAGS,
TAG_TYPE_CREATED,
TAG_TYPE_DELETED,
TAG_TYPE_UPDATED,
TAG_TYPE_IMPORT,
DROP_TAG_TYPES,
ADDON_CONFIG_CREATED,
ADDON_CONFIG_UPDATED,
ADDON_CONFIG_DELETED,
DB_POOL_UPDATE,
USER_CREATED,
USER_UPDATED,
USER_DELETED,
DROP_ENVIRONMENTS,
ENVIRONMENT_IMPORT,
SEGMENT_CREATED,
SEGMENT_UPDATED,
SEGMENT_DELETED,
GROUP_CREATED,
GROUP_UPDATED,
SETTING_CREATED,
SETTING_UPDATED,
SETTING_DELETED,
CLIENT_METRICS,
CLIENT_REGISTER,
PAT_CREATED,
PAT_DELETED,
PUBLIC_SIGNUP_TOKEN_CREATED,
PUBLIC_SIGNUP_TOKEN_USER_ADDED,
PUBLIC_SIGNUP_TOKEN_TOKEN_UPDATED,
CHANGE_REQUEST_CREATED,
CHANGE_REQUEST_DISCARDED,
CHANGE_ADDED,
CHANGE_DISCARDED,
CHANGE_REQUEST_APPROVED,
CHANGE_REQUEST_APPROVAL_ADDED,
CHANGE_REQUEST_CANCELLED,
CHANGE_REQUEST_SENT_TO_REVIEW,
CHANGE_REQUEST_APPLIED,
API_TOKEN_CREATED,
API_TOKEN_UPDATED,
API_TOKEN_DELETED,
FEATURE_FAVORITED,
FEATURE_UNFAVORITED,
PROJECT_FAVORITED,
PROJECT_UNFAVORITED,
FEATURES_EXPORTED,
FEATURES_IMPORTED,
] as const;
export type IEventType = typeof IEventTypes[number];
export interface IBaseEvent { export interface IBaseEvent {
type: string; type: IEventType;
createdBy: string; createdBy: string;
project?: string; project?: string;
environment?: string; environment?: string;
@ -132,7 +239,7 @@ export interface IEventList {
} }
class BaseEvent implements IBaseEvent { class BaseEvent implements IBaseEvent {
readonly type: string; readonly type: IEventType;
readonly createdBy: string; readonly createdBy: string;
@ -141,7 +248,11 @@ class BaseEvent implements IBaseEvent {
/** /**
* @param createdBy accepts a string for backward compatibility. Prefer using IUser for standardization * @param createdBy accepts a string for backward compatibility. Prefer using IUser for standardization
*/ */
constructor(type: string, createdBy: string | IUser, tags: ITag[] = []) { constructor(
type: IEventType,
createdBy: string | IUser,
tags: ITag[] = [],
) {
this.type = type; this.type = type;
this.createdBy = this.createdBy =
typeof createdBy === 'string' typeof createdBy === 'string'

View File

@ -59,7 +59,6 @@ test('the generated OpenAPI spec is valid', async () => {
.get('/docs/openapi.json') .get('/docs/openapi.json')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200); .expect(200);
// this throws if the swagger parser can't parse it correctly // this throws if the swagger parser can't parse it correctly
// also parses examples, but _does_ do some string coercion in examples // also parses examples, but _does_ do some string coercion in examples
try { try {
@ -86,7 +85,6 @@ test('the generated OpenAPI spec is valid', async () => {
], ],
}, },
}); });
if (enforcerWarning !== undefined) { if (enforcerWarning !== undefined) {
console.warn(enforcerWarning); console.warn(enforcerWarning);
} }

View File

@ -47,8 +47,8 @@ beforeAll(async () => {
}); });
userStore = stores.userStore; userStore = stores.userStore;
const rootRoles = await accessService.getRootRoles(); const rootRoles = await accessService.getRootRoles();
adminRole = rootRoles.find((r) => r.name === RoleName.ADMIN); adminRole = rootRoles.find((r) => r.name === RoleName.ADMIN)!;
viewerRole = rootRoles.find((r) => r.name === RoleName.VIEWER); viewerRole = rootRoles.find((r) => r.name === RoleName.VIEWER)!;
}); });
afterAll(async () => { afterAll(async () => {
@ -218,7 +218,6 @@ test('updating a user without an email should not strip the email', async () =>
await userService.updateUser({ await userService.updateUser({
id: user.id, id: user.id,
email: null,
name: 'some', name: 'some',
}); });

View File

@ -40,7 +40,7 @@ test('Should include id and createdAt when saving', async () => {
appName: 'test1', appName: 'test1',
}, },
}; };
const seen = []; const seen: Array<IEvent> = [];
eventStore.on(APPLICATION_CREATED, (e) => seen.push(e)); eventStore.on(APPLICATION_CREATED, (e) => seen.push(e));
await eventStore.store(event1); await eventStore.store(event1);
jest.advanceTimersByTime(100); jest.advanceTimersByTime(100);