mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: generate an OpenAPI client (2) (#875)
* feat: add a script that generates an OpenAPI client * feat: generate an OpenAPI client * feat: use the generated OpenAPI client * refactor: add an OpenAPI section to the readme * refactor: fix missing interface prefixes * refactor: regenerate OpenAPI client
This commit is contained in:
		
							parent
							
								
									f6e42f99f9
								
							
						
					
					
						commit
						8f1900f32b
					
				@ -1,2 +1,3 @@
 | 
			
		||||
CHANGELOG.md
 | 
			
		||||
.github/*
 | 
			
		||||
/src/openapi
 | 
			
		||||
CHANGELOG.md
 | 
			
		||||
 | 
			
		||||
@ -23,10 +23,10 @@ yarn install
 | 
			
		||||
yarn run start:heroku
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Running end-to-end Tests
 | 
			
		||||
 | 
			
		||||
We have a set of Cypress tests that run on the build before a PR can be merged so it's important that you check these yourself before submitting a PR.
 | 
			
		||||
## Running end-to-end tests
 | 
			
		||||
 | 
			
		||||
We have a set of Cypress tests that run on the build before a PR can be merged
 | 
			
		||||
so it's important that you check these yourself before submitting a PR.
 | 
			
		||||
On the server the tests will run against the deployed Heroku app so this is what you probably want to test against:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
@ -39,15 +39,30 @@ In a different shell, you can run the tests themselves:
 | 
			
		||||
yarn run e2e:heroku
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you need to test against patches against a local server instance, you'll need to run that, and then run the end to end tests using:
 | 
			
		||||
If you need to test against patches against a local server instance,
 | 
			
		||||
you'll need to run that, and then run the end to end tests using:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
yarn run e2e
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You may also need to test that a feature works against the enterprise version of unleash. Assuming the Heroku instance is still running, this can be done by:
 | 
			
		||||
You may also need to test that a feature works against the enterprise version of unleash.
 | 
			
		||||
Assuming the Heroku instance is still running, this can be done by:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
yarn run start:enterprise
 | 
			
		||||
yarn run e2e
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Generating the OpenAPI client
 | 
			
		||||
 | 
			
		||||
The frontend uses an OpenAPI client generated from the backend's OpenAPI spec.
 | 
			
		||||
Whenever there are changes to the backend API, the client should be regenerated:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
./scripts/generate-openapi.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This script assumes that you have a running instance of the enterprise backend at `http://localhost:4242`.
 | 
			
		||||
The new OpenAPI client will be generated from the runtime schema of this instance.
 | 
			
		||||
The target URL can be changed by setting the `UNLEASH_OPENAPI_URL` env var.
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@
 | 
			
		||||
    "@material-ui/core": "4.12.4",
 | 
			
		||||
    "@material-ui/icons": "4.11.3",
 | 
			
		||||
    "@material-ui/lab": "4.0.0-alpha.61",
 | 
			
		||||
    "@openapitools/openapi-generator-cli": "^2.4.26",
 | 
			
		||||
    "@testing-library/dom": "8.12.0",
 | 
			
		||||
    "@testing-library/jest-dom": "5.16.3",
 | 
			
		||||
    "@testing-library/react": "12.1.5",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								frontend/scripts/generate-openapi.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								frontend/scripts/generate-openapi.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
# Generate OpenAPI bindings for the Unleash API.
 | 
			
		||||
# https://openapi-generator.tech/docs/generators/typescript-fetch
 | 
			
		||||
 | 
			
		||||
set -feux
 | 
			
		||||
cd "$(dirname "$0")"
 | 
			
		||||
 | 
			
		||||
# URL to the generated open API spec.
 | 
			
		||||
# Set the UNLEASH_OPENAPI_URL environment variable to override.
 | 
			
		||||
UNLEASH_OPENAPI_URL="${UNLEASH_OPENAPI_URL:-http://localhost:4242/docs/openapi.json}"
 | 
			
		||||
 | 
			
		||||
rm -rf "../src/openapi"
 | 
			
		||||
mkdir "../src/openapi"
 | 
			
		||||
 | 
			
		||||
npx @openapitools/openapi-generator-cli generate \
 | 
			
		||||
    -g "typescript-fetch" \
 | 
			
		||||
    -i "$UNLEASH_OPENAPI_URL" \
 | 
			
		||||
    -o "../src/openapi"
 | 
			
		||||
 | 
			
		||||
# Remove unused files.
 | 
			
		||||
rm  "openapitools.json"
 | 
			
		||||
rm  "../src/openapi/.openapi-generator-ignore"
 | 
			
		||||
rm  -r "../src/openapi/.openapi-generator"
 | 
			
		||||
@ -10,7 +10,7 @@ import {
 | 
			
		||||
    TextField,
 | 
			
		||||
} from '@material-ui/core';
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
interface IAutoCreateFormProps {
 | 
			
		||||
    data?: {
 | 
			
		||||
        enabled: boolean;
 | 
			
		||||
        autoCreate: boolean;
 | 
			
		||||
@ -23,7 +23,7 @@ interface Props {
 | 
			
		||||
export const AutoCreateForm = ({
 | 
			
		||||
    data = { enabled: false, autoCreate: false },
 | 
			
		||||
    setValue,
 | 
			
		||||
}: Props) => {
 | 
			
		||||
}: IAutoCreateFormProps) => {
 | 
			
		||||
    const updateAutoCreate = () => {
 | 
			
		||||
        setValue('autoCreate', !data.autoCreate);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,13 @@ export const ArchiveListContainer = () => {
 | 
			
		||||
    const { setToastData, setToastApiError } = useToast();
 | 
			
		||||
    const { uiConfig } = useUiConfig();
 | 
			
		||||
    const { reviveFeature } = useFeatureArchiveApi();
 | 
			
		||||
    const { archivedFeatures, loading, refetchArchived } = useFeaturesArchive();
 | 
			
		||||
 | 
			
		||||
    const {
 | 
			
		||||
        archivedFeatures = [],
 | 
			
		||||
        refetchArchived,
 | 
			
		||||
        loading,
 | 
			
		||||
    } = useFeaturesArchive();
 | 
			
		||||
 | 
			
		||||
    const { filtered, filter, setFilter } = useFeaturesFilter(archivedFeatures);
 | 
			
		||||
    const { sorted, sort, setSort } = useFeaturesSort(filtered);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -37,13 +37,13 @@ interface IEnvironmentListItemProps {
 | 
			
		||||
    moveListItemApi: (dragIndex: number, hoverIndex: number) => Promise<void>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface DragItem {
 | 
			
		||||
interface IDragItem {
 | 
			
		||||
    index: number;
 | 
			
		||||
    id: string;
 | 
			
		||||
    type: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface CollectedProps {
 | 
			
		||||
interface ICollectedProps {
 | 
			
		||||
    handlerId: Identifier | null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -69,19 +69,19 @@ const EnvironmentListItem = ({
 | 
			
		||||
        }),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [{ handlerId }, drop] = useDrop<DragItem, unknown, CollectedProps>({
 | 
			
		||||
    const [{ handlerId }, drop] = useDrop<IDragItem, unknown, ICollectedProps>({
 | 
			
		||||
        accept: ACCEPT_TYPE,
 | 
			
		||||
        collect(monitor) {
 | 
			
		||||
            return {
 | 
			
		||||
                handlerId: monitor.getHandlerId(),
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
        drop(item: DragItem, monitor: DropTargetMonitor) {
 | 
			
		||||
        drop(item: IDragItem, monitor: DropTargetMonitor) {
 | 
			
		||||
            const dragIndex = item.index;
 | 
			
		||||
            const hoverIndex = index;
 | 
			
		||||
            moveListItemApi(dragIndex, hoverIndex);
 | 
			
		||||
        },
 | 
			
		||||
        hover(item: DragItem, monitor: DropTargetMonitor) {
 | 
			
		||||
        hover(item: IDragItem, monitor: DropTargetMonitor) {
 | 
			
		||||
            if (!ref.current) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,6 @@ const CreateFeature = () => {
 | 
			
		||||
        if (validToggleName) {
 | 
			
		||||
            const payload = getTogglePayload();
 | 
			
		||||
            try {
 | 
			
		||||
                // @ts-expect-error
 | 
			
		||||
                await createFeatureToggle(project, payload);
 | 
			
		||||
                history.push(`/projects/${project}/features/${name}`);
 | 
			
		||||
                setToastData({
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ import { useFeaturesSort } from 'hooks/useFeaturesSort';
 | 
			
		||||
 | 
			
		||||
export const FeatureToggleListContainer = () => {
 | 
			
		||||
    const { uiConfig } = useUiConfig();
 | 
			
		||||
    const { features, loading } = useFeatures();
 | 
			
		||||
    const { features = [], loading } = useFeatures();
 | 
			
		||||
    const { filtered, filter, setFilter } = useFeaturesFilter(features);
 | 
			
		||||
    const { sorted, sort, setSort } = useFeaturesSort(filtered);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,11 +2,11 @@ import { Tooltip } from '@material-ui/core';
 | 
			
		||||
import { useLocationSettings } from 'hooks/useLocationSettings';
 | 
			
		||||
import { formatDateYMD, formatDateYMDHMS } from 'utils/formatDate';
 | 
			
		||||
 | 
			
		||||
interface CreatedAtProps {
 | 
			
		||||
interface ICreatedAtProps {
 | 
			
		||||
    time: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CreatedAt = ({ time }: CreatedAtProps) => {
 | 
			
		||||
const CreatedAt = ({ time }: ICreatedAtProps) => {
 | 
			
		||||
    const { locationSettings } = useLocationSettings();
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,10 @@ export const FeatureNotFound = () => {
 | 
			
		||||
        { name: featureId }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (!archivedFeatures) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const isArchived = archivedFeatures.some(archivedFeature => {
 | 
			
		||||
        return archivedFeature.name === featureId;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import FeatureOverviewEnvironmentStrategy from './FeatureOverviewEnvironmentStrategy/FeatureOverviewEnvironmentStrategy';
 | 
			
		||||
 | 
			
		||||
interface FeatureOverviewEnvironmentStrategiesProps {
 | 
			
		||||
interface IFeatureOverviewEnvironmentStrategiesProps {
 | 
			
		||||
    strategies: IFeatureStrategy[];
 | 
			
		||||
    environmentName: string;
 | 
			
		||||
}
 | 
			
		||||
@ -9,7 +9,7 @@ interface FeatureOverviewEnvironmentStrategiesProps {
 | 
			
		||||
const FeatureOverviewEnvironmentStrategies = ({
 | 
			
		||||
    strategies,
 | 
			
		||||
    environmentName,
 | 
			
		||||
}: FeatureOverviewEnvironmentStrategiesProps) => {
 | 
			
		||||
}: IFeatureOverviewEnvironmentStrategiesProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            {strategies.map(strategy => (
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@ function getColor(unit?: string): string {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface FeatureStatusProps {
 | 
			
		||||
interface IFeatureStatusProps {
 | 
			
		||||
    lastSeenAt?: string;
 | 
			
		||||
    tooltipPlacement?: TooltipProps['placement'];
 | 
			
		||||
}
 | 
			
		||||
@ -54,7 +54,7 @@ interface FeatureStatusProps {
 | 
			
		||||
const FeatureStatus = ({
 | 
			
		||||
    lastSeenAt,
 | 
			
		||||
    tooltipPlacement,
 | 
			
		||||
}: FeatureStatusProps) => {
 | 
			
		||||
}: IFeatureStatusProps) => {
 | 
			
		||||
    const styles = useStyles();
 | 
			
		||||
 | 
			
		||||
    const Wrapper = (
 | 
			
		||||
 | 
			
		||||
@ -3,11 +3,11 @@ import { Tooltip } from '@material-ui/core';
 | 
			
		||||
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
 | 
			
		||||
import useFeatureTypes from 'hooks/api/getters/useFeatureTypes/useFeatureTypes';
 | 
			
		||||
 | 
			
		||||
interface FeatureTypeProps {
 | 
			
		||||
interface IFeatureTypeProps {
 | 
			
		||||
    type: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FeatureStatus = ({ type }: FeatureTypeProps) => {
 | 
			
		||||
const FeatureStatus = ({ type }: IFeatureTypeProps) => {
 | 
			
		||||
    const styles = useStyles();
 | 
			
		||||
    const { featureTypes } = useFeatureTypes();
 | 
			
		||||
    const IconComponent = getFeatureTypeIcons(type);
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { Redirect, useParams } from 'react-router-dom';
 | 
			
		||||
import { useFeatures } from 'hooks/api/getters/useFeatures/useFeatures';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import { getTogglePath } from 'utils/routePathHelpers';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
interface IRedirectParams {
 | 
			
		||||
    name: string;
 | 
			
		||||
@ -10,12 +10,12 @@ interface IRedirectParams {
 | 
			
		||||
 | 
			
		||||
const RedirectFeatureView = () => {
 | 
			
		||||
    const { name } = useParams<IRedirectParams>();
 | 
			
		||||
    const { features } = useFeatures();
 | 
			
		||||
    const [featureToggle, setFeatureToggle] = useState<IFeatureToggle>();
 | 
			
		||||
    const { features = [] } = useFeatures();
 | 
			
		||||
    const [featureToggle, setFeatureToggle] = useState<FeatureSchema>();
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        const toggle = features.find(
 | 
			
		||||
            (toggle: IFeatureToggle) => toggle.name === name
 | 
			
		||||
            (toggle: FeatureSchema) => toggle.name === name
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        setFeatureToggle(toggle);
 | 
			
		||||
 | 
			
		||||
@ -4,11 +4,11 @@ import ConditionallyRender from 'component/common/ConditionallyRender';
 | 
			
		||||
import ReportToggleList from 'component/Reporting/ReportToggleList/ReportToggleList';
 | 
			
		||||
import { ReportCard } from 'component/Reporting/ReportCard/ReportCard';
 | 
			
		||||
 | 
			
		||||
interface ProjectHealthProps {
 | 
			
		||||
interface IProjectHealthProps {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ProjectHealth = ({ projectId }: ProjectHealthProps) => {
 | 
			
		||||
const ProjectHealth = ({ projectId }: IProjectHealthProps) => {
 | 
			
		||||
    const { healthReport, refetchHealthReport, error } =
 | 
			
		||||
        useHealthReport(projectId);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,11 +3,11 @@ import { ProjectFeatureToggles } from './ProjectFeatureToggles/ProjectFeatureTog
 | 
			
		||||
import ProjectInfo from './ProjectInfo/ProjectInfo';
 | 
			
		||||
import { useStyles } from './Project.styles';
 | 
			
		||||
 | 
			
		||||
interface ProjectOverviewProps {
 | 
			
		||||
interface IProjectOverviewProps {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ProjectOverview = ({ projectId }: ProjectOverviewProps) => {
 | 
			
		||||
const ProjectOverview = ({ projectId }: IProjectOverviewProps) => {
 | 
			
		||||
    const { project, loading } = useProject(projectId, {
 | 
			
		||||
        refreshInterval: 10000,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@ -23,11 +23,13 @@ import { getEnabledEnvs } from './helpers';
 | 
			
		||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
 | 
			
		||||
import { useCommonStyles } from 'themes/commonStyles';
 | 
			
		||||
 | 
			
		||||
interface ProjectEnvironmentListProps {
 | 
			
		||||
interface IProjectEnvironmentListProps {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ProjectEnvironmentList = ({ projectId }: ProjectEnvironmentListProps) => {
 | 
			
		||||
const ProjectEnvironmentList = ({
 | 
			
		||||
    projectId,
 | 
			
		||||
}: IProjectEnvironmentListProps) => {
 | 
			
		||||
    // api state
 | 
			
		||||
    const [envs, setEnvs] = useState<IProjectEnvironment[]>([]);
 | 
			
		||||
    const { setToastData, setToastApiError } = useToast();
 | 
			
		||||
 | 
			
		||||
@ -13,12 +13,12 @@ import styles from '../../strategies.module.scss';
 | 
			
		||||
import { TogglesLinkList } from 'component/strategies/TogglesLinkList/TogglesLinkList';
 | 
			
		||||
import { IParameter, IStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { IApplication } from 'interfaces/application';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
interface IStrategyDetailsProps {
 | 
			
		||||
    strategy: IStrategy;
 | 
			
		||||
    applications: IApplication[];
 | 
			
		||||
    toggles: IFeatureToggle[];
 | 
			
		||||
    toggles: FeatureSchema[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const StrategyDetails = ({
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ import ConditionallyRender from 'component/common/ConditionallyRender';
 | 
			
		||||
export const StrategyView = () => {
 | 
			
		||||
    const { name } = useParams<{ name: string }>();
 | 
			
		||||
    const { strategies } = useStrategies();
 | 
			
		||||
    const { features } = useFeatures();
 | 
			
		||||
    const { features = [] } = useFeatures();
 | 
			
		||||
    const { applications } = useApplications();
 | 
			
		||||
    const history = useHistory();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -9,10 +9,10 @@ import { Pause, PlayArrow } from '@material-ui/icons';
 | 
			
		||||
import styles from 'component/common/common.module.scss';
 | 
			
		||||
import { Link } from 'react-router-dom';
 | 
			
		||||
import ConditionallyRender from 'component/common/ConditionallyRender';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
interface ITogglesLinkListProps {
 | 
			
		||||
    toggles: IFeatureToggle[];
 | 
			
		||||
    toggles: FeatureSchema[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TogglesLinkList = ({ toggles }: ITogglesLinkListProps) => (
 | 
			
		||||
 | 
			
		||||
@ -8,13 +8,11 @@ Object {
 | 
			
		||||
  },
 | 
			
		||||
  "filtered": Array [
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "a",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -80,13 +78,11 @@ Object {
 | 
			
		||||
  },
 | 
			
		||||
  "filtered": Array [
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "1",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -95,13 +91,11 @@ Object {
 | 
			
		||||
      "variants": Array [],
 | 
			
		||||
    },
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "1",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -110,13 +104,11 @@ Object {
 | 
			
		||||
      "variants": Array [],
 | 
			
		||||
    },
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "1",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -136,13 +128,11 @@ Object {
 | 
			
		||||
  },
 | 
			
		||||
  "filtered": Array [
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "2",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -151,13 +141,11 @@ Object {
 | 
			
		||||
      "variants": Array [],
 | 
			
		||||
    },
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "2",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -178,13 +166,11 @@ Object {
 | 
			
		||||
  },
 | 
			
		||||
  "filtered": Array [
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "abc",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
@ -193,13 +179,11 @@ Object {
 | 
			
		||||
      "variants": Array [],
 | 
			
		||||
    },
 | 
			
		||||
    Object {
 | 
			
		||||
      "archived": false,
 | 
			
		||||
      "createdAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "createdAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "description": "1",
 | 
			
		||||
      "enabled": false,
 | 
			
		||||
      "environments": Array [],
 | 
			
		||||
      "impressionData": false,
 | 
			
		||||
      "lastSeenAt": "2006-01-02T15:04:05Z",
 | 
			
		||||
      "lastSeenAt": 2006-01-02T15:04:05.000Z,
 | 
			
		||||
      "name": "1",
 | 
			
		||||
      "project": "abcd",
 | 
			
		||||
      "stale": false,
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
import { IFeatureTogglePayload } from 'interfaces/featureToggle';
 | 
			
		||||
import { ITag } from 'interfaces/tags';
 | 
			
		||||
import useAPI from '../useApi/useApi';
 | 
			
		||||
import { Operation } from 'fast-json-patch';
 | 
			
		||||
import { IConstraint } from 'interfaces/strategy';
 | 
			
		||||
import { CreateFeatureSchema } from 'openapi';
 | 
			
		||||
import { openApiAdmin } from 'utils/openapiClient';
 | 
			
		||||
 | 
			
		||||
const useFeatureApi = () => {
 | 
			
		||||
    const { makeRequest, createRequest, errors, loading } = useAPI({
 | 
			
		||||
@ -38,21 +39,12 @@ const useFeatureApi = () => {
 | 
			
		||||
 | 
			
		||||
    const createFeatureToggle = async (
 | 
			
		||||
        projectId: string,
 | 
			
		||||
        featureToggle: IFeatureTogglePayload
 | 
			
		||||
        createFeatureSchema: CreateFeatureSchema
 | 
			
		||||
    ) => {
 | 
			
		||||
        const path = `api/admin/projects/${projectId}/features`;
 | 
			
		||||
        const req = createRequest(path, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            body: JSON.stringify(featureToggle),
 | 
			
		||||
        return openApiAdmin.apiAdminProjectsProjectIdFeaturesPost({
 | 
			
		||||
            projectId,
 | 
			
		||||
            createFeatureSchema,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            const res = await makeRequest(req.caller, req.id);
 | 
			
		||||
 | 
			
		||||
            return res;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const toggleFeatureEnvironmentOn = async (
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								frontend/src/hooks/api/getters/useApiGetter/useApiGetter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								frontend/src/hooks/api/getters/useApiGetter/useApiGetter.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
import useSWR, { SWRConfiguration, mutate } from 'swr';
 | 
			
		||||
import { useCallback } from 'react';
 | 
			
		||||
 | 
			
		||||
type CacheKey = 'apiAdminFeaturesGet' | 'apiAdminArchiveFeaturesGet';
 | 
			
		||||
 | 
			
		||||
interface IUseApiGetterOutput<T> {
 | 
			
		||||
    data?: T;
 | 
			
		||||
    refetch: () => void;
 | 
			
		||||
    error?: Error | undefined;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useApiGetter = <T>(
 | 
			
		||||
    cacheKey: CacheKey,
 | 
			
		||||
    fetcher: () => Promise<T>,
 | 
			
		||||
    options?: SWRConfiguration
 | 
			
		||||
): IUseApiGetterOutput<T> => {
 | 
			
		||||
    const { data, error } = useSWR<T>(cacheKey, fetcher, options);
 | 
			
		||||
 | 
			
		||||
    const refetch = useCallback(() => {
 | 
			
		||||
        mutate(cacheKey).catch(console.warn);
 | 
			
		||||
    }, [cacheKey]);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        data,
 | 
			
		||||
        error,
 | 
			
		||||
        refetch,
 | 
			
		||||
        loading: !error && !data,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
@ -1,39 +1,24 @@
 | 
			
		||||
import useSWR, { mutate, SWRConfiguration } from 'swr';
 | 
			
		||||
import { useCallback } from 'react';
 | 
			
		||||
import { formatApiPath } from 'utils/formatPath';
 | 
			
		||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
 | 
			
		||||
const PATH = formatApiPath('api/admin/features');
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
import { openApiAdmin } from 'utils/openapiClient';
 | 
			
		||||
import { useApiGetter } from 'hooks/api/getters/useApiGetter/useApiGetter';
 | 
			
		||||
 | 
			
		||||
export interface IUseFeaturesOutput {
 | 
			
		||||
    features: IFeatureToggle[];
 | 
			
		||||
    features?: FeatureSchema[];
 | 
			
		||||
    refetchFeatures: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
    error?: Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useFeatures = (options?: SWRConfiguration): IUseFeaturesOutput => {
 | 
			
		||||
    const { data, error } = useSWR<{ features: IFeatureToggle[] }>(
 | 
			
		||||
        PATH,
 | 
			
		||||
        fetchFeatures,
 | 
			
		||||
        options
 | 
			
		||||
export const useFeatures = (): IUseFeaturesOutput => {
 | 
			
		||||
    const { data, refetch, loading, error } = useApiGetter(
 | 
			
		||||
        'apiAdminFeaturesGet',
 | 
			
		||||
        () => openApiAdmin.apiAdminFeaturesGet()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const refetchFeatures = useCallback(() => {
 | 
			
		||||
        mutate(PATH).catch(console.warn);
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        features: data?.features || [],
 | 
			
		||||
        loading: !error && !data,
 | 
			
		||||
        refetchFeatures,
 | 
			
		||||
        features: data?.features,
 | 
			
		||||
        refetchFeatures: refetch,
 | 
			
		||||
        loading,
 | 
			
		||||
        error,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const fetchFeatures = () => {
 | 
			
		||||
    return fetch(PATH, { method: 'GET' })
 | 
			
		||||
        .then(handleErrorResponses('Features'))
 | 
			
		||||
        .then(res => res.json());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,41 +1,24 @@
 | 
			
		||||
import useSWR, { mutate, SWRConfiguration } from 'swr';
 | 
			
		||||
import { useCallback } from 'react';
 | 
			
		||||
import { formatApiPath } from 'utils/formatPath';
 | 
			
		||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import { openApiAdmin } from 'utils/openapiClient';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
import { useApiGetter } from 'hooks/api/getters/useApiGetter/useApiGetter';
 | 
			
		||||
 | 
			
		||||
const PATH = formatApiPath('api/admin/archive/features');
 | 
			
		||||
 | 
			
		||||
export interface UseFeaturesArchiveOutput {
 | 
			
		||||
    archivedFeatures: IFeatureToggle[];
 | 
			
		||||
export interface IUseFeaturesArchiveOutput {
 | 
			
		||||
    archivedFeatures?: FeatureSchema[];
 | 
			
		||||
    refetchArchived: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
    error?: Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useFeaturesArchive = (
 | 
			
		||||
    options?: SWRConfiguration
 | 
			
		||||
): UseFeaturesArchiveOutput => {
 | 
			
		||||
    const { data, error } = useSWR<{ features: IFeatureToggle[] }>(
 | 
			
		||||
        PATH,
 | 
			
		||||
        fetchArchivedFeatures,
 | 
			
		||||
        options
 | 
			
		||||
export const useFeaturesArchive = (): IUseFeaturesArchiveOutput => {
 | 
			
		||||
    const { data, refetch, loading, error } = useApiGetter(
 | 
			
		||||
        'apiAdminArchiveFeaturesGet',
 | 
			
		||||
        () => openApiAdmin.apiAdminArchiveFeaturesGet()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const refetchArchived = useCallback(() => {
 | 
			
		||||
        mutate(PATH).catch(console.warn);
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        archivedFeatures: data?.features || [],
 | 
			
		||||
        refetchArchived,
 | 
			
		||||
        loading: !error && !data,
 | 
			
		||||
        archivedFeatures: data?.features,
 | 
			
		||||
        refetchArchived: refetch,
 | 
			
		||||
        loading,
 | 
			
		||||
        error,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const fetchArchivedFeatures = () => {
 | 
			
		||||
    return fetch(PATH, { method: 'GET' })
 | 
			
		||||
        .then(handleErrorResponses('Archive'))
 | 
			
		||||
        .then(res => res.json());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -4,14 +4,14 @@ import { formatApiPath } from 'utils/formatPath';
 | 
			
		||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
			
		||||
import { ISegment } from 'interfaces/segment';
 | 
			
		||||
 | 
			
		||||
export interface UseSegmentOutput {
 | 
			
		||||
export interface IUseSegmentOutput {
 | 
			
		||||
    segment?: ISegment;
 | 
			
		||||
    refetchSegment: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
    error?: Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useSegment = (id: number): UseSegmentOutput => {
 | 
			
		||||
export const useSegment = (id: number): IUseSegmentOutput => {
 | 
			
		||||
    const path = formatApiPath(`api/admin/segments/${id}`);
 | 
			
		||||
    const { data, error } = useSWR<ISegment>(path, () => fetchSegment(path));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,14 +6,14 @@ import { ISegment } from 'interfaces/segment';
 | 
			
		||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
			
		||||
import { IFlags } from 'interfaces/uiConfig';
 | 
			
		||||
 | 
			
		||||
export interface UseSegmentsOutput {
 | 
			
		||||
export interface IUseSegmentsOutput {
 | 
			
		||||
    segments?: ISegment[];
 | 
			
		||||
    refetchSegments: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
    error?: Error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useSegments = (strategyId?: string): UseSegmentsOutput => {
 | 
			
		||||
export const useSegments = (strategyId?: string): IUseSegmentsOutput => {
 | 
			
		||||
    const { uiConfig } = useUiConfig();
 | 
			
		||||
 | 
			
		||||
    const { data, error, mutate } = useSWR(
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import { formatApiPath } from 'utils/formatPath';
 | 
			
		||||
import handleErrorResponses from '../httpErrorResponseHandler';
 | 
			
		||||
import { IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
export interface useStrategiesBySegmentOutput {
 | 
			
		||||
export interface IUseStrategiesBySegmentOutput {
 | 
			
		||||
    strategies?: IFeatureStrategy[];
 | 
			
		||||
    refetchUsedSegments: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
@ -13,7 +13,7 @@ export interface useStrategiesBySegmentOutput {
 | 
			
		||||
 | 
			
		||||
export const useStrategiesBySegment = (
 | 
			
		||||
    id: number
 | 
			
		||||
): useStrategiesBySegmentOutput => {
 | 
			
		||||
): IUseStrategiesBySegmentOutput => {
 | 
			
		||||
    const path = formatApiPath(`api/admin/segments/${id}/strategies`);
 | 
			
		||||
    const { data, error } = useSWR(path, () => fetchUsedSegment(path));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
import { renderHook, act } from '@testing-library/react-hooks';
 | 
			
		||||
import { useFeaturesFilter } from 'hooks/useFeaturesFilter';
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import { IConstraint, IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
import parseISO from 'date-fns/parseISO';
 | 
			
		||||
 | 
			
		||||
test('useFeaturesFilter empty', () => {
 | 
			
		||||
    const { result } = renderHook(() => useFeaturesFilter([]));
 | 
			
		||||
@ -88,22 +89,20 @@ test('useFeaturesFilter constraints', () => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mockFeatureToggle = (
 | 
			
		||||
    overrides?: Partial<IFeatureToggle>
 | 
			
		||||
): IFeatureToggle => {
 | 
			
		||||
    overrides?: Partial<FeatureSchema>
 | 
			
		||||
): FeatureSchema => {
 | 
			
		||||
    return {
 | 
			
		||||
        name: '1',
 | 
			
		||||
        description: '1',
 | 
			
		||||
        type: '1',
 | 
			
		||||
        project: '1',
 | 
			
		||||
        archived: false,
 | 
			
		||||
        enabled: false,
 | 
			
		||||
        stale: false,
 | 
			
		||||
        impressionData: false,
 | 
			
		||||
        strategies: [],
 | 
			
		||||
        variants: [],
 | 
			
		||||
        environments: [],
 | 
			
		||||
        createdAt: '2006-01-02T15:04:05Z',
 | 
			
		||||
        lastSeenAt: '2006-01-02T15:04:05Z',
 | 
			
		||||
        createdAt: parseISO('2006-01-02T15:04:05Z'),
 | 
			
		||||
        lastSeenAt: parseISO('2006-01-02T15:04:05Z'),
 | 
			
		||||
        ...overrides,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { IFeatureToggle } from 'interfaces/featureToggle';
 | 
			
		||||
import React, { useMemo } from 'react';
 | 
			
		||||
import { createGlobalStateHook } from 'hooks/useGlobalState';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
export interface IFeaturesFilter {
 | 
			
		||||
    query?: string;
 | 
			
		||||
@ -8,7 +8,7 @@ export interface IFeaturesFilter {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IFeaturesSortOutput {
 | 
			
		||||
    filtered: IFeatureToggle[];
 | 
			
		||||
    filtered: FeatureSchema[];
 | 
			
		||||
    filter: IFeaturesFilter;
 | 
			
		||||
    setFilter: React.Dispatch<React.SetStateAction<IFeaturesFilter>>;
 | 
			
		||||
}
 | 
			
		||||
@ -21,7 +21,7 @@ const useFeaturesFilterState = createGlobalStateHook<IFeaturesFilter>(
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const useFeaturesFilter = (
 | 
			
		||||
    features: IFeatureToggle[]
 | 
			
		||||
    features: FeatureSchema[]
 | 
			
		||||
): IFeaturesSortOutput => {
 | 
			
		||||
    const [filter, setFilter] = useFeaturesFilterState();
 | 
			
		||||
 | 
			
		||||
@ -37,9 +37,9 @@ export const useFeaturesFilter = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const filterFeatures = (
 | 
			
		||||
    features: IFeatureToggle[],
 | 
			
		||||
    features: FeatureSchema[],
 | 
			
		||||
    filter: IFeaturesFilter
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return filterFeaturesByQuery(
 | 
			
		||||
        filterFeaturesByProject(features, filter),
 | 
			
		||||
        filter
 | 
			
		||||
@ -47,18 +47,18 @@ const filterFeatures = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const filterFeaturesByProject = (
 | 
			
		||||
    features: IFeatureToggle[],
 | 
			
		||||
    features: FeatureSchema[],
 | 
			
		||||
    filter: IFeaturesFilter
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return filter.project === '*'
 | 
			
		||||
        ? features
 | 
			
		||||
        : features.filter(f => f.project === filter.project);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const filterFeaturesByQuery = (
 | 
			
		||||
    features: IFeatureToggle[],
 | 
			
		||||
    features: FeatureSchema[],
 | 
			
		||||
    filter: IFeaturesFilter
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    if (!filter.query) {
 | 
			
		||||
        return features;
 | 
			
		||||
    }
 | 
			
		||||
@ -78,11 +78,14 @@ const filterFeaturesByQuery = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const filterFeatureByRegExp = (
 | 
			
		||||
    feature: IFeatureToggle,
 | 
			
		||||
    feature: FeatureSchema,
 | 
			
		||||
    filter: IFeaturesFilter,
 | 
			
		||||
    regExp: RegExp
 | 
			
		||||
): boolean => {
 | 
			
		||||
    if (regExp.test(feature.name) || regExp.test(feature.description)) {
 | 
			
		||||
    if (
 | 
			
		||||
        regExp.test(feature.name) ||
 | 
			
		||||
        (feature.description && regExp.test(feature.description))
 | 
			
		||||
    ) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,12 @@
 | 
			
		||||
import { IFeatureToggle } from '../interfaces/featureToggle';
 | 
			
		||||
import React, { useMemo } from 'react';
 | 
			
		||||
import { getBasePath } from 'utils/formatPath';
 | 
			
		||||
import { createPersistentGlobalStateHook } from './usePersistentGlobalState';
 | 
			
		||||
import { parseISO } from 'date-fns';
 | 
			
		||||
import {
 | 
			
		||||
    expired,
 | 
			
		||||
    getDiffInDays,
 | 
			
		||||
    toggleExpiryByTypeMap,
 | 
			
		||||
} from 'component/Reporting/utils';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
type FeaturesSortType =
 | 
			
		||||
    | 'name'
 | 
			
		||||
@ -27,7 +26,7 @@ interface IFeaturesSort {
 | 
			
		||||
 | 
			
		||||
export interface IFeaturesSortOutput {
 | 
			
		||||
    sort: IFeaturesSort;
 | 
			
		||||
    sorted: IFeatureToggle[];
 | 
			
		||||
    sorted: FeatureSchema[];
 | 
			
		||||
    setSort: React.Dispatch<React.SetStateAction<IFeaturesSort>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -44,7 +43,7 @@ const useFeaturesSortState = createPersistentGlobalStateHook<IFeaturesSort>(
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const useFeaturesSort = (
 | 
			
		||||
    features: IFeatureToggle[]
 | 
			
		||||
    features: FeatureSchema[]
 | 
			
		||||
): IFeaturesSortOutput => {
 | 
			
		||||
    const [sort, setSort] = useFeaturesSortState();
 | 
			
		||||
 | 
			
		||||
@ -73,9 +72,9 @@ export const createFeaturesFilterSortOptions =
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
const sortAscendingFeatures = (
 | 
			
		||||
    features: IFeatureToggle[],
 | 
			
		||||
    features: FeatureSchema[],
 | 
			
		||||
    sort: IFeaturesSort
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    switch (sort.type) {
 | 
			
		||||
        case 'enabled':
 | 
			
		||||
            return sortByEnabled(features);
 | 
			
		||||
@ -102,9 +101,9 @@ const sortAscendingFeatures = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortFeatures = (
 | 
			
		||||
    features: IFeatureToggle[],
 | 
			
		||||
    features: FeatureSchema[],
 | 
			
		||||
    sort: IFeaturesSort
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    const sorted = sortAscendingFeatures(features, sort);
 | 
			
		||||
 | 
			
		||||
    if (sort.desc) {
 | 
			
		||||
@ -115,84 +114,97 @@ const sortFeatures = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByEnabled = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
    features: Readonly<FeatureSchema[]>
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) =>
 | 
			
		||||
        a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByStale = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
const sortByStale = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) =>
 | 
			
		||||
        a.stale === b.stale ? 0 : a.stale ? -1 : 1
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByLastSeen = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
    features: Readonly<FeatureSchema[]>
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) =>
 | 
			
		||||
        a.lastSeenAt && b.lastSeenAt
 | 
			
		||||
            ? b.lastSeenAt.localeCompare(a.lastSeenAt)
 | 
			
		||||
            ? compareNullableDates(b.lastSeenAt, a.lastSeenAt)
 | 
			
		||||
            : a.lastSeenAt
 | 
			
		||||
            ? -1
 | 
			
		||||
            : b.lastSeenAt
 | 
			
		||||
            ? 1
 | 
			
		||||
            : b.createdAt.localeCompare(a.createdAt)
 | 
			
		||||
            : compareNullableDates(b.createdAt, a.createdAt)
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByCreated = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
    return [...features].sort((a, b) => b.createdAt.localeCompare(a.createdAt));
 | 
			
		||||
    features: Readonly<FeatureSchema[]>
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) =>
 | 
			
		||||
        compareNullableDates(b.createdAt, a.createdAt)
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByName = (features: Readonly<IFeatureToggle[]>): IFeatureToggle[] => {
 | 
			
		||||
const sortByName = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) => a.name.localeCompare(b.name));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByProject = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
    features: Readonly<FeatureSchema[]>
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) => a.project.localeCompare(b.project));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByType = (features: Readonly<IFeatureToggle[]>): IFeatureToggle[] => {
 | 
			
		||||
    return [...features].sort((a, b) => a.type.localeCompare(b.type));
 | 
			
		||||
const sortByType = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) =>
 | 
			
		||||
        a.type && b.type
 | 
			
		||||
            ? a.type.localeCompare(b.type)
 | 
			
		||||
            : a.type
 | 
			
		||||
            ? 1
 | 
			
		||||
            : b.type
 | 
			
		||||
            ? -1
 | 
			
		||||
            : 0
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const compareNullableDates = (
 | 
			
		||||
    a: Date | null | undefined,
 | 
			
		||||
    b: Date | null | undefined
 | 
			
		||||
): number => {
 | 
			
		||||
    return a && b ? a.getTime() - b.getTime() : a ? 1 : b ? -1 : 0;
 | 
			
		||||
};
 | 
			
		||||
const sortByExpired = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
    features: Readonly<FeatureSchema[]>
 | 
			
		||||
): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) => {
 | 
			
		||||
        const now = new Date();
 | 
			
		||||
        const dateA = parseISO(a.createdAt);
 | 
			
		||||
        const dateB = parseISO(b.createdAt);
 | 
			
		||||
        const dateA = a.createdAt!;
 | 
			
		||||
        const dateB = b.createdAt!;
 | 
			
		||||
 | 
			
		||||
        const diffA = getDiffInDays(dateA, now);
 | 
			
		||||
        const diffB = getDiffInDays(dateB, now);
 | 
			
		||||
 | 
			
		||||
        if (!expired(diffA, a.type) && expired(diffB, b.type)) {
 | 
			
		||||
        if (!expired(diffA, a.type!) && expired(diffB, b.type!)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (expired(diffA, a.type) && !expired(diffB, b.type)) {
 | 
			
		||||
        if (expired(diffA, a.type!) && !expired(diffB, b.type!)) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const expiration = toggleExpiryByTypeMap as Record<string, number>;
 | 
			
		||||
        const expiredByA = diffA - expiration[a.type];
 | 
			
		||||
        const expiredByB = diffB - expiration[b.type];
 | 
			
		||||
        const expiredByA = a.type ? diffA - expiration[a.type] : 0;
 | 
			
		||||
        const expiredByB = b.type ? diffB - expiration[b.type] : 0;
 | 
			
		||||
 | 
			
		||||
        return expiredByB - expiredByA;
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const sortByStatus = (
 | 
			
		||||
    features: Readonly<IFeatureToggle[]>
 | 
			
		||||
): IFeatureToggle[] => {
 | 
			
		||||
const sortByStatus = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
 | 
			
		||||
    return [...features].sort((a, b) => {
 | 
			
		||||
        if (a.stale) {
 | 
			
		||||
            return 1;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										262
									
								
								frontend/src/openapi/apis/AdminApi.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								frontend/src/openapi/apis/AdminApi.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,262 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import * as runtime from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    ChangeProjectSchema,
 | 
			
		||||
    ChangeProjectSchemaFromJSON,
 | 
			
		||||
    ChangeProjectSchemaToJSON,
 | 
			
		||||
    CreateFeatureSchema,
 | 
			
		||||
    CreateFeatureSchemaFromJSON,
 | 
			
		||||
    CreateFeatureSchemaToJSON,
 | 
			
		||||
    FeatureSchema,
 | 
			
		||||
    FeatureSchemaFromJSON,
 | 
			
		||||
    FeatureSchemaToJSON,
 | 
			
		||||
    FeaturesSchema,
 | 
			
		||||
    FeaturesSchemaFromJSON,
 | 
			
		||||
    FeaturesSchemaToJSON,
 | 
			
		||||
} from '../models';
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
    changeProjectSchema: ChangeProjectSchema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameGetRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesGetRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesPostRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    createFeatureSchema: CreateFeatureSchema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
export class AdminApi extends runtime.BaseAPI {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminArchiveFeaturesGetRaw(initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/archive/features`,
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => FeaturesSchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminArchiveFeaturesGet(initOverrides?: RequestInit): Promise<FeaturesSchema> {
 | 
			
		||||
        const response = await this.apiAdminArchiveFeaturesGetRaw(initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminFeaturesGetRaw(initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/features/`,
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => FeaturesSchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminFeaturesGet(initOverrides?: RequestInit): Promise<FeaturesSchema> {
 | 
			
		||||
        const response = await this.apiAdminFeaturesGetRaw(initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<void>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.changeProjectSchema === null || requestParameters.changeProjectSchema === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('changeProjectSchema','Required parameter requestParameters.changeProjectSchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        headerParameters['Content-Type'] = 'application/json';
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features/{featureName}/changeProject`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))),
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
            body: ChangeProjectSchemaToJSON(requestParameters.changeProjectSchema),
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.VoidApiResponse(response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<void> {
 | 
			
		||||
        await this.apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters, initOverrides);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameGetRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameGetRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameGet.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameGet.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features/{featureName}`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))),
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => FeatureSchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameGet(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameGetRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
 | 
			
		||||
        const response = await this.apiAdminProjectsProjectIdFeaturesFeatureNameGetRaw(requestParameters, initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesGetRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesGetRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeaturesSchema>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesGet.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))),
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => FeaturesSchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesGet(requestParameters: ApiAdminProjectsProjectIdFeaturesGetRequest, initOverrides?: RequestInit): Promise<FeaturesSchema> {
 | 
			
		||||
        const response = await this.apiAdminProjectsProjectIdFeaturesGetRaw(requestParameters, initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesPostRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesPostRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.createFeatureSchema === null || requestParameters.createFeatureSchema === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('createFeatureSchema','Required parameter requestParameters.createFeatureSchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        headerParameters['Content-Type'] = 'application/json';
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))),
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
            body: CreateFeatureSchemaToJSON(requestParameters.createFeatureSchema),
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => FeatureSchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesPost(requestParameters: ApiAdminProjectsProjectIdFeaturesPostRequest, initOverrides?: RequestInit): Promise<FeatureSchema> {
 | 
			
		||||
        const response = await this.apiAdminProjectsProjectIdFeaturesPostRaw(requestParameters, initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								frontend/src/openapi/apis/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								frontend/src/openapi/apis/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export * from './AdminApi';
 | 
			
		||||
							
								
								
									
										5
									
								
								frontend/src/openapi/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								frontend/src/openapi/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export * from './runtime';
 | 
			
		||||
export * from './apis';
 | 
			
		||||
export * from './models';
 | 
			
		||||
							
								
								
									
										56
									
								
								frontend/src/openapi/models/ChangeProjectSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/src/openapi/models/ChangeProjectSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface ChangeProjectSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface ChangeProjectSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof ChangeProjectSchema
 | 
			
		||||
     */
 | 
			
		||||
    newProjectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaFromJSON(json: any): ChangeProjectSchema {
 | 
			
		||||
    return ChangeProjectSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeProjectSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'newProjectId': json['newProjectId'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaToJSON(value?: ChangeProjectSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'newProjectId': value.newProjectId,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								frontend/src/openapi/models/ConstraintSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								frontend/src/openapi/models/ConstraintSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface ConstraintSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface ConstraintSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    contextName: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    operator: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<string>}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    values?: Array<string>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ConstraintSchemaFromJSON(json: any): ConstraintSchema {
 | 
			
		||||
    return ConstraintSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ConstraintSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ConstraintSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': json['contextName'],
 | 
			
		||||
        'operator': json['operator'],
 | 
			
		||||
        'values': !exists(json, 'values') ? undefined : json['values'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ConstraintSchemaToJSON(value?: ConstraintSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': value.contextName,
 | 
			
		||||
        'operator': value.operator,
 | 
			
		||||
        'values': value.values,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										80
									
								
								frontend/src/openapi/models/CreateFeatureSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								frontend/src/openapi/models/CreateFeatureSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface CreateFeatureSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface CreateFeatureSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateFeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateFeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    type?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateFeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    description?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof CreateFeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    impressionData?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateFeatureSchemaFromJSON(json: any): CreateFeatureSchema {
 | 
			
		||||
    return CreateFeatureSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateFeatureSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreateFeatureSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'type': !exists(json, 'type') ? undefined : json['type'],
 | 
			
		||||
        'description': !exists(json, 'description') ? undefined : json['description'],
 | 
			
		||||
        'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateFeatureSchemaToJSON(value?: CreateFeatureSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'type': value.type,
 | 
			
		||||
        'description': value.description,
 | 
			
		||||
        'impressionData': value.impressionData,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										149
									
								
								frontend/src/openapi/models/FeatureSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								frontend/src/openapi/models/FeatureSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    StrategySchema,
 | 
			
		||||
    StrategySchemaFromJSON,
 | 
			
		||||
    StrategySchemaFromJSONTyped,
 | 
			
		||||
    StrategySchemaToJSON,
 | 
			
		||||
} from './StrategySchema';
 | 
			
		||||
import {
 | 
			
		||||
    VariantSchema,
 | 
			
		||||
    VariantSchemaFromJSON,
 | 
			
		||||
    VariantSchemaFromJSONTyped,
 | 
			
		||||
    VariantSchemaToJSON,
 | 
			
		||||
} from './VariantSchema';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeatureSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface FeatureSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    type?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    description?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    project: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    enabled?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    stale?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    impressionData?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Date}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    createdAt?: Date | null;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Date}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    lastSeenAt?: Date | null;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<StrategySchema>}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    strategies?: Array<StrategySchema>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<VariantSchema>}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    variants?: Array<VariantSchema>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaFromJSON(json: any): FeatureSchema {
 | 
			
		||||
    return FeatureSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeatureSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'type': !exists(json, 'type') ? undefined : json['type'],
 | 
			
		||||
        'description': !exists(json, 'description') ? undefined : json['description'],
 | 
			
		||||
        'project': json['project'],
 | 
			
		||||
        'enabled': !exists(json, 'enabled') ? undefined : json['enabled'],
 | 
			
		||||
        'stale': !exists(json, 'stale') ? undefined : json['stale'],
 | 
			
		||||
        'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
 | 
			
		||||
        'createdAt': !exists(json, 'createdAt') ? undefined : (json['createdAt'] === null ? null : new Date(json['createdAt'])),
 | 
			
		||||
        'lastSeenAt': !exists(json, 'lastSeenAt') ? undefined : (json['lastSeenAt'] === null ? null : new Date(json['lastSeenAt'])),
 | 
			
		||||
        'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(StrategySchemaFromJSON)),
 | 
			
		||||
        'variants': !exists(json, 'variants') ? undefined : ((json['variants'] as Array<any>).map(VariantSchemaFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaToJSON(value?: FeatureSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'type': value.type,
 | 
			
		||||
        'description': value.description,
 | 
			
		||||
        'project': value.project,
 | 
			
		||||
        'enabled': value.enabled,
 | 
			
		||||
        'stale': value.stale,
 | 
			
		||||
        'impressionData': value.impressionData,
 | 
			
		||||
        'createdAt': value.createdAt === undefined ? undefined : (value.createdAt === null ? null : value.createdAt.toISOString().substr(0,10)),
 | 
			
		||||
        'lastSeenAt': value.lastSeenAt === undefined ? undefined : (value.lastSeenAt === null ? null : value.lastSeenAt.toISOString().substr(0,10)),
 | 
			
		||||
        'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(StrategySchemaToJSON)),
 | 
			
		||||
        'variants': value.variants === undefined ? undefined : ((value.variants as Array<any>).map(VariantSchemaToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								frontend/src/openapi/models/FeaturesSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								frontend/src/openapi/models/FeaturesSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    FeatureSchema,
 | 
			
		||||
    FeatureSchemaFromJSON,
 | 
			
		||||
    FeatureSchemaFromJSONTyped,
 | 
			
		||||
    FeatureSchemaToJSON,
 | 
			
		||||
} from './FeatureSchema';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeaturesSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface FeaturesSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {number}
 | 
			
		||||
     * @memberof FeaturesSchema
 | 
			
		||||
     */
 | 
			
		||||
    version: number;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<FeatureSchema>}
 | 
			
		||||
     * @memberof FeaturesSchema
 | 
			
		||||
     */
 | 
			
		||||
    features: Array<FeatureSchema>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFromJSON(json: any): FeaturesSchema {
 | 
			
		||||
    return FeaturesSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeaturesSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'version': json['version'],
 | 
			
		||||
        'features': ((json['features'] as Array<any>).map(FeatureSchemaFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaToJSON(value?: FeaturesSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'version': value.version,
 | 
			
		||||
        'features': ((value.features as Array<any>).map(FeatureSchemaToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								frontend/src/openapi/models/OverrideSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								frontend/src/openapi/models/OverrideSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface OverrideSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface OverrideSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof OverrideSchema
 | 
			
		||||
     */
 | 
			
		||||
    contextName: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<string>}
 | 
			
		||||
     * @memberof OverrideSchema
 | 
			
		||||
     */
 | 
			
		||||
    values: Array<string>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function OverrideSchemaFromJSON(json: any): OverrideSchema {
 | 
			
		||||
    return OverrideSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function OverrideSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): OverrideSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': json['contextName'],
 | 
			
		||||
        'values': json['values'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function OverrideSchemaToJSON(value?: OverrideSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': value.contextName,
 | 
			
		||||
        'values': value.values,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								frontend/src/openapi/models/StrategySchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								frontend/src/openapi/models/StrategySchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    ConstraintSchema,
 | 
			
		||||
    ConstraintSchemaFromJSON,
 | 
			
		||||
    ConstraintSchemaFromJSONTyped,
 | 
			
		||||
    ConstraintSchemaToJSON,
 | 
			
		||||
} from './ConstraintSchema';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface StrategySchema
 | 
			
		||||
 */
 | 
			
		||||
export interface StrategySchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    id: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<ConstraintSchema>}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    constraints: Array<ConstraintSchema>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {object}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    parameters: object;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function StrategySchemaFromJSON(json: any): StrategySchema {
 | 
			
		||||
    return StrategySchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function StrategySchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): StrategySchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'id': json['id'],
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'constraints': ((json['constraints'] as Array<any>).map(ConstraintSchemaFromJSON)),
 | 
			
		||||
        'parameters': json['parameters'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function StrategySchemaToJSON(value?: StrategySchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'id': value.id,
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'constraints': ((value.constraints as Array<any>).map(ConstraintSchemaToJSON)),
 | 
			
		||||
        'parameters': value.parameters,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								frontend/src/openapi/models/VariantSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontend/src/openapi/models/VariantSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    OverrideSchema,
 | 
			
		||||
    OverrideSchemaFromJSON,
 | 
			
		||||
    OverrideSchemaFromJSONTyped,
 | 
			
		||||
    OverrideSchemaToJSON,
 | 
			
		||||
} from './OverrideSchema';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface VariantSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface VariantSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {number}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    weight: number;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    weightType: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    stickiness: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {object}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    payload?: object;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<OverrideSchema>}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    overrides: Array<OverrideSchema>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function VariantSchemaFromJSON(json: any): VariantSchema {
 | 
			
		||||
    return VariantSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function VariantSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): VariantSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'weight': json['weight'],
 | 
			
		||||
        'weightType': json['weightType'],
 | 
			
		||||
        'stickiness': json['stickiness'],
 | 
			
		||||
        'payload': !exists(json, 'payload') ? undefined : json['payload'],
 | 
			
		||||
        'overrides': ((json['overrides'] as Array<any>).map(OverrideSchemaFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function VariantSchemaToJSON(value?: VariantSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'weight': value.weight,
 | 
			
		||||
        'weightType': value.weightType,
 | 
			
		||||
        'stickiness': value.stickiness,
 | 
			
		||||
        'payload': value.payload,
 | 
			
		||||
        'overrides': ((value.overrides as Array<any>).map(OverrideSchemaToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								frontend/src/openapi/models/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								frontend/src/openapi/models/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export * from './ChangeProjectSchema';
 | 
			
		||||
export * from './ConstraintSchema';
 | 
			
		||||
export * from './CreateFeatureSchema';
 | 
			
		||||
export * from './FeatureSchema';
 | 
			
		||||
export * from './FeaturesSchema';
 | 
			
		||||
export * from './OverrideSchema';
 | 
			
		||||
export * from './StrategySchema';
 | 
			
		||||
export * from './VariantSchema';
 | 
			
		||||
							
								
								
									
										320
									
								
								frontend/src/openapi/runtime.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								frontend/src/openapi/runtime.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,320 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0-beta.1
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export const BASE_PATH = "http://localhost:4242".replace(/\/+$/, "");
 | 
			
		||||
 | 
			
		||||
const isBlob = (value: any) => typeof Blob !== 'undefined' && value instanceof Blob;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This is the base class for all generated API classes.
 | 
			
		||||
 */
 | 
			
		||||
export class BaseAPI {
 | 
			
		||||
 | 
			
		||||
    private middleware: Middleware[];
 | 
			
		||||
 | 
			
		||||
    constructor(protected configuration = new Configuration()) {
 | 
			
		||||
        this.middleware = configuration.middleware;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
 | 
			
		||||
        const next = this.clone<T>();
 | 
			
		||||
        next.middleware = next.middleware.concat(...middlewares);
 | 
			
		||||
        return next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
 | 
			
		||||
        const middlewares = preMiddlewares.map((pre) => ({ pre }));
 | 
			
		||||
        return this.withMiddleware<T>(...middlewares);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
 | 
			
		||||
        const middlewares = postMiddlewares.map((post) => ({ post }));
 | 
			
		||||
        return this.withMiddleware<T>(...middlewares);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected async request(context: RequestOpts, initOverrides?: RequestInit): Promise<Response> {
 | 
			
		||||
        const { url, init } = this.createFetchParams(context, initOverrides);
 | 
			
		||||
        const response = await this.fetchApi(url, init);
 | 
			
		||||
        if (response.status >= 200 && response.status < 300) {
 | 
			
		||||
            return response;
 | 
			
		||||
        }
 | 
			
		||||
        throw response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private createFetchParams(context: RequestOpts, initOverrides?: RequestInit) {
 | 
			
		||||
        let url = this.configuration.basePath + context.path;
 | 
			
		||||
        if (context.query !== undefined && Object.keys(context.query).length !== 0) {
 | 
			
		||||
            // only add the querystring to the URL if there are query parameters.
 | 
			
		||||
            // this is done to avoid urls ending with a "?" character which buggy webservers
 | 
			
		||||
            // do not handle correctly sometimes.
 | 
			
		||||
            url += '?' + this.configuration.queryParamsStringify(context.query);
 | 
			
		||||
        }
 | 
			
		||||
        const body = ((typeof FormData !== "undefined" && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body))
 | 
			
		||||
        ? context.body
 | 
			
		||||
        : JSON.stringify(context.body);
 | 
			
		||||
 | 
			
		||||
        const headers = Object.assign({}, this.configuration.headers, context.headers);
 | 
			
		||||
        const init = {
 | 
			
		||||
            method: context.method,
 | 
			
		||||
            headers: headers,
 | 
			
		||||
            body,
 | 
			
		||||
            credentials: this.configuration.credentials,
 | 
			
		||||
            ...initOverrides
 | 
			
		||||
        };
 | 
			
		||||
        return { url, init };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fetchApi = async (url: string, init: RequestInit) => {
 | 
			
		||||
        let fetchParams = { url, init };
 | 
			
		||||
        for (const middleware of this.middleware) {
 | 
			
		||||
            if (middleware.pre) {
 | 
			
		||||
                fetchParams = await middleware.pre({
 | 
			
		||||
                    fetch: this.fetchApi,
 | 
			
		||||
                    ...fetchParams,
 | 
			
		||||
                }) || fetchParams;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
 | 
			
		||||
        for (const middleware of this.middleware) {
 | 
			
		||||
            if (middleware.post) {
 | 
			
		||||
                response = await middleware.post({
 | 
			
		||||
                    fetch: this.fetchApi,
 | 
			
		||||
                    url: fetchParams.url,
 | 
			
		||||
                    init: fetchParams.init,
 | 
			
		||||
                    response: response.clone(),
 | 
			
		||||
                }) || response;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a shallow clone of `this` by constructing a new instance
 | 
			
		||||
     * and then shallow cloning data members.
 | 
			
		||||
     */
 | 
			
		||||
    private clone<T extends BaseAPI>(this: T): T {
 | 
			
		||||
        const constructor = this.constructor as any;
 | 
			
		||||
        const next = new constructor(this.configuration);
 | 
			
		||||
        next.middleware = this.middleware.slice();
 | 
			
		||||
        return next;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export class RequiredError extends Error {
 | 
			
		||||
    name: "RequiredError" = "RequiredError";
 | 
			
		||||
    constructor(public field: string, msg?: string) {
 | 
			
		||||
        super(msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const COLLECTION_FORMATS = {
 | 
			
		||||
    csv: ",",
 | 
			
		||||
    ssv: " ",
 | 
			
		||||
    tsv: "\t",
 | 
			
		||||
    pipes: "|",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type FetchAPI = GlobalFetch['fetch'];
 | 
			
		||||
 | 
			
		||||
export interface ConfigurationParameters {
 | 
			
		||||
    basePath?: string; // override base path
 | 
			
		||||
    fetchApi?: FetchAPI; // override for fetch implementation
 | 
			
		||||
    middleware?: Middleware[]; // middleware to apply before/after fetch requests
 | 
			
		||||
    queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings
 | 
			
		||||
    username?: string; // parameter for basic security
 | 
			
		||||
    password?: string; // parameter for basic security
 | 
			
		||||
    apiKey?: string | ((name: string) => string); // parameter for apiKey security
 | 
			
		||||
    accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string | Promise<string>); // parameter for oauth2 security
 | 
			
		||||
    headers?: HTTPHeaders; //header params we want to use on every request
 | 
			
		||||
    credentials?: RequestCredentials; //value for the credentials param we want to use on each request
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Configuration {
 | 
			
		||||
    constructor(private configuration: ConfigurationParameters = {}) {}
 | 
			
		||||
 | 
			
		||||
    get basePath(): string {
 | 
			
		||||
        return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get fetchApi(): FetchAPI | undefined {
 | 
			
		||||
        return this.configuration.fetchApi;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get middleware(): Middleware[] {
 | 
			
		||||
        return this.configuration.middleware || [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get queryParamsStringify(): (params: HTTPQuery) => string {
 | 
			
		||||
        return this.configuration.queryParamsStringify || querystring;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get username(): string | undefined {
 | 
			
		||||
        return this.configuration.username;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get password(): string | undefined {
 | 
			
		||||
        return this.configuration.password;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get apiKey(): ((name: string) => string) | undefined {
 | 
			
		||||
        const apiKey = this.configuration.apiKey;
 | 
			
		||||
        if (apiKey) {
 | 
			
		||||
            return typeof apiKey === 'function' ? apiKey : () => apiKey;
 | 
			
		||||
        }
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get accessToken(): ((name?: string, scopes?: string[]) => string | Promise<string>) | undefined {
 | 
			
		||||
        const accessToken = this.configuration.accessToken;
 | 
			
		||||
        if (accessToken) {
 | 
			
		||||
            return typeof accessToken === 'function' ? accessToken : async () => accessToken;
 | 
			
		||||
        }
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get headers(): HTTPHeaders | undefined {
 | 
			
		||||
        return this.configuration.headers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get credentials(): RequestCredentials | undefined {
 | 
			
		||||
        return this.configuration.credentials;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Json = any;
 | 
			
		||||
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
 | 
			
		||||
export type HTTPHeaders = { [key: string]: string };
 | 
			
		||||
export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | HTTPQuery };
 | 
			
		||||
export type HTTPBody = Json | FormData | URLSearchParams;
 | 
			
		||||
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
 | 
			
		||||
 | 
			
		||||
export interface FetchParams {
 | 
			
		||||
    url: string;
 | 
			
		||||
    init: RequestInit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RequestOpts {
 | 
			
		||||
    path: string;
 | 
			
		||||
    method: HTTPMethod;
 | 
			
		||||
    headers: HTTPHeaders;
 | 
			
		||||
    query?: HTTPQuery;
 | 
			
		||||
    body?: HTTPBody;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function exists(json: any, key: string) {
 | 
			
		||||
    const value = json[key];
 | 
			
		||||
    return value !== null && value !== undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function querystring(params: HTTPQuery, prefix: string = ''): string {
 | 
			
		||||
    return Object.keys(params)
 | 
			
		||||
        .map((key) => {
 | 
			
		||||
            const fullKey = prefix + (prefix.length ? `[${key}]` : key);
 | 
			
		||||
            const value = params[key];
 | 
			
		||||
            if (value instanceof Array) {
 | 
			
		||||
                const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
 | 
			
		||||
                    .join(`&${encodeURIComponent(fullKey)}=`);
 | 
			
		||||
                return `${encodeURIComponent(fullKey)}=${multiValue}`;
 | 
			
		||||
            }
 | 
			
		||||
            if (value instanceof Date) {
 | 
			
		||||
                return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
 | 
			
		||||
            }
 | 
			
		||||
            if (value instanceof Object) {
 | 
			
		||||
                return querystring(value as HTTPQuery, fullKey);
 | 
			
		||||
            }
 | 
			
		||||
            return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
 | 
			
		||||
        })
 | 
			
		||||
        .filter(part => part.length > 0)
 | 
			
		||||
        .join('&');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function mapValues(data: any, fn: (item: any) => any) {
 | 
			
		||||
  return Object.keys(data).reduce(
 | 
			
		||||
    (acc, key) => ({ ...acc, [key]: fn(data[key]) }),
 | 
			
		||||
    {}
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function canConsumeForm(consumes: Consume[]): boolean {
 | 
			
		||||
    for (const consume of consumes) {
 | 
			
		||||
        if ('multipart/form-data' === consume.contentType) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Consume {
 | 
			
		||||
    contentType: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RequestContext {
 | 
			
		||||
    fetch: FetchAPI;
 | 
			
		||||
    url: string;
 | 
			
		||||
    init: RequestInit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ResponseContext {
 | 
			
		||||
    fetch: FetchAPI;
 | 
			
		||||
    url: string;
 | 
			
		||||
    init: RequestInit;
 | 
			
		||||
    response: Response;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Middleware {
 | 
			
		||||
    pre?(context: RequestContext): Promise<FetchParams | void>;
 | 
			
		||||
    post?(context: ResponseContext): Promise<Response | void>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiResponse<T> {
 | 
			
		||||
    raw: Response;
 | 
			
		||||
    value(): Promise<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ResponseTransformer<T> {
 | 
			
		||||
    (json: any): T;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class JSONApiResponse<T> {
 | 
			
		||||
    constructor(public raw: Response, private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue) {}
 | 
			
		||||
 | 
			
		||||
    async value(): Promise<T> {
 | 
			
		||||
        return this.transformer(await this.raw.json());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class VoidApiResponse {
 | 
			
		||||
    constructor(public raw: Response) {}
 | 
			
		||||
 | 
			
		||||
    async value(): Promise<void> {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class BlobApiResponse {
 | 
			
		||||
    constructor(public raw: Response) {}
 | 
			
		||||
 | 
			
		||||
    async value(): Promise<Blob> {
 | 
			
		||||
        return await this.raw.blob();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class TextApiResponse {
 | 
			
		||||
    constructor(public raw: Response) {}
 | 
			
		||||
 | 
			
		||||
    async value(): Promise<string> {
 | 
			
		||||
        return await this.raw.text();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								frontend/src/types/global-fetch.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								frontend/src/types/global-fetch.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
// Add missing GlobalFetch declaration for the OpenAPI bindings.
 | 
			
		||||
// https://github.com/apollographql/apollo-link/issues/1131#issuecomment-526109609
 | 
			
		||||
declare type GlobalFetch = WindowOrWorkerGlobalScope;
 | 
			
		||||
							
								
								
									
										12
									
								
								frontend/src/utils/openapiClient.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/utils/openapiClient.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
import { Configuration, AdminApi } from 'openapi';
 | 
			
		||||
import { getBasePath } from 'utils/formatPath';
 | 
			
		||||
 | 
			
		||||
const createAdminApi = (): AdminApi => {
 | 
			
		||||
    return new AdminApi(
 | 
			
		||||
        new Configuration({
 | 
			
		||||
            basePath: getBasePath(),
 | 
			
		||||
        })
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const openApiAdmin = createAdminApi();
 | 
			
		||||
@ -1502,6 +1502,29 @@
 | 
			
		||||
    outvariant "^1.2.1"
 | 
			
		||||
    strict-event-emitter "^0.2.0"
 | 
			
		||||
 | 
			
		||||
"@nestjs/common@8.2.6":
 | 
			
		||||
  version "8.2.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-8.2.6.tgz#34cd5cc44082d3525c56c95db42ca0e5277b7d85"
 | 
			
		||||
  integrity sha512-flLYSXunxcKyjbYddrhwbc49uE705MxBt85rS3mHyhDbAIPSGGeZEqME44YyAzCg1NTfJSNe7ztmOce5kNkb9A==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    axios "0.24.0"
 | 
			
		||||
    iterare "1.2.1"
 | 
			
		||||
    tslib "2.3.1"
 | 
			
		||||
    uuid "8.3.2"
 | 
			
		||||
 | 
			
		||||
"@nestjs/core@8.2.6":
 | 
			
		||||
  version "8.2.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-8.2.6.tgz#08eb38203fb01a828227ea25972d38bfef5c818f"
 | 
			
		||||
  integrity sha512-NwPcEIMmCsucs3QaDlQvkoU1FlFM2wm/WjaqLQhkSoIEmAR1gNtBo88f5io5cpMwCo1k5xYhqGlaSl6TfngwWQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@nuxtjs/opencollective" "0.3.2"
 | 
			
		||||
    fast-safe-stringify "2.1.1"
 | 
			
		||||
    iterare "1.2.1"
 | 
			
		||||
    object-hash "2.2.0"
 | 
			
		||||
    path-to-regexp "3.2.0"
 | 
			
		||||
    tslib "2.3.1"
 | 
			
		||||
    uuid "8.3.2"
 | 
			
		||||
 | 
			
		||||
"@nodelib/fs.scandir@2.1.5":
 | 
			
		||||
  version "2.1.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
 | 
			
		||||
@ -1523,11 +1546,41 @@
 | 
			
		||||
    "@nodelib/fs.scandir" "2.1.5"
 | 
			
		||||
    fastq "^1.6.0"
 | 
			
		||||
 | 
			
		||||
"@nuxtjs/opencollective@0.3.2":
 | 
			
		||||
  version "0.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz#620ce1044f7ac77185e825e1936115bb38e2681c"
 | 
			
		||||
  integrity sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    chalk "^4.1.0"
 | 
			
		||||
    consola "^2.15.0"
 | 
			
		||||
    node-fetch "^2.6.1"
 | 
			
		||||
 | 
			
		||||
"@open-draft/until@^1.0.3":
 | 
			
		||||
  version "1.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca"
 | 
			
		||||
  integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==
 | 
			
		||||
 | 
			
		||||
"@openapitools/openapi-generator-cli@^2.4.26":
 | 
			
		||||
  version "2.4.26"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.4.26.tgz#67622fc41c258aeae3ff074cd92772978e03484f"
 | 
			
		||||
  integrity sha512-O42H9q1HWGoIpcpMaUu318b6bmOgcjP3MieHwOrFdoG3KyttceBGlbLf9Kbf7WM91WSNCDXum7cnEKASuoGjAg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@nestjs/common" "8.2.6"
 | 
			
		||||
    "@nestjs/core" "8.2.6"
 | 
			
		||||
    "@nuxtjs/opencollective" "0.3.2"
 | 
			
		||||
    chalk "4.1.2"
 | 
			
		||||
    commander "8.3.0"
 | 
			
		||||
    compare-versions "3.6.0"
 | 
			
		||||
    concurrently "6.5.1"
 | 
			
		||||
    console.table "0.10.0"
 | 
			
		||||
    fs-extra "10.0.0"
 | 
			
		||||
    glob "7.1.6"
 | 
			
		||||
    inquirer "8.2.0"
 | 
			
		||||
    lodash "4.17.21"
 | 
			
		||||
    reflect-metadata "0.1.13"
 | 
			
		||||
    rxjs "7.5.2"
 | 
			
		||||
    tslib "2.0.3"
 | 
			
		||||
 | 
			
		||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
 | 
			
		||||
  version "0.5.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca"
 | 
			
		||||
@ -2807,6 +2860,13 @@ axe-core@^4.3.5:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413"
 | 
			
		||||
  integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==
 | 
			
		||||
 | 
			
		||||
axios@0.24.0:
 | 
			
		||||
  version "0.24.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
 | 
			
		||||
  integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    follow-redirects "^1.14.4"
 | 
			
		||||
 | 
			
		||||
axobject-query@^2.2.0:
 | 
			
		||||
  version "2.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
 | 
			
		||||
@ -3192,6 +3252,14 @@ chalk@4.1.1:
 | 
			
		||||
    ansi-styles "^4.1.0"
 | 
			
		||||
    supports-color "^7.1.0"
 | 
			
		||||
 | 
			
		||||
chalk@4.1.2, chalk@^4.0.2, chalk@^4.1.1, chalk@^4.1.2:
 | 
			
		||||
  version "4.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
 | 
			
		||||
  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ansi-styles "^4.1.0"
 | 
			
		||||
    supports-color "^7.1.0"
 | 
			
		||||
 | 
			
		||||
chalk@^2.0.0, chalk@^2.4.1:
 | 
			
		||||
  version "2.4.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
 | 
			
		||||
@ -3209,10 +3277,10 @@ chalk@^3.0.0:
 | 
			
		||||
    ansi-styles "^4.1.0"
 | 
			
		||||
    supports-color "^7.1.0"
 | 
			
		||||
 | 
			
		||||
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
 | 
			
		||||
  version "4.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
 | 
			
		||||
  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
 | 
			
		||||
chalk@^4.0.0, chalk@^4.1.0:
 | 
			
		||||
  version "4.1.0"
 | 
			
		||||
  resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz"
 | 
			
		||||
  integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ansi-styles "^4.1.0"
 | 
			
		||||
    supports-color "^7.1.0"
 | 
			
		||||
@ -3422,6 +3490,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    delayed-stream "~1.0.0"
 | 
			
		||||
 | 
			
		||||
commander@8.3.0, commander@^8.3.0:
 | 
			
		||||
  version "8.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
 | 
			
		||||
  integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
 | 
			
		||||
 | 
			
		||||
commander@^2.20.0:
 | 
			
		||||
  version "2.20.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
 | 
			
		||||
@ -3437,11 +3510,6 @@ commander@^7.2.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
 | 
			
		||||
  integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
 | 
			
		||||
 | 
			
		||||
commander@^8.3.0:
 | 
			
		||||
  version "8.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
 | 
			
		||||
  integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
 | 
			
		||||
 | 
			
		||||
common-path-prefix@^3.0.0:
 | 
			
		||||
  version "3.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0"
 | 
			
		||||
@ -3457,6 +3525,11 @@ commondir@^1.0.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
 | 
			
		||||
  integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
 | 
			
		||||
 | 
			
		||||
compare-versions@3.6.0:
 | 
			
		||||
  version "3.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
 | 
			
		||||
  integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
 | 
			
		||||
 | 
			
		||||
compressible@~2.0.16:
 | 
			
		||||
  version "2.0.18"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
 | 
			
		||||
@ -3482,6 +3555,20 @@ concat-map@0.0.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
 | 
			
		||||
  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 | 
			
		||||
 | 
			
		||||
concurrently@6.5.1:
 | 
			
		||||
  version "6.5.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.5.1.tgz#4518c67f7ac680cf5c34d5adf399a2a2047edc8c"
 | 
			
		||||
  integrity sha512-FlSwNpGjWQfRwPLXvJ/OgysbBxPkWpiVjy1042b0U7on7S7qwwMIILRj7WTN1mTgqa582bG6NFuScOoh6Zgdag==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    chalk "^4.1.0"
 | 
			
		||||
    date-fns "^2.16.1"
 | 
			
		||||
    lodash "^4.17.21"
 | 
			
		||||
    rxjs "^6.6.3"
 | 
			
		||||
    spawn-command "^0.0.2-1"
 | 
			
		||||
    supports-color "^8.1.0"
 | 
			
		||||
    tree-kill "^1.2.2"
 | 
			
		||||
    yargs "^16.2.0"
 | 
			
		||||
 | 
			
		||||
confusing-browser-globals@^1.0.11:
 | 
			
		||||
  version "1.0.11"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
 | 
			
		||||
@ -3492,6 +3579,18 @@ connect-history-api-fallback@^1.6.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
 | 
			
		||||
  integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
 | 
			
		||||
 | 
			
		||||
consola@^2.15.0:
 | 
			
		||||
  version "2.15.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
 | 
			
		||||
  integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
 | 
			
		||||
 | 
			
		||||
console.table@0.10.0:
 | 
			
		||||
  version "0.10.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/console.table/-/console.table-0.10.0.tgz#0917025588875befd70cf2eff4bef2c6e2d75d04"
 | 
			
		||||
  integrity sha1-CRcCVYiHW+/XDPLv9L7yxuLXXQQ=
 | 
			
		||||
  dependencies:
 | 
			
		||||
    easy-table "1.1.0"
 | 
			
		||||
 | 
			
		||||
content-disposition@0.5.4:
 | 
			
		||||
  version "0.5.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
 | 
			
		||||
@ -3878,7 +3977,7 @@ data-urls@^2.0.0:
 | 
			
		||||
    whatwg-mimetype "^2.3.0"
 | 
			
		||||
    whatwg-url "^8.0.0"
 | 
			
		||||
 | 
			
		||||
date-fns@2.28.0:
 | 
			
		||||
date-fns@2.28.0, date-fns@^2.16.1:
 | 
			
		||||
  version "2.28.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2"
 | 
			
		||||
  integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==
 | 
			
		||||
@ -4175,6 +4274,13 @@ duplexer@^0.1.2:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
 | 
			
		||||
  integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
 | 
			
		||||
 | 
			
		||||
easy-table@1.1.0:
 | 
			
		||||
  version "1.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/easy-table/-/easy-table-1.1.0.tgz#86f9ab4c102f0371b7297b92a651d5824bc8cb73"
 | 
			
		||||
  integrity sha1-hvmrTBAvA3G3KXuSplHVgkvIy3M=
 | 
			
		||||
  optionalDependencies:
 | 
			
		||||
    wcwidth ">=1.0.1"
 | 
			
		||||
 | 
			
		||||
ecc-jsbn@~0.1.1:
 | 
			
		||||
  version "0.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
 | 
			
		||||
@ -4770,6 +4876,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
 | 
			
		||||
  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
 | 
			
		||||
 | 
			
		||||
fast-safe-stringify@2.1.1:
 | 
			
		||||
  version "2.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
 | 
			
		||||
  integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
 | 
			
		||||
 | 
			
		||||
fastq@^1.6.0:
 | 
			
		||||
  version "1.13.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
 | 
			
		||||
@ -4904,7 +5015,7 @@ flatted@^3.1.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
 | 
			
		||||
  integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
 | 
			
		||||
 | 
			
		||||
follow-redirects@^1.0.0:
 | 
			
		||||
follow-redirects@^1.0.0, follow-redirects@^1.14.4:
 | 
			
		||||
  version "1.14.9"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
 | 
			
		||||
  integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
 | 
			
		||||
@ -4966,6 +5077,15 @@ fresh@0.5.2:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
 | 
			
		||||
  integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
 | 
			
		||||
 | 
			
		||||
fs-extra@10.0.0:
 | 
			
		||||
  version "10.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
 | 
			
		||||
  integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    graceful-fs "^4.2.0"
 | 
			
		||||
    jsonfile "^6.0.1"
 | 
			
		||||
    universalify "^2.0.0"
 | 
			
		||||
 | 
			
		||||
fs-extra@^10.0.0:
 | 
			
		||||
  version "10.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8"
 | 
			
		||||
@ -5092,10 +5212,10 @@ glob-to-regexp@^0.4.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
 | 
			
		||||
  integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
 | 
			
		||||
 | 
			
		||||
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
 | 
			
		||||
  version "7.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
 | 
			
		||||
  integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
 | 
			
		||||
glob@7.1.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
 | 
			
		||||
  version "7.1.6"
 | 
			
		||||
  resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
 | 
			
		||||
  integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    fs.realpath "^1.0.0"
 | 
			
		||||
    inflight "^1.0.4"
 | 
			
		||||
@ -5263,11 +5383,16 @@ html-encoding-sniffer@^2.0.1:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    whatwg-encoding "^1.0.5"
 | 
			
		||||
 | 
			
		||||
html-entities@^2.1.0, html-entities@^2.3.2:
 | 
			
		||||
html-entities@^2.1.0:
 | 
			
		||||
  version "2.3.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
 | 
			
		||||
  integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
 | 
			
		||||
 | 
			
		||||
html-entities@^2.3.2:
 | 
			
		||||
  version "2.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488"
 | 
			
		||||
  integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==
 | 
			
		||||
 | 
			
		||||
html-escaper@^2.0.0:
 | 
			
		||||
  version "2.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
 | 
			
		||||
@ -5504,6 +5629,26 @@ ini@^1.3.5:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
 | 
			
		||||
  integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
 | 
			
		||||
 | 
			
		||||
inquirer@8.2.0:
 | 
			
		||||
  version "8.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a"
 | 
			
		||||
  integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ansi-escapes "^4.2.1"
 | 
			
		||||
    chalk "^4.1.1"
 | 
			
		||||
    cli-cursor "^3.1.0"
 | 
			
		||||
    cli-width "^3.0.0"
 | 
			
		||||
    external-editor "^3.0.3"
 | 
			
		||||
    figures "^3.0.0"
 | 
			
		||||
    lodash "^4.17.21"
 | 
			
		||||
    mute-stream "0.0.8"
 | 
			
		||||
    ora "^5.4.1"
 | 
			
		||||
    run-async "^2.4.0"
 | 
			
		||||
    rxjs "^7.2.0"
 | 
			
		||||
    string-width "^4.1.0"
 | 
			
		||||
    strip-ansi "^6.0.0"
 | 
			
		||||
    through "^2.3.6"
 | 
			
		||||
 | 
			
		||||
inquirer@^8.2.0:
 | 
			
		||||
  version "8.2.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.2.tgz#1310517a87a0814d25336c78a20b44c3d9b7629d"
 | 
			
		||||
@ -5818,6 +5963,11 @@ istanbul-reports@^3.1.3:
 | 
			
		||||
    html-escaper "^2.0.0"
 | 
			
		||||
    istanbul-lib-report "^3.0.0"
 | 
			
		||||
 | 
			
		||||
iterare@1.2.1:
 | 
			
		||||
  version "1.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/iterare/-/iterare-1.2.1.tgz#139c400ff7363690e33abffa33cbba8920f00042"
 | 
			
		||||
  integrity sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==
 | 
			
		||||
 | 
			
		||||
jake@^10.6.1:
 | 
			
		||||
  version "10.8.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.4.tgz#f6a8b7bf90c6306f768aa82bb7b98bf4ca15e84a"
 | 
			
		||||
@ -6638,7 +6788,7 @@ lodash.uniq@^4.5.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 | 
			
		||||
  integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 | 
			
		||||
 | 
			
		||||
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
 | 
			
		||||
lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
 | 
			
		||||
  version "4.17.21"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
 | 
			
		||||
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 | 
			
		||||
@ -6910,7 +7060,7 @@ no-case@^3.0.4:
 | 
			
		||||
    lower-case "^2.0.2"
 | 
			
		||||
    tslib "^2.0.3"
 | 
			
		||||
 | 
			
		||||
node-fetch@^2.6.7:
 | 
			
		||||
node-fetch@^2.6.1, node-fetch@^2.6.7:
 | 
			
		||||
  version "2.6.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
 | 
			
		||||
  integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
 | 
			
		||||
@ -6978,7 +7128,7 @@ object-assign@^4.1.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
 | 
			
		||||
  integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
 | 
			
		||||
 | 
			
		||||
object-hash@^2.2.0:
 | 
			
		||||
object-hash@2.2.0, object-hash@^2.2.0:
 | 
			
		||||
  version "2.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
 | 
			
		||||
  integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
 | 
			
		||||
@ -7288,6 +7438,11 @@ path-to-regexp@0.1.7:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
 | 
			
		||||
  integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
 | 
			
		||||
 | 
			
		||||
path-to-regexp@3.2.0:
 | 
			
		||||
  version "3.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.2.0.tgz#fa7877ecbc495c601907562222453c43cc204a5f"
 | 
			
		||||
  integrity sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==
 | 
			
		||||
 | 
			
		||||
path-to-regexp@^1.7.0:
 | 
			
		||||
  version "1.8.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
 | 
			
		||||
@ -8342,6 +8497,11 @@ redux@^4.1.2:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@babel/runtime" "^7.9.2"
 | 
			
		||||
 | 
			
		||||
reflect-metadata@0.1.13:
 | 
			
		||||
  version "0.1.13"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
 | 
			
		||||
  integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
 | 
			
		||||
 | 
			
		||||
regenerate-unicode-properties@^10.0.1:
 | 
			
		||||
  version "10.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
 | 
			
		||||
@ -8560,6 +8720,27 @@ run-parallel@^1.1.9:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    queue-microtask "^1.2.2"
 | 
			
		||||
 | 
			
		||||
rxjs@7.5.2:
 | 
			
		||||
  version "7.5.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.2.tgz#11e4a3a1dfad85dbf7fb6e33cbba17668497490b"
 | 
			
		||||
  integrity sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    tslib "^2.1.0"
 | 
			
		||||
 | 
			
		||||
rxjs@^6.6.3:
 | 
			
		||||
  version "6.6.7"
 | 
			
		||||
  resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz"
 | 
			
		||||
  integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    tslib "^1.9.0"
 | 
			
		||||
 | 
			
		||||
rxjs@^7.2.0:
 | 
			
		||||
  version "7.5.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d"
 | 
			
		||||
  integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    tslib "^2.1.0"
 | 
			
		||||
 | 
			
		||||
rxjs@^7.5.1, rxjs@^7.5.5:
 | 
			
		||||
  version "7.5.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
 | 
			
		||||
@ -8896,6 +9077,11 @@ sourcemap-codec@^1.4.8:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
 | 
			
		||||
  integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
 | 
			
		||||
 | 
			
		||||
spawn-command@^0.0.2-1:
 | 
			
		||||
  version "0.0.2-1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
 | 
			
		||||
  integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
 | 
			
		||||
 | 
			
		||||
spdy-transport@^3.0.0:
 | 
			
		||||
  version "3.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
 | 
			
		||||
@ -9129,7 +9315,7 @@ supports-color@^7.0.0, supports-color@^7.1.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    has-flag "^4.0.0"
 | 
			
		||||
 | 
			
		||||
supports-color@^8.0.0, supports-color@^8.1.1:
 | 
			
		||||
supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1:
 | 
			
		||||
  version "8.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
 | 
			
		||||
  integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
 | 
			
		||||
@ -9398,6 +9584,11 @@ tr46@~0.0.3:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
 | 
			
		||||
  integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
 | 
			
		||||
 | 
			
		||||
tree-kill@^1.2.2:
 | 
			
		||||
  version "1.2.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
 | 
			
		||||
  integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
 | 
			
		||||
 | 
			
		||||
tryer@^1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
 | 
			
		||||
@ -9413,16 +9604,21 @@ tsconfig-paths@^3.14.1:
 | 
			
		||||
    minimist "^1.2.6"
 | 
			
		||||
    strip-bom "^3.0.0"
 | 
			
		||||
 | 
			
		||||
tslib@^1.8.1:
 | 
			
		||||
  version "1.14.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
 | 
			
		||||
  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 | 
			
		||||
tslib@2.0.3:
 | 
			
		||||
  version "2.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
 | 
			
		||||
  integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
 | 
			
		||||
 | 
			
		||||
tslib@^2.0.3, tslib@^2.1.0:
 | 
			
		||||
tslib@2.3.1, tslib@^2.0.3, tslib@^2.1.0:
 | 
			
		||||
  version "2.3.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
 | 
			
		||||
  integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
 | 
			
		||||
 | 
			
		||||
tslib@^1.8.1, tslib@^1.9.0:
 | 
			
		||||
  version "1.14.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
 | 
			
		||||
  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 | 
			
		||||
 | 
			
		||||
tsutils@^3.21.0:
 | 
			
		||||
  version "3.21.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
 | 
			
		||||
@ -9603,9 +9799,9 @@ utils-merge@1.0.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
 | 
			
		||||
  integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 | 
			
		||||
 | 
			
		||||
uuid@^8.3.2:
 | 
			
		||||
uuid@8.3.2, uuid@^8.3.2:
 | 
			
		||||
  version "8.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
 | 
			
		||||
  resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
 | 
			
		||||
  integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
 | 
			
		||||
 | 
			
		||||
v8-compile-cache@^2.0.3:
 | 
			
		||||
@ -9677,7 +9873,7 @@ wbuf@^1.1.0, wbuf@^1.7.3:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    minimalistic-assert "^1.0.0"
 | 
			
		||||
 | 
			
		||||
wcwidth@^1.0.1:
 | 
			
		||||
wcwidth@>=1.0.1, wcwidth@^1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
 | 
			
		||||
  integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user