mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: add OpenApi spec to feature variants (#1659)
* feat: add OpenApi spec to feature variants
This commit is contained in:
parent
05b65c53ee
commit
7895002602
12
src/lib/openapi/spec/feature-variants-response.ts
Normal file
12
src/lib/openapi/spec/feature-variants-response.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { OpenAPIV3 } from 'openapi-types';
|
||||||
|
|
||||||
|
export const featureVariantsResponse: OpenAPIV3.ResponseObject = {
|
||||||
|
description: 'featureVariantResponse',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/featureVariantsSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
26
src/lib/openapi/spec/feature-variants-schema.ts
Normal file
26
src/lib/openapi/spec/feature-variants-schema.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { createSchemaObject, CreateSchemaType } from '../types';
|
||||||
|
import { variantSchema } from './variant-schema';
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['version', 'variants'],
|
||||||
|
properties: {
|
||||||
|
version: {
|
||||||
|
type: 'integer',
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
$ref: '#/components/schemas/variantSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'components/schemas': {
|
||||||
|
variantSchema,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FeatureVariantsSchema = CreateSchemaType<typeof schema>;
|
||||||
|
|
||||||
|
export const featureVariantsSchema = createSchemaObject(schema);
|
15
src/lib/openapi/spec/update-feature-variants-request.ts
Normal file
15
src/lib/openapi/spec/update-feature-variants-request.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { OpenAPIV3 } from 'openapi-types';
|
||||||
|
|
||||||
|
export const updateFeatureVariantsRequest: OpenAPIV3.RequestBodyObject = {
|
||||||
|
required: true,
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
$ref: '#/components/schemas/variantSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
@ -5,10 +5,14 @@ import { IUnleashConfig } from '../../../types/option';
|
|||||||
import { IUnleashServices } from '../../../types';
|
import { IUnleashServices } from '../../../types';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { UPDATE_FEATURE_VARIANTS } from '../../../types/permissions';
|
import { NONE, UPDATE_FEATURE_VARIANTS } from '../../../types/permissions';
|
||||||
import { IVariant } from '../../../types/model';
|
import { IVariant } from '../../../types/model';
|
||||||
import { extractUsername } from '../../../util/extract-user';
|
import { extractUsername } from '../../../util/extract-user';
|
||||||
import { IAuthRequest } from '../../unleash-types';
|
import { IAuthRequest } from '../../unleash-types';
|
||||||
|
import { featureVariantsResponse } from '../../../openapi/spec/feature-variants-response';
|
||||||
|
import { patchRequest } from '../../../openapi/spec/patch-request';
|
||||||
|
import { updateFeatureVariantsRequest } from '../../../openapi/spec/update-feature-variants-request';
|
||||||
|
import { FeatureVariantsSchema } from '../../../openapi/spec/feature-variants-schema';
|
||||||
|
|
||||||
const PREFIX = '/:projectId/features/:featureName/variants';
|
const PREFIX = '/:projectId/features/:featureName/variants';
|
||||||
|
|
||||||
@ -19,7 +23,6 @@ interface FeatureParams extends ProjectParam {
|
|||||||
interface ProjectParam {
|
interface ProjectParam {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class VariantsController extends Controller {
|
export default class VariantsController extends Controller {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
@ -29,19 +32,59 @@ export default class VariantsController extends Controller {
|
|||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{
|
{
|
||||||
featureToggleService,
|
featureToggleService,
|
||||||
}: Pick<IUnleashServices, 'featureToggleService'>,
|
openApiService,
|
||||||
|
}: Pick<IUnleashServices, 'featureToggleService' | 'openApiService'>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.logger = config.getLogger('admin-api/project/variants.ts');
|
this.logger = config.getLogger('admin-api/project/variants.ts');
|
||||||
this.featureService = featureToggleService;
|
this.featureService = featureToggleService;
|
||||||
this.get(PREFIX, this.getVariants);
|
this.route({
|
||||||
this.patch(PREFIX, this.patchVariants, UPDATE_FEATURE_VARIANTS);
|
method: 'get',
|
||||||
this.put(PREFIX, this.overwriteVariants, UPDATE_FEATURE_VARIANTS);
|
path: PREFIX,
|
||||||
|
permission: NONE,
|
||||||
|
acceptAnyContentType: true,
|
||||||
|
handler: this.getVariants,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'getFeatureVariants',
|
||||||
|
responses: { 200: featureVariantsResponse },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this.route({
|
||||||
|
method: 'patch',
|
||||||
|
path: PREFIX,
|
||||||
|
permission: UPDATE_FEATURE_VARIANTS,
|
||||||
|
handler: this.patchVariants,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'patchFeatureVariants',
|
||||||
|
requestBody: patchRequest,
|
||||||
|
responses: { 200: featureVariantsResponse },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this.route({
|
||||||
|
method: 'put',
|
||||||
|
path: PREFIX,
|
||||||
|
permission: UPDATE_FEATURE_VARIANTS,
|
||||||
|
handler: this.overwriteVariants,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'overwriteFeatureVariants',
|
||||||
|
requestBody: updateFeatureVariantsRequest,
|
||||||
|
responses: { 200: featureVariantsResponse },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getVariants(
|
async getVariants(
|
||||||
req: Request<FeatureParams, any, any, any>,
|
req: Request<FeatureParams, any, any, any>,
|
||||||
res: Response,
|
res: Response<FeatureVariantsSchema>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { featureName } = req.params;
|
const { featureName } = req.params;
|
||||||
const variants = await this.featureService.getVariants(featureName);
|
const variants = await this.featureService.getVariants(featureName);
|
||||||
@ -50,7 +93,7 @@ export default class VariantsController extends Controller {
|
|||||||
|
|
||||||
async patchVariants(
|
async patchVariants(
|
||||||
req: IAuthRequest<FeatureParams, any, Operation[]>,
|
req: IAuthRequest<FeatureParams, any, Operation[]>,
|
||||||
res: Response,
|
res: Response<FeatureVariantsSchema>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { projectId, featureName } = req.params;
|
const { projectId, featureName } = req.params;
|
||||||
const userName = extractUsername(req);
|
const userName = extractUsername(req);
|
||||||
@ -69,7 +112,7 @@ export default class VariantsController extends Controller {
|
|||||||
|
|
||||||
async overwriteVariants(
|
async overwriteVariants(
|
||||||
req: IAuthRequest<FeatureParams, any, IVariant[], any>,
|
req: IAuthRequest<FeatureParams, any, IVariant[], any>,
|
||||||
res: Response,
|
res: Response<FeatureVariantsSchema>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { projectId, featureName } = req.params;
|
const { projectId, featureName } = req.params;
|
||||||
const userName = extractUsername(req);
|
const userName = extractUsername(req);
|
||||||
|
@ -266,6 +266,7 @@ test('PUTing an invalid variant throws 400 exception', async () => {
|
|||||||
name: 'variant',
|
name: 'variant',
|
||||||
weight: 500,
|
weight: 500,
|
||||||
weightType: 'party',
|
weightType: 'party',
|
||||||
|
stickiness: 'userId',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await app.request
|
await app.request
|
||||||
|
@ -1515,6 +1515,142 @@ Object {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/api/admin/projects/{projectId}/features/{featureName}/variants": Object {
|
||||||
|
"get": Object {
|
||||||
|
"operationId": "getFeatureVariants",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "projectId",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "featureName",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/featureVariantsSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "featureVariantResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"patch": Object {
|
||||||
|
"operationId": "patchFeatureVariants",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "projectId",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "featureName",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"items": Object {
|
||||||
|
"$ref": "#/components/schemas/patchOperationSchema",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/featureVariantsSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "featureVariantResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"put": Object {
|
||||||
|
"operationId": "overwriteFeatureVariants",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "projectId",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "featureName",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"items": Object {
|
||||||
|
"$ref": "#/components/schemas/variantSchema",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/featureVariantsSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "featureVariantResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"security": Array [
|
"security": Array [
|
||||||
Object {
|
Object {
|
||||||
|
Loading…
Reference in New Issue
Block a user