1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-11-01 19:07:38 +01:00
unleash.unleash/src/lib/schema/feature-schema.ts
Christopher Kolstad 6c6001619c
Feat/variant api (#1119)
Add a new .../:feature/variants API

This adds
- `GET /api/admin/projects/:projectId/features/:featureName/variants` which returns 
```json
{ version: '1', variants: IVariant[] }
```
- `PATCH /api/admin/projects/:projectId/features/:featureName/variants` which accepts a json patch set and updates the feature's variants field and then returns 
```json
{ version: '1', variants: IVariant[] }
```
- `PUT /api/admin/projects/:projectId/features/:featureName/variants`
 which accepts a IVariant[] and overwrites the current variants list for the feature defined in :featureName and returns
```json
{ version: '1', variants: IVariant[] }

- This also makes sure the total weight of all variants is == 1000
- Validates that there is at least 1 'variable' variant if there are variants
- Validates that 'fix' variants total weight can't exceed 1000
- Adds tests for all these invariants.


Co-authored-by: Simon Hornby <simon@getunleash.ai>
2021-11-24 13:08:04 +01:00

111 lines
3.4 KiB
TypeScript

import joi from 'joi';
import { nameType } from '../routes/util';
export const nameSchema = joi
.object()
.keys({ name: nameType })
.options({ stripUnknown: true, allowUnknown: false, abortEarly: false });
export const constraintSchema = joi.object().keys({
contextName: joi.string(),
operator: joi.string(),
values: joi.array().items(joi.string().min(1).max(100)).min(1).optional(),
});
export const strategiesSchema = joi.object().keys({
id: joi.string().optional(),
name: nameType,
constraints: joi.array().allow(null).items(constraintSchema),
parameters: joi.object(),
});
export const variantsSchema = joi.object().keys({
name: nameType,
weight: joi.number().min(0).max(1000).required(),
weightType: joi.string().valid('variable', 'fix').default('variable'),
payload: joi
.object()
.keys({
type: joi.string().required(),
value: joi.string().required(),
})
.optional(),
stickiness: joi.string().default('default'),
overrides: joi.array().items(
joi
.object()
.keys({
contextName: joi.string().required(),
values: joi.array().items(joi.string()),
})
.optional(),
),
});
export const variantsArraySchema = joi.array().min(0).items(variantsSchema);
export const featureMetadataSchema = joi
.object()
.keys({
name: nameType,
stale: joi.boolean().default(false),
archived: joi.boolean().default(false),
type: joi.string().default('release'),
description: joi.string().allow('').allow(null).optional(),
variants: joi
.array()
.allow(null)
.unique((a, b) => a.name === b.name)
.optional()
.items(variantsSchema),
createdAt: joi.date().optional().allow(null),
})
.options({ allowUnknown: false, stripUnknown: true, abortEarly: false });
export const featureSchema = joi
.object()
.keys({
name: nameType,
enabled: joi.boolean().default(false),
stale: joi.boolean().default(false),
archived: joi.boolean().default(false),
type: joi.string().default('release'),
project: joi.string().default('default'),
description: joi.string().allow('').allow(null).optional(),
strategies: joi
.array()
.min(0)
.allow(null)
.optional()
.items(strategiesSchema),
variants: joi
.array()
.allow(null)
.unique((a, b) => a.name === b.name)
.optional()
.items(variantsSchema),
})
.options({ allowUnknown: false, stripUnknown: true, abortEarly: false });
export const querySchema = joi
.object()
.keys({
tag: joi
.array()
.allow(null)
.items(joi.string().pattern(/\w+:.+/, { name: 'tag' }))
.optional(),
project: joi.array().allow(null).items(nameType).optional(),
namePrefix: joi.string().allow(null).optional(),
environment: joi.string().allow(null).optional(),
})
.options({ allowUnknown: false, stripUnknown: true, abortEarly: false });
export const featureTagSchema = joi.object().keys({
featureName: nameType,
tagType: nameType.optional(),
tagValue: joi.string(),
type: nameType.optional(),
value: joi.string().optional(),
});