diff --git a/src/lib/openapi/spec/environment-schema.ts b/src/lib/openapi/spec/environment-schema.ts index 1d03356e3a..32a8750030 100644 --- a/src/lib/openapi/spec/environment-schema.ts +++ b/src/lib/openapi/spec/environment-schema.ts @@ -5,33 +5,51 @@ export const environmentSchema = { type: 'object', additionalProperties: false, required: ['name', 'type', 'enabled'], + description: 'A definition of the project environment', properties: { name: { type: 'string', + example: 'my-dev-env', + description: 'The name of the environment', }, type: { type: 'string', + example: 'development', + description: 'The type of the environment', }, enabled: { type: 'boolean', + example: true, + description: + '`true` if the environment is enabled for the project, otherwise `false`.', }, protected: { type: 'boolean', }, sortOrder: { type: 'number', + example: 3, + description: + 'The sort order of the environment in the environments list', }, projectCount: { type: 'number', nullable: true, + example: 10, + description: 'The number of projects with this environment', }, apiTokenCount: { type: 'number', nullable: true, + example: 6, + description: 'The number of API tokens for the project environment', }, enabledToggleCount: { type: 'number', nullable: true, + example: 10, + description: + 'The number of enabled toggles for the project environment', }, }, components: {}, diff --git a/src/lib/openapi/spec/feature-environment-schema.ts b/src/lib/openapi/spec/feature-environment-schema.ts index 0df5eb6a4f..554a53b026 100644 --- a/src/lib/openapi/spec/feature-environment-schema.ts +++ b/src/lib/openapi/spec/feature-environment-schema.ts @@ -9,24 +9,36 @@ export const featureEnvironmentSchema = { type: 'object', additionalProperties: false, required: ['name', 'enabled'], + description: 'A detailed description of the feature environment', properties: { name: { type: 'string', + example: 'my-dev-env', + description: 'The name of the environment', }, featureName: { type: 'string', + example: 'disable-comments', }, environment: { type: 'string', }, type: { type: 'string', + example: 'development', + description: 'The type of the environment', }, enabled: { type: 'boolean', + example: true, + description: + '`true` if the feature is enabled for the environment, otherwise `false`.', }, sortOrder: { type: 'number', + example: 3, + description: + 'The sort order of the feature environment in the feature environments list', }, variantCount: { type: 'number', @@ -36,12 +48,15 @@ export const featureEnvironmentSchema = { items: { $ref: '#/components/schemas/featureStrategySchema', }, + description: + 'A list of activation strategies for the feature environment', }, variants: { type: 'array', items: { $ref: '#/components/schemas/variantSchema', }, + description: 'A list of variants for the feature environment', }, }, components: { diff --git a/src/lib/openapi/spec/feature-schema.ts b/src/lib/openapi/spec/feature-schema.ts index 154b79fbe6..320ffafa39 100644 --- a/src/lib/openapi/spec/feature-schema.ts +++ b/src/lib/openapi/spec/feature-schema.ts @@ -15,58 +15,87 @@ export const featureSchema = { properties: { name: { type: 'string', + example: 'disable-comments', + description: 'Unique feature name', }, type: { type: 'string', + example: 'kill-switch', + description: + 'Type of the toggle e.g. experiment, kill-switch, release, operational, permission', }, description: { type: 'string', nullable: true, + example: + 'Controls disabling of the comments section in case of an incident', + description: 'Detailed description of the feature', }, archived: { type: 'boolean', + example: true, + description: + '`true` if the feature is archived, otherwise `false`.', }, project: { type: 'string', + example: 'dx-squad', + description: 'Name of the project the feature belongs to', }, enabled: { type: 'boolean', + example: true, }, stale: { type: 'boolean', + example: false, + description: + '`true` if the feature is stale based on the age and feature type, otherwise `false`.', }, favorite: { type: 'boolean', + example: true, + description: + '`true` if the feature was favorited, otherwise `false`.', }, impressionData: { type: 'boolean', + example: false, + description: + '`true` if the impression data collection is enabled for the feature, otherwise `false`.', }, createdAt: { type: 'string', format: 'date-time', nullable: true, + example: '2023-01-28T15:21:39.975Z', }, archivedAt: { type: 'string', format: 'date-time', nullable: true, + example: '2023-01-29T15:21:39.975Z', }, lastSeenAt: { type: 'string', format: 'date-time', nullable: true, + example: '2023-01-28T16:21:39.975Z', }, environments: { type: 'array', items: { $ref: '#/components/schemas/featureEnvironmentSchema', }, + description: + 'The list of environments where the feature can be used', }, variants: { type: 'array', items: { $ref: '#/components/schemas/variantSchema', }, + description: 'The list of feature variants', }, tags: { type: 'array', @@ -74,6 +103,7 @@ export const featureSchema = { $ref: '#/components/schemas/tagSchema', }, nullable: true, + description: 'The list of feature tags', }, }, components: { diff --git a/src/lib/openapi/spec/project-overview-schema.ts b/src/lib/openapi/spec/project-overview-schema.ts index 6f21298d98..787dbe9a5d 100644 --- a/src/lib/openapi/spec/project-overview-schema.ts +++ b/src/lib/openapi/spec/project-overview-schema.ts @@ -14,44 +14,66 @@ export const projectOverviewSchema = { type: 'object', additionalProperties: false, required: ['version', 'name'], + description: + 'A high-level overview of a project. It contains information such as project statistics, the name of the project, what members and what features it contains, etc.', properties: { stats: { $ref: '#/components/schemas/projectStatsSchema', + description: 'Project statistics', }, version: { type: 'number', + example: 1, }, name: { type: 'string', + example: 'dx-squad', + description: 'The name of this project', }, description: { type: 'string', + nullable: true, + example: 'DX squad feature release', + description: 'Additional information about the project', }, members: { type: 'number', + example: 4, + description: 'The number of members this project has', }, health: { type: 'number', + example: 50, + description: + "An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#health-rating) on a scale from 0 to 100", }, environments: { type: 'array', items: { type: 'string', }, + example: ['development', 'production'], + description: 'The environments that are enabled for this project', }, features: { type: 'array', items: { $ref: '#/components/schemas/featureSchema', }, + description: + 'The full list of features in this project (excluding archived features)', }, updatedAt: { type: 'string', format: 'date-time', nullable: true, + example: '2023-02-10T08:36:35.262Z', }, favorite: { type: 'boolean', + example: true, + description: + '`true` if the project was favorited, otherwise `false`.', }, }, components: { diff --git a/src/lib/openapi/spec/project-schema.test.ts b/src/lib/openapi/spec/project-schema.test.ts index ce231dd847..fe5d2ce0b7 100644 --- a/src/lib/openapi/spec/project-schema.test.ts +++ b/src/lib/openapi/spec/project-schema.test.ts @@ -10,7 +10,6 @@ test('projectSchema', () => { featureCount: 10, memberCount: 3, updatedAt: '2022-06-28T17:33:53.963Z', - changeRequestsEnabled: false, }; expect( diff --git a/src/lib/openapi/spec/project-schema.ts b/src/lib/openapi/spec/project-schema.ts index 09b5de7a35..b81512188b 100644 --- a/src/lib/openapi/spec/project-schema.ts +++ b/src/lib/openapi/spec/project-schema.ts @@ -5,24 +5,40 @@ export const projectSchema = { type: 'object', additionalProperties: false, required: ['id', 'name'], + description: + 'A definition of the project used for projects listing purposes', properties: { id: { type: 'string', + example: 'dx-squad', + description: 'The id of this project', }, name: { type: 'string', + example: 'DX-Squad', + description: 'The name of this project', }, description: { type: 'string', + nullable: true, + example: 'DX squad feature release', + description: 'Additional information about the project', }, health: { type: 'number', + example: 50, + description: + "An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#health-rating) on a scale from 0 to 100", }, featureCount: { type: 'number', + example: 10, + description: 'The number of features this project has', }, memberCount: { type: 'number', + example: 4, + description: 'The number of members this project has', }, createdAt: { type: 'string', @@ -33,11 +49,11 @@ export const projectSchema = { format: 'date-time', nullable: true, }, - changeRequestsEnabled: { - type: 'boolean', - }, favorite: { type: 'boolean', + example: true, + description: + '`true` if the project was favorited, otherwise `false`.', }, }, components: {}, diff --git a/src/lib/openapi/spec/project-stats-schema.ts b/src/lib/openapi/spec/project-stats-schema.ts index ae5dc2671a..041ddba94f 100644 --- a/src/lib/openapi/spec/project-stats-schema.ts +++ b/src/lib/openapi/spec/project-stats-schema.ts @@ -15,33 +15,65 @@ export const projectStatsSchema = { 'projectActivityPastWindow', 'projectMembersAddedCurrentWindow', ], + description: `Statistics for a project, including the average time to production, number of features created, the project activity and more. + +Stats are divided into current and previous **windows**. +- The **current window** is the past 30 days. +- The **previous window** is the 30 days **before** the current window (from 60 to 30 days ago)`, properties: { avgTimeToProdCurrentWindow: { type: 'number', + example: 10, + description: + 'The average time from when a feature was created to when it was enabled in the "production" environment during the current window', }, avgTimeToProdPastWindow: { type: 'number', + example: 10, + description: + 'The average time from when a feature was created to when it was enabled in the "production" environment during the previous window', }, createdCurrentWindow: { type: 'number', + example: 15, + description: + 'The number of feature toggles created during the current window', }, createdPastWindow: { type: 'number', + example: 15, + description: + 'The number of feature toggles created during the previous window', }, archivedCurrentWindow: { type: 'number', + example: 5, + description: + 'The number of feature toggles that were archived during the current window', }, archivedPastWindow: { type: 'number', + example: 5, + description: + 'The number of feature toggles that were archived during the previous window', }, projectActivityCurrentWindow: { type: 'number', + example: 100, + description: + 'The number of project events that occurred during the current window', }, projectActivityPastWindow: { type: 'number', + example: 100, + description: + 'The number of project events that occurred during the previous window', }, projectMembersAddedCurrentWindow: { type: 'number', + example: 1, + description: + 'The number of members that were added to the project during the current window', }, }, components: {}, diff --git a/src/lib/openapi/spec/projects-schema.ts b/src/lib/openapi/spec/projects-schema.ts index 0634b71df4..ba2618ef63 100644 --- a/src/lib/openapi/spec/projects-schema.ts +++ b/src/lib/openapi/spec/projects-schema.ts @@ -6,6 +6,7 @@ export const projectsSchema = { type: 'object', additionalProperties: false, required: ['version', 'projects'], + description: 'An overview of all the projects in the Unleash instance', properties: { version: { type: 'integer', @@ -15,6 +16,7 @@ export const projectsSchema = { items: { $ref: '#/components/schemas/projectSchema', }, + description: 'A list of projects in the Unleash instance', }, }, components: { diff --git a/src/lib/routes/admin-api/project/index.ts b/src/lib/routes/admin-api/project/index.ts index 1e5a830a4c..af363ac3f0 100644 --- a/src/lib/routes/admin-api/project/index.ts +++ b/src/lib/routes/admin-api/project/index.ts @@ -17,8 +17,8 @@ import { serializeDates } from '../../../types/serialize-dates'; import { createResponseSchema } from '../../../openapi/util/create-response-schema'; import { IAuthRequest } from '../../unleash-types'; import { - HealthOverviewSchema, - healthOverviewSchema, + ProjectOverviewSchema, + projectOverviewSchema, } from '../../../../lib/openapi'; import { IArchivedQuery, IProjectParam } from '../../../types/model'; @@ -92,7 +92,7 @@ export default class ProjectApi extends Controller { async getProjectOverview( req: IAuthRequest, - res: Response, + res: Response, ): Promise { const { projectId } = req.params; const { archived } = req.query; @@ -105,7 +105,7 @@ export default class ProjectApi extends Controller { this.openApiService.respondWithValidation( 200, res, - healthOverviewSchema.$id, + projectOverviewSchema.$id, serializeDates(overview), ); } diff --git a/src/lib/types/model.ts b/src/lib/types/model.ts index 5bb0775b24..c528a57abd 100644 --- a/src/lib/types/model.ts +++ b/src/lib/types/model.ts @@ -183,7 +183,7 @@ export interface IProjectOverview { health: number; favorite?: boolean; updatedAt?: Date; - stats: IProjectStats | {}; + stats?: IProjectStats; } export interface IProjectHealthReport extends IProjectOverview { diff --git a/src/test/e2e/api/admin/project/environments.e2e.test.ts b/src/test/e2e/api/admin/project/environments.e2e.test.ts index e1b96eb2bb..7612162276 100644 --- a/src/test/e2e/api/admin/project/environments.e2e.test.ts +++ b/src/test/e2e/api/admin/project/environments.e2e.test.ts @@ -1,5 +1,8 @@ import dbInit, { ITestDb } from '../../../helpers/database-init'; -import { IUnleashTest, setupApp } from '../../../helpers/test-helper'; +import { + IUnleashTest, + setupAppWithCustomConfig, +} from '../../../helpers/test-helper'; import getLogger from '../../../../fixtures/no-logger'; import { DEFAULT_ENV } from '../../../../../lib/util/constants'; @@ -8,7 +11,13 @@ let db: ITestDb; beforeAll(async () => { db = await dbInit('project_environments_api_serial', getLogger); - app = await setupApp(db.stores); + app = await setupAppWithCustomConfig(db.stores, { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }); }); afterEach(async () => { diff --git a/src/test/e2e/api/admin/project/features.e2e.test.ts b/src/test/e2e/api/admin/project/features.e2e.test.ts index 59d14427d6..5bac0ede8b 100644 --- a/src/test/e2e/api/admin/project/features.e2e.test.ts +++ b/src/test/e2e/api/admin/project/features.e2e.test.ts @@ -1,5 +1,8 @@ import dbInit, { ITestDb } from '../../../helpers/database-init'; -import { IUnleashTest, setupApp } from '../../../helpers/test-helper'; +import { + IUnleashTest, + setupAppWithCustomConfig, +} from '../../../helpers/test-helper'; import getLogger from '../../../../fixtures/no-logger'; import { DEFAULT_ENV } from '../../../../../lib/util/constants'; import { @@ -85,7 +88,13 @@ const updateStrategy = async ( beforeAll(async () => { db = await dbInit('feature_strategy_api_serial', getLogger); - app = await setupApp(db.stores); + app = await setupAppWithCustomConfig(db.stores, { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }); }); afterEach(async () => { diff --git a/src/test/e2e/api/admin/project/projects.e2e.test.ts b/src/test/e2e/api/admin/project/projects.e2e.test.ts index 9bbae4ccff..e6cd0e3fe0 100644 --- a/src/test/e2e/api/admin/project/projects.e2e.test.ts +++ b/src/test/e2e/api/admin/project/projects.e2e.test.ts @@ -1,5 +1,5 @@ import dbInit from '../../../helpers/database-init'; -import { setupApp } from '../../../helpers/test-helper'; +import { setupAppWithCustomConfig } from '../../../helpers/test-helper'; import getLogger from '../../../../fixtures/no-logger'; import ProjectStore from '../../../../../lib/db/project-store'; @@ -10,7 +10,13 @@ let projectStore: ProjectStore; beforeAll(async () => { db = await dbInit('projects_api_serial', getLogger); - app = await setupApp(db.stores); + app = await setupAppWithCustomConfig(db.stores, { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }); projectStore = db.stores.projectStore; }); diff --git a/src/test/e2e/api/admin/strategy.e2e.test.ts b/src/test/e2e/api/admin/strategy.e2e.test.ts index af1ee8d1a4..235f7ccaf3 100644 --- a/src/test/e2e/api/admin/strategy.e2e.test.ts +++ b/src/test/e2e/api/admin/strategy.e2e.test.ts @@ -1,5 +1,5 @@ import dbInit from '../../helpers/database-init'; -import { setupApp } from '../../helpers/test-helper'; +import { setupAppWithCustomConfig } from '../../helpers/test-helper'; import getLogger from '../../../fixtures/no-logger'; let app; @@ -7,7 +7,13 @@ let db; beforeAll(async () => { db = await dbInit('strategy_api_serial', getLogger); - app = await setupApp(db.stores); + app = await setupAppWithCustomConfig(db.stores, { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }); }); afterAll(async () => { diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap index 72bc086a42..73208757b6 100644 --- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap +++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap @@ -883,22 +883,33 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "environmentSchema": { "additionalProperties": false, + "description": "A definition of the project environment", "properties": { "apiTokenCount": { + "description": "The number of API tokens for the project environment", + "example": 6, "nullable": true, "type": "number", }, "enabled": { + "description": "\`true\` if the environment is enabled for the project, otherwise \`false\`.", + "example": true, "type": "boolean", }, "enabledToggleCount": { + "description": "The number of enabled toggles for the project environment", + "example": 10, "nullable": true, "type": "number", }, "name": { + "description": "The name of the environment", + "example": "my-dev-env", "type": "string", }, "projectCount": { + "description": "The number of projects with this environment", + "example": 10, "nullable": true, "type": "number", }, @@ -906,9 +917,13 @@ exports[`should serve the OpenAPI spec 1`] = ` "type": "boolean", }, "sortOrder": { + "description": "The sort order of the environment in the environments list", + "example": 3, "type": "number", }, "type": { + "description": "The type of the environment", + "example": "development", "type": "string", }, }, @@ -1143,35 +1158,47 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "featureEnvironmentSchema": { "additionalProperties": false, + "description": "A detailed description of the feature environment", "properties": { "enabled": { + "description": "\`true\` if the feature is enabled for the environment, otherwise \`false\`.", + "example": true, "type": "boolean", }, "environment": { "type": "string", }, "featureName": { + "example": "disable-comments", "type": "string", }, "name": { + "description": "The name of the environment", + "example": "my-dev-env", "type": "string", }, "sortOrder": { + "description": "The sort order of the feature environment in the feature environments list", + "example": 3, "type": "number", }, "strategies": { + "description": "A list of activation strategies for the feature environment", "items": { "$ref": "#/components/schemas/featureStrategySchema", }, "type": "array", }, "type": { + "description": "The type of the environment", + "example": "development", "type": "string", }, "variantCount": { "type": "number", }, "variants": { + "description": "A list of variants for the feature environment", "items": { "$ref": "#/components/schemas/variantSchema", }, @@ -1232,52 +1259,72 @@ exports[`should serve the OpenAPI spec 1`] = ` "additionalProperties": false, "properties": { "archived": { + "description": "\`true\` if the feature is archived, otherwise \`false\`.", + "example": true, "type": "boolean", }, "archivedAt": { + "example": "2023-01-29T15:21:39.975Z", "format": "date-time", "nullable": true, "type": "string", }, "createdAt": { + "example": "2023-01-28T15:21:39.975Z", "format": "date-time", "nullable": true, "type": "string", }, "description": { + "description": "Detailed description of the feature", + "example": "Controls disabling of the comments section in case of an incident", "nullable": true, "type": "string", }, "enabled": { + "example": true, "type": "boolean", }, "environments": { + "description": "The list of environments where the feature can be used", "items": { "$ref": "#/components/schemas/featureEnvironmentSchema", }, "type": "array", }, "favorite": { + "description": "\`true\` if the feature was favorited, otherwise \`false\`.", + "example": true, "type": "boolean", }, "impressionData": { + "description": "\`true\` if the impression data collection is enabled for the feature, otherwise \`false\`.", + "example": false, "type": "boolean", }, "lastSeenAt": { + "example": "2023-01-28T16:21:39.975Z", "format": "date-time", "nullable": true, "type": "string", }, "name": { + "description": "Unique feature name", + "example": "disable-comments", "type": "string", }, "project": { + "description": "Name of the project the feature belongs to", + "example": "dx-squad", "type": "string", }, "stale": { + "description": "\`true\` if the feature is stale based on the age and feature type, otherwise \`false\`.", + "example": false, "type": "boolean", }, "tags": { + "description": "The list of feature tags", "items": { "$ref": "#/components/schemas/tagSchema", }, @@ -1285,9 +1332,12 @@ exports[`should serve the OpenAPI spec 1`] = ` "type": "array", }, "type": { + "description": "Type of the toggle e.g. experiment, kill-switch, release, operational, permission", + "example": "kill-switch", "type": "string", }, "variants": { + "description": "The list of feature variants", "items": { "$ref": "#/components/schemas/variantSchema", }, @@ -2428,43 +2478,64 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "projectOverviewSchema": { "additionalProperties": false, + "description": "A high-level overview of a project. It contains information such as project statistics, the name of the project, what members and what features it contains, etc.", "properties": { "description": { + "description": "Additional information about the project", + "example": "DX squad feature release", + "nullable": true, "type": "string", }, "environments": { + "description": "The environments that are enabled for this project", + "example": [ + "development", + "production", + ], "items": { "type": "string", }, "type": "array", }, "favorite": { + "description": "\`true\` if the project was favorited, otherwise \`false\`.", + "example": true, "type": "boolean", }, "features": { + "description": "The full list of features in this project (excluding archived features)", "items": { "$ref": "#/components/schemas/featureSchema", }, "type": "array", }, "health": { + "description": "An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#health-rating) on a scale from 0 to 100", + "example": 50, "type": "number", }, "members": { + "description": "The number of members this project has", + "example": 4, "type": "number", }, "name": { + "description": "The name of this project", + "example": "dx-squad", "type": "string", }, "stats": { "$ref": "#/components/schemas/projectStatsSchema", + "description": "Project statistics", }, "updatedAt": { + "example": "2023-02-10T08:36:35.262Z", "format": "date-time", "nullable": true, "type": "string", }, "version": { + "example": 1, "type": "number", }, }, @@ -2476,33 +2547,46 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "projectSchema": { "additionalProperties": false, + "description": "A definition of the project used for projects listing purposes", "properties": { - "changeRequestsEnabled": { - "type": "boolean", - }, "createdAt": { "format": "date-time", "type": "string", }, "description": { + "description": "Additional information about the project", + "example": "DX squad feature release", + "nullable": true, "type": "string", }, "favorite": { + "description": "\`true\` if the project was favorited, otherwise \`false\`.", + "example": true, "type": "boolean", }, "featureCount": { + "description": "The number of features this project has", + "example": 10, "type": "number", }, "health": { + "description": "An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#health-rating) on a scale from 0 to 100", + "example": 50, "type": "number", }, "id": { + "description": "The id of this project", + "example": "dx-squad", "type": "string", }, "memberCount": { + "description": "The number of members this project has", + "example": 4, "type": "number", }, "name": { + "description": "The name of this project", + "example": "DX-Squad", "type": "string", }, "updatedAt": { @@ -2519,32 +2603,55 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "projectStatsSchema": { "additionalProperties": false, + "description": "Statistics for a project, including the average time to production, number of features created, the project activity and more. + +Stats are divided into current and previous **windows**. +- The **current window** is the past 30 days. +- The **previous window** is the 30 days **before** the current window (from 60 to 30 days ago)", "properties": { "archivedCurrentWindow": { + "description": "The number of feature toggles that were archived during the current window", + "example": 5, "type": "number", }, "archivedPastWindow": { + "description": "The number of feature toggles that were archived during the previous window", + "example": 5, "type": "number", }, "avgTimeToProdCurrentWindow": { + "description": "The average time from when a feature was created to when it was enabled in the "production" environment during the current window", + "example": 10, "type": "number", }, "avgTimeToProdPastWindow": { + "description": "The average time from when a feature was created to when it was enabled in the "production" environment during the previous window", + "example": 10, "type": "number", }, "createdCurrentWindow": { + "description": "The number of feature toggles created during the current window", + "example": 15, "type": "number", }, "createdPastWindow": { + "description": "The number of feature toggles created during the previous window", + "example": 15, "type": "number", }, "projectActivityCurrentWindow": { + "description": "The number of project events that occurred during the current window", + "example": 100, "type": "number", }, "projectActivityPastWindow": { + "description": "The number of project events that occurred during the previous window", + "example": 100, "type": "number", }, "projectMembersAddedCurrentWindow": { + "description": "The number of members that were added to the project during the current window", + "example": 1, "type": "number", }, }, @@ -2563,8 +2670,10 @@ exports[`should serve the OpenAPI spec 1`] = ` }, "projectsSchema": { "additionalProperties": false, + "description": "An overview of all the projects in the Unleash instance", "properties": { "projects": { + "description": "A list of projects in the Unleash instance", "items": { "$ref": "#/components/schemas/projectSchema", },