/** @ignore */
export class TypeAssembler extends Visitor {
    public visit<T extends type.DataType>(node: T, builder: Builder): number | undefined {
        return (node == null || builder == null) ? undefined : super.visit(node, builder);
    }
    public visitNull<T extends type.Null>(_node: T, b: Builder) {
        Null.startNull(b);
        return Null.endNull(b);
    }
    public visitInt<T extends type.Int>(node: T, b: Builder) {
        Int.startInt(b);
        Int.addBitWidth(b, node.bitWidth);
        Int.addIsSigned(b, node.isSigned);
        return Int.endInt(b);
    }
    public visitFloat<T extends type.Float>(node: T, b: Builder) {
        FloatingPoint.startFloatingPoint(b);
        FloatingPoint.addPrecision(b, node.precision);
        return FloatingPoint.endFloatingPoint(b);
    }
    public visitBinary<T extends type.Binary>(_node: T, b: Builder) {
        Binary.startBinary(b);
        return Binary.endBinary(b);
    }
    public visitBool<T extends type.Bool>(_node: T, b: Builder) {
        Bool.startBool(b);
        return Bool.endBool(b);
    }
    public visitUtf8<T extends type.Utf8>(_node: T, b: Builder) {
        Utf8.startUtf8(b);
        return Utf8.endUtf8(b);
    }
    public visitDecimal<T extends type.Decimal>(node: T, b: Builder) {
        Decimal.startDecimal(b);
        Decimal.addScale(b, node.scale);
        Decimal.addPrecision(b, node.precision);
        Decimal.addBitWidth(b, node.bitWidth);
        return Decimal.endDecimal(b);
    }
    public visitDate<T extends type.Date_>(node: T, b: Builder) {
        Date.startDate(b);
        Date.addUnit(b, node.unit);
        return Date.endDate(b);
    }
    public visitTime<T extends type.Time>(node: T, b: Builder) {
        Time.startTime(b);
        Time.addUnit(b, node.unit);
        Time.addBitWidth(b, node.bitWidth);
        return Time.endTime(b);
    }
    public visitTimestamp<T extends type.Timestamp>(node: T, b: Builder) {
        const timezone = (node.timezone && b.createString(node.timezone)) || undefined;
        Timestamp.startTimestamp(b);
        Timestamp.addUnit(b, node.unit);
        if (timezone !== undefined) {
            Timestamp.addTimezone(b, timezone);
        }
        return Timestamp.endTimestamp(b);
    }
    public visitInterval<T extends type.Interval>(node: T, b: Builder) {
        Interval.startInterval(b);
        Interval.addUnit(b, node.unit);
        return Interval.endInterval(b);
    }
    public visitList<T extends type.List>(_node: T, b: Builder) {
        List.startList(b);
        return List.endList(b);
    }
    public visitStruct<T extends type.Struct>(_node: T, b: Builder) {
        Struct.startStruct_(b);
        return Struct.endStruct_(b);
    }
    public visitUnion<T extends type.Union>(node: T, b: Builder) {
        Union.startTypeIdsVector(b, node.typeIds.length);
        const typeIds = Union.createTypeIdsVector(b, node.typeIds);
        Union.startUnion(b);
        Union.addMode(b, node.mode);
        Union.addTypeIds(b, typeIds);
        return Union.endUnion(b);
    }
    public visitDictionary<T extends type.Dictionary>(node: T, b: Builder) {
        const indexType = this.visit(node.indices, b);
        DictionaryEncoding.startDictionaryEncoding(b);
        DictionaryEncoding.addId(b, new Long(node.id, 0));
        DictionaryEncoding.addIsOrdered(b, node.isOrdered);
        if (indexType !== undefined) {
            DictionaryEncoding.addIndexType(b, indexType);
        }
        return DictionaryEncoding.endDictionaryEncoding(b);
    }
    public visitFixedSizeBinary<T extends type.FixedSizeBinary>(node: T, b: Builder) {
        FixedSizeBinary.startFixedSizeBinary(b);
        FixedSizeBinary.addByteWidth(b, node.byteWidth);
        return FixedSizeBinary.endFixedSizeBinary(b);
    }
    public visitFixedSizeList<T extends type.FixedSizeList>(node: T, b: Builder) {
        FixedSizeList.startFixedSizeList(b);
        FixedSizeList.addListSize(b, node.listSize);
        return FixedSizeList.endFixedSizeList(b);
    }
    public visitMap<T extends type.Map_>(node: T, b: Builder) {
        Map_.startMap(b);
        Map_.addKeysSorted(b, node.keysSorted);
        return Map_.endMap(b);
    }
}


/** @ignore */
export interface TypeAssembler extends Visitor {
    visit<T extends type.DataType>(node: T, builder: Builder): number | undefined;
}


public visit<T extends type.DataType>(node: T, builder: Builder): number | undefined {
        return (node == null || builder == null) ? undefined : super.visit(node, builder);
    }


public visitNull<T extends type.Null>(_node: T, b: Builder) {
        Null.startNull(b);
        return Null.endNull(b);
    }


public visitInt<T extends type.Int>(node: T, b: Builder) {
        Int.startInt(b);
        Int.addBitWidth(b, node.bitWidth);
        Int.addIsSigned(b, node.isSigned);
        return Int.endInt(b);
    }


public visitFloat<T extends type.Float>(node: T, b: Builder) {
        FloatingPoint.startFloatingPoint(b);
        FloatingPoint.addPrecision(b, node.precision);
        return FloatingPoint.endFloatingPoint(b);
    }


public visitBinary<T extends type.Binary>(_node: T, b: Builder) {
        Binary.startBinary(b);
        return Binary.endBinary(b);
    }


public visitBool<T extends type.Bool>(_node: T, b: Builder) {
        Bool.startBool(b);
        return Bool.endBool(b);
    }


public visitUtf8<T extends type.Utf8>(_node: T, b: Builder) {
        Utf8.startUtf8(b);
        return Utf8.endUtf8(b);
    }


public visitDecimal<T extends type.Decimal>(node: T, b: Builder) {
        Decimal.startDecimal(b);
        Decimal.addScale(b, node.scale);
        Decimal.addPrecision(b, node.precision);
        Decimal.addBitWidth(b, node.bitWidth);
        return Decimal.endDecimal(b);
    }


public visitDate<T extends type.Date_>(node: T, b: Builder) {
        Date.startDate(b);
        Date.addUnit(b, node.unit);
        return Date.endDate(b);
    }


public visitTime<T extends type.Time>(node: T, b: Builder) {
        Time.startTime(b);
        Time.addUnit(b, node.unit);
        Time.addBitWidth(b, node.bitWidth);
        return Time.endTime(b);
    }


public visitTimestamp<T extends type.Timestamp>(node: T, b: Builder) {
        const timezone = (node.timezone && b.createString(node.timezone)) || undefined;
        Timestamp.startTimestamp(b);
        Timestamp.addUnit(b, node.unit);
        if (timezone !== undefined) {
            Timestamp.addTimezone(b, timezone);
        }
        return Timestamp.endTimestamp(b);
    }


public visitInterval<T extends type.Interval>(node: T, b: Builder) {
        Interval.startInterval(b);
        Interval.addUnit(b, node.unit);
        return Interval.endInterval(b);
    }


public visitList<T extends type.List>(_node: T, b: Builder) {
        List.startList(b);
        return List.endList(b);
    }


public visitStruct<T extends type.Struct>(_node: T, b: Builder) {
        Struct.startStruct_(b);
        return Struct.endStruct_(b);
    }


public visitUnion<T extends type.Union>(node: T, b: Builder) {
        Union.startTypeIdsVector(b, node.typeIds.length);
        const typeIds = Union.createTypeIdsVector(b, node.typeIds);
        Union.startUnion(b);
        Union.addMode(b, node.mode);
        Union.addTypeIds(b, typeIds);
        return Union.endUnion(b);
    }


public visitDictionary<T extends type.Dictionary>(node: T, b: Builder) {
        const indexType = this.visit(node.indices, b);
        DictionaryEncoding.startDictionaryEncoding(b);
        DictionaryEncoding.addId(b, new Long(node.id, 0));
        DictionaryEncoding.addIsOrdered(b, node.isOrdered);
        if (indexType !== undefined) {
            DictionaryEncoding.addIndexType(b, indexType);
        }
        return DictionaryEncoding.endDictionaryEncoding(b);
    }


public visitFixedSizeBinary<T extends type.FixedSizeBinary>(node: T, b: Builder) {
        FixedSizeBinary.startFixedSizeBinary(b);
        FixedSizeBinary.addByteWidth(b, node.byteWidth);
        return FixedSizeBinary.endFixedSizeBinary(b);
    }


public visitFixedSizeList<T extends type.FixedSizeList>(node: T, b: Builder) {
        FixedSizeList.startFixedSizeList(b);
        FixedSizeList.addListSize(b, node.listSize);
        return FixedSizeList.endFixedSizeList(b);
    }


public visitMap<T extends type.Map_>(node: T, b: Builder) {
        Map_.startMap(b);
        Map_.addKeysSorted(b, node.keysSorted);
        return Map_.endMap(b);
    }


() => {
      this.tagMenu.openMenu();
      this.tagMenuContent.focus();
    }


@Component({
  selector   : 'sm-experiment-info-header',
  templateUrl: './experiment-info-header.component.html',
  styleUrls  : ['./experiment-info-header.component.scss']
})
export class ExperimentInfoHeaderComponent {

  readonly TaskStatusEnum = TaskStatusEnum;
  readonly TaskTypeEnum   = TaskTypeEnum;

  public viewId: boolean;
  public tags$: Observable<string[]>;
  public isDev = false;
  public systemTags = [] as string[];

  @Input() editable: boolean = true;
  @Input() infoData;
  @Input() backdropActive    = false;
  @Input() showMenu: boolean;
  @Input() showMinimize: boolean;
  @Output() experimentNameChanged = new EventEmitter<string>();
  @Output() minimizeClicked = new EventEmitter();
  @ViewChild('tagMenu') tagMenu: MenuComponent;
  @ViewChild('tagsMenuContent') tagMenuContent: TagsMenuComponent;

  constructor(private store: Store<any>) {
    this.tags$ = this.store.select(selectProjectTags);
  }

  private _experiment: ISelectedExperiment;
  private previousId: string;

  get experiment() {
    return this._experiment;
  }

  @Input() set experiment(experiment: ISelectedExperiment) {
    this._experiment = experiment;
    this.isDev = isDevelopment(experiment);
    this.systemTags = getSystemTags(experiment);
    if (experiment?.id !== this.previousId) {
      this.viewId = false;
    }
    this.previousId = experiment?.id;
  }

  onNameChanged(name) {
    this.experimentNameChanged.emit(name);
  }

  openTagMenu(event: MouseEvent) {
    if (!this.tagMenu) {
      return;
    }
    this.store.dispatch(getTags());
    this.tagMenu.position = {x: event.clientX, y: event.clientY};
    window.setTimeout(() => {
      this.tagMenu.openMenu();
      this.tagMenuContent.focus();
    });
  }

  addTag(tag: string) {
    this.store.dispatch(addTag({tag, experiments: [this.experiment]}));
  }

  removeTag(tag: string) {
    this.store.dispatch(removeTag({tag, experiments: [this.experiment]}));
  }

  tagsMenuClosed() {
    this.tagMenuContent.clear();
  }

  editExperimentName(edit) {
    if (edit) {
      this.store.dispatch(new ActivateEdit('ExperimentName'));
    } else {
      this.store.dispatch(new DeactivateEdit());
    }
  }

  showID() {
    this.viewId = true;
  }
}


onNameChanged(name) {
    this.experimentNameChanged.emit(name);
  }


openTagMenu(event: MouseEvent) {
    if (!this.tagMenu) {
      return;
    }
    this.store.dispatch(getTags());
    this.tagMenu.position = {x: event.clientX, y: event.clientY};
    window.setTimeout(() => {
      this.tagMenu.openMenu();
      this.tagMenuContent.focus();
    });
  }


addTag(tag: string) {
    this.store.dispatch(addTag({tag, experiments: [this.experiment]}));
  }


removeTag(tag: string) {
    this.store.dispatch(removeTag({tag, experiments: [this.experiment]}));
  }


tagsMenuClosed() {
    this.tagMenuContent.clear();
  }


editExperimentName(edit) {
    if (edit) {
      this.store.dispatch(new ActivateEdit('ExperimentName'));
    } else {
      this.store.dispatch(new DeactivateEdit());
    }
  }


showID() {
    this.viewId = true;
  }


function parseJSON(json: string) {
	if (json.startsWith(']')) json = json.substr(1);
	const data: {error: string | null, json: any[] | null} = {error: null, json: null};
	try {
		data.json = JSON.parse(json);
	} catch (err) {
		data.error = err.message;
	}
	return data;
}


resolve => {
			this.requestQueue.push([actionData, resolve]);
			this.requestTimerPoke();
		}


() => void this.makeRequests()


() => {
	void LoginServer.request('invalidatecss');
}


/**
 * A custom error type used when requests to the login server take too long.
 */
class TimeoutError extends Error {}


class LoginServerInstance {
	readonly uri: string;
	requestQueue: [AnyObject, (val: LoginServerResponse) => void][];
	requestTimer: NodeJS.Timer | null;
	requestLog: string;
	lastRequest: number;
	openRequests: number;
	disabled: false;

	constructor() {
		this.uri = Config.loginserver;
		this.requestQueue = [];
		this.requestTimer = null;
		this.requestLog = '';
		this.lastRequest = 0;
		this.openRequests = 0;
		this.disabled = false;
	}

	async instantRequest(action: string, data: AnyObject | null = null): Promise<LoginServerResponse> {
		if (this.openRequests > 5) {
			return Promise.resolve(
				[null, new RangeError("Request overflow")]
			);
		}
		this.openRequests++;

		try {
			const request = Net(this.uri);
			const buffer = await request.get({
				query: {
					...data,
					act: action,
					serverid: Config.serverid,
					servertoken: Config.servertoken,
					nocache: new Date().getTime(),
				},
			});
			const json = parseJSON(buffer);
			this.openRequests--;
			if (json.error) {
				return [null, new Error(json.error)];
			}
			this.openRequests--;
			return [json.json!, null];
		} catch (error) {
			this.openRequests--;
			return [null, error];
		}
	}

	request(action: string, data: AnyObject | null = null): Promise<LoginServerResponse> {
		if (this.disabled) {
			return Promise.resolve(
				[null, new Error(`Login server connection disabled.`)]
			);
		}

		// ladderupdate and mmr are the most common actions
		// prepreplay is also common
		// @ts-ignore
		if (this[action + 'Server']) {
			// @ts-ignore
			return this[action + 'Server'].request(action, data);
		}

		const actionData = data || {};
		actionData.act = action;
		return new Promise(resolve => {
			this.requestQueue.push([actionData, resolve]);
			this.requestTimerPoke();
		});
	}
	requestTimerPoke() {
		// "poke" the request timer, i.e. make sure it knows it should make
		// a request soon

		// if we already have it going or the request queue is empty no need to do anything
		if (this.openRequests || this.requestTimer || !this.requestQueue.length) return;

		this.requestTimer = setTimeout(() => void this.makeRequests(), LOGIN_SERVER_BATCH_TIME);
	}
	async makeRequests() {
		this.requestTimer = null;
		const requests = this.requestQueue;
		this.requestQueue = [];

		if (!requests.length) return;

		const resolvers: ((val: LoginServerResponse) => void)[] = [];
		const dataList = [];
		for (const [data, resolve] of requests) {
			resolvers.push(resolve);
			dataList.push(data);
		}

		this.requestStart(requests.length);

		try {
			const request = Net(`${this.uri}action.php`);
			let buffer = await request.post({
				body: {
					serverid: Config.serverid,
					servertoken: Config.servertoken,
					nocache: new Date().getTime(),
					json: JSON.stringify(dataList),
				},
				timeout: LOGIN_SERVER_TIMEOUT,
			});
			// console.log('RESPONSE: ' + buffer);
			const data = parseJSON(buffer).json;
			if (buffer.startsWith(`[{"actionsuccess":true,`)) {
				buffer = 'stream interrupt';
			}
			if (!data) {
				if (buffer.includes('<')) buffer = 'invalid response';
				throw new Error(buffer);
			}
			for (const [i, resolve] of resolvers.entries()) {
				resolve([data[i], null]);
			}

			this.requestEnd();
		} catch (error) {
			for (const resolve of resolvers) {
				resolve([null, error]);
			}
			this.requestEnd(error);
		}
	}
	requestStart(size: number) {
		this.lastRequest = Date.now();
		this.requestLog += ' | ' + size + ' rqs: ';
		this.openRequests++;
	}
	requestEnd(error?: Error) {
		this.openRequests = 0;
		if (error && error instanceof TimeoutError) {
			this.requestLog += 'TIMEOUT';
		} else {
			this.requestLog += '' + ((Date.now() - this.lastRequest) / 1000) + 's';
		}
		this.requestLog = this.requestLog.substr(-1000);
		this.requestTimerPoke();
	}
	getLog() {
		if (!this.lastRequest) return this.requestLog;
		return `${this.requestLog} (${Chat.toDurationString(Date.now() - this.lastRequest)} since last request)`;
	}
}


type LoginServerResponse = [AnyObject, null] | [null, Error];


async instantRequest(action: string, data: AnyObject | null = null): Promise<LoginServerResponse> {
		if (this.openRequests > 5) {
			return Promise.resolve(
				[null, new RangeError("Request overflow")]
			);
		}
		this.openRequests++;

		try {
			const request = Net(this.uri);
			const buffer = await request.get({
				query: {
					...data,
					act: action,
					serverid: Config.serverid,
					servertoken: Config.servertoken,
					nocache: new Date().getTime(),
				},
			});
			const json = parseJSON(buffer);
			this.openRequests--;
			if (json.error) {
				return [null, new Error(json.error)];
			}
			this.openRequests--;
			return [json.json!, null];
		} catch (error) {
			this.openRequests--;
			return [null, error];
		}
	}


request(action: string, data: AnyObject | null = null): Promise<LoginServerResponse> {
		if (this.disabled) {
			return Promise.resolve(
				[null, new Error(`Login server connection disabled.`)]
			);
		}

		// ladderupdate and mmr are the most common actions
		// prepreplay is also common
		// @ts-ignore
		if (this[action + 'Server']) {
			// @ts-ignore
			return this[action + 'Server'].request(action, data);
		}

		const actionData = data || {};
		actionData.act = action;
		return new Promise(resolve => {
			this.requestQueue.push([actionData, resolve]);
			this.requestTimerPoke();
		});
	}


requestTimerPoke() {
		// "poke" the request timer, i.e. make sure it knows it should make
		// a request soon

		// if we already have it going or the request queue is empty no need to do anything
		if (this.openRequests || this.requestTimer || !this.requestQueue.length) return;

		this.requestTimer = setTimeout(() => void this.makeRequests(), LOGIN_SERVER_BATCH_TIME);
	}


async makeRequests() {
		this.requestTimer = null;
		const requests = this.requestQueue;
		this.requestQueue = [];

		if (!requests.length) return;

		const resolvers: ((val: LoginServerResponse) => void)[] = [];
		const dataList = [];
		for (const [data, resolve] of requests) {
			resolvers.push(resolve);
			dataList.push(data);
		}

		this.requestStart(requests.length);

		try {
			const request = Net(`${this.uri}action.php`);
			let buffer = await request.post({
				body: {
					serverid: Config.serverid,
					servertoken: Config.servertoken,
					nocache: new Date().getTime(),
					json: JSON.stringify(dataList),
				},
				timeout: LOGIN_SERVER_TIMEOUT,
			});
			// console.log('RESPONSE: ' + buffer);
			const data = parseJSON(buffer).json;
			if (buffer.startsWith(`[{"actionsuccess":true,`)) {
				buffer = 'stream interrupt';
			}
			if (!data) {
				if (buffer.includes('<')) buffer = 'invalid response';
				throw new Error(buffer);
			}
			for (const [i, resolve] of resolvers.entries()) {
				resolve([data[i], null]);
			}

			this.requestEnd();
		} catch (error) {
			for (const resolve of resolvers) {
				resolve([null, error]);
			}
			this.requestEnd(error);
		}
	}


requestStart(size: number) {
		this.lastRequest = Date.now();
		this.requestLog += ' | ' + size + ' rqs: ';
		this.openRequests++;
	}


requestEnd(error?: Error) {
		this.openRequests = 0;
		if (error && error instanceof TimeoutError) {
			this.requestLog += 'TIMEOUT';
		} else {
			this.requestLog += '' + ((Date.now() - this.lastRequest) / 1000) + 's';
		}
		this.requestLog = this.requestLog.substr(-1000);
		this.requestTimerPoke();
	}


getLog() {
		if (!this.lastRequest) return this.requestLog;
		return `${this.requestLog} (${Chat.toDurationString(Date.now() - this.lastRequest)} since last request)`;
	}


export declare function notEmpty<T>(value: T | null | undefined): value is T;


export declare function parseFileIgnores(path: string): string[];


export declare function getGlobPatterns(supportedFiles: ISupportedFiles): string[];


export declare function collectIgnoreRules(dirs: string[], symlinksEnabled?: boolean, fileIgnores?: string[]): Promise<string[]>;


export declare function determineBaseDir(paths: string[]): string;


/**
 * Returns bundle files from requested paths
 * */
export declare function collectBundleFiles(baseDir: string, paths: string[], supportedFiles: ISupportedFiles, fileIgnores?: string[], maxFileSize?: number, symlinksEnabled?: boolean): AsyncGenerator<IFileInfo>;


export declare function prepareExtendingBundle(baseDir: string, files: string[], supportedFiles: ISupportedFiles, fileIgnores?: string[], maxFileSize?: number, symlinksEnabled?: boolean): Promise<{
    files: IFileInfo[];
    removedFiles: string[];
}>;


export declare function getFileInfo(filePath: string, baseDir: string, withContent?: boolean, cache?: Cache | null): Promise<IFileInfo | null>;


export declare function resolveBundleFiles(baseDir: string, bundleMissingFiles: string[]): Promise<IFileInfo[]>;


export declare function resolveBundleFilePath(baseDir: string, bundleFilePath: string): string;


export declare function composeFilePayloads(files: IFileInfo[], bucketSize?: number): Generator<IFileInfo[]>;


export declare function filterIgnoredFiles(filePaths: string[], ignores: string[]): string[];


({
  isPrivate = false,
  component: Component,
  ...rest
}) => {
  const { user } = useAuth();

  return (
    <ReactDOMRoute
      {...rest}
      render={({ location })


interface RouteProps extends ReactDOMRouteProps {
  isPrivate?: boolean;
  component: React.ComponentType;
}


export function LazyLoadQuery<O extends OperationType>(
  props: LazyLoadQueryProps<O>,
): React.ReactElement | null {
  const { children, query, variables, options } = props;
  const response = useLazyLoadQuery<O>(query, variables, options);
  return children(response);
}


export interface LazyLoadQueryProps<O extends OperationType> {
  query: GraphQLTaggedNode;
  variables: O['variables'];
  options?: Parameters<typeof useLazyLoadQuery>[2];
  children: (response: O['response']) => React.ReactElement | null;
}


() => {
  const classes = useStyles();

  const [isLoggingIn, setIsLoggingIn] = useState(true);

  return (
    <Box className={classes.container}>
      <Grid container className={classes.boxContainer}>
        <Grid item md={6}>
          <Box
            display="flex"
            height="100%"
            flexDirection="column"
            padding="0 80px"
            justifyContent="center"
          >
            {isLoggingIn ? <LogInForm /> : <SignUpForm />}
            <Box display="flex" justifyContent="flex-end">
              <Typography>
                <Link
                  style={{ marginRight: 10 }}
                  href="#"
                  onClick={(e)


isLoggingIn ? <LogInForm


(props) => {
  const {
    prefixCls,
    style,
    mode,
    disabled,
    showFoldIcons,
    foldIcons,
    hideFirstPanel,
    hideSecondPanel,
    handleMousedown,
  } = props

  const triggerPrefixCls = `${prefixCls}-trigger`
  const isVertical = mode === 'vertical'

  const getCustomFoldIcons = (index: number) => {
    return foldIcons && foldIcons[index]
  }

  const triggerCls = classNames(
    triggerPrefixCls,
    isVertical ? `${triggerPrefixCls}-vertical` : `${triggerPrefixCls}-horizontal`,
    {
      [`is-disabled`]: disabled,
    },
  )
  const getArrowCls = (cls: string) =>
    classNames(`${triggerPrefixCls}-arrow`, isVertical ? `is-vertical` : `is-horizontal`, cls)

  const firstCustomIcons = getCustomFoldIcons(0)
  const secondCustomIcons = getCustomFoldIcons(1)

  const renderFoldIcons = () => {
    if (!showFoldIcons) {
      return null
    }
    const firstIconPos = isVertical ? 'left' : 'top'
    const secondIconPos = isVertical ? 'right' : 'bottom'
    const firstIconType = isVertical ? 'arrow-left-solid' : 'arrow-up-solid'
    const secondIconType = isVertical ? 'arrow-right-solid' : 'arrow-down-solid'
    return (
      <>
        <span className={getArrowCls(firstIconPos)} onClick={(e: React.MouseEvent)


(index: number) => {
    return foldIcons && foldIcons[index]
  }


(cls: string) =>
    classNames(`${triggerPrefixCls}-arrow`, isVertical ? `is-vertical` : `is-horizontal`, cls)


() => {
    if (!showFoldIcons) {
      return null
    }
    const firstIconPos = isVertical ? 'left' : 'top'
    const secondIconPos = isVertical ? 'right' : 'bottom'
    const firstIconType = isVertical ? 'arrow-left-solid' : 'arrow-up-solid'
    const secondIconType = isVertical ? 'arrow-right-solid' : 'arrow-down-solid'
    return (
      <>
        <span className={getArrowCls(firstIconPos)} onClick={(e: React.MouseEvent)


interface TriggerProps {
  prefixCls: string
  style?: React.CSSProperties
  mode: SplitPanelMode
  disabled?: boolean
  showFoldIcons: boolean
  foldIcons?: React.ReactNode[]
  hideFirstPanel: (e: React.MouseEvent, direction: FoldDirection) => void
  hideSecondPanel: (e: React.MouseEvent, direction: FoldDirection) => void
  handleMousedown: (e: React.MouseEvent) => void
}


getArrowCls(firstIconPos)


getArrowCls(secondIconPos)


export class Button extends React.Component<ButtonProps, {}> {
  constructor(props: ButtonProps) {
    super(props);
  }

  setEnabled(enabled: boolean) {
    this.setState({ enabled: enabled });
  }

  setText(text: string) {
    this.setState({ text: text });
  }

  render() {
    if (this.props.enabled) {
      return (
        <button
          className="btn btn-lg btn-secondary"
          type="button"
          onClick={this.props.onClick}
        >
          {this.props.text}
        </button>
      );
    }
    return (
      <button
        className="btn btn-lg btn-secondary"
        type="button"
        disabled
        onClick={this.props.onClick}
      >
        {this.props.text}
      </button>
    );
  }
}


export interface ButtonProps {
  enabled: boolean;
  text: string;
  onClick: () => void;
}


setEnabled(enabled: boolean) {
    this.setState({ enabled: enabled });
  }


setText(text: string) {
    this.setState({ text: text });
  }


render() {
    if (this.props.enabled) {
      return (
        <button
          className="btn btn-lg btn-secondary"
          type="button"
          onClick={this.props.onClick}
        >
          {this.props.text}
        </button>
      );
    }
    return (
      <button
        className="btn btn-lg btn-secondary"
        type="button"
        disabled
        onClick={this.props.onClick}
      >
        {this.props.text}
      </button>
    );
  }


(toaster: Toaster): NotificationSystem => ({
    addNotification: (msg: NotificationMessage) => {
      const intent = {
        "in-progress": Intent.PRIMARY,
        info: Intent.PRIMARY,
        success: Intent.SUCCESS,
        warning: Intent.WARNING,
        error: Intent.DANGER,
      }[msg.level ?? "info"];

      toaster.show({
        message: (
          <>
            {msg.level === "in-progress"
              ? <FloatRight>
                  <Spinner size={20} intent={intent}/>
                </FloatRight>


(msg: NotificationMessage) => {
      const intent = {
        "in-progress": Intent.PRIMARY,
        info: Intent.PRIMARY,
        success: Intent.SUCCESS,
        warning: Intent.WARNING,
        error: Intent.DANGER,
      }[msg.level ?? "info"];

      toaster.show({
        message: (
          <>
            {msg.level === "in-progress"
              ? <FloatRight>
                  <Spinner size={20} intent={intent}/>
                </FloatRight>


state => state.routes


state => state.current


set (state, payload) {
      state.routes = payload.routes
      state.current = payload.current
    }


set ({ commit }, payload) {
      commit('set', payload)
    }


export async function* paginateListServices(
  config: ECSPaginationConfiguration,
  input: ListServicesCommandInput,
  ...additionalArguments: any
): Paginator<ListServicesCommandOutput> {
  // ToDo: replace with actual type instead of typeof input.nextToken
  let token: typeof input.nextToken | undefined = config.startingToken || undefined;
  let hasNext = true;
  let page: ListServicesCommandOutput;
  while (hasNext) {
    input.nextToken = token;
    input["maxResults"] = config.pageSize;
    if (config.client instanceof ECS) {
      page = await makePagedRequest(config.client, input, ...additionalArguments);
    } else if (config.client instanceof ECSClient) {
      page = await makePagedClientRequest(config.client, input, ...additionalArguments);
    } else {
      throw new Error("Invalid client, expected ECS | ECSClient");
    }
    yield page;
    token = page.nextToken;
    hasNext = !!token;
  }
  // @ts-ignore
  return undefined;
}


async (
  client: ECSClient,
  input: ListServicesCommandInput,
  ...args: any
): Promise<ListServicesCommandOutput> => {
  // @ts-ignore
  return await client.send(new ListServicesCommand(input), ...args);
}


async (
  client: ECS,
  input: ListServicesCommandInput,
  ...args: any
): Promise<ListServicesCommandOutput> => {
  // @ts-ignore
  return await client.listServices(input, ...args);
}


async () => {
  beforeAll(async () => {
    await browser.get(`${appHost}/k8s/cluster/projects`);
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');

    // Extend the default jasmine timeout interval just in case it takes a while for the htpasswd idp to be ready
    jasmine.DEFAULT_TIMEOUT_INTERVAL = JASMINE_EXTENDED_TIMEOUT_INTERVAL;
  });

  afterAll(() => {
    // Set jasmine timeout interval back to the original value after these tests are done
    jasmine.DEFAULT_TIMEOUT_INTERVAL = JASMINE_DEFAULT_TIMEOUT_INTERVAL;
  });

  afterEach(() => {
    checkLogs();
    checkErrors();
  });

  it('displays subscription creation form for serverless Operator', async () => {
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Operators')));
    await sidenavView.clickNavLink(['Operators', 'OperatorHub']);
    await crudView.isLoaded();
    await catalogView.categoryTabsPresent();
    await catalogView.categoryTabs.get(0).click();
    await catalogPageView.catalogTileFor('OpenShift Serverless Operator').click();
    await browser.wait(until.visibilityOf(installServerlessOperator));
    await installServerlessOperator.element(by.linkText('Install')).click();
    await operatorHubView.createSubscriptionFormLoaded();
    expect(operatorHubView.createSubscriptionFormName.getText()).toEqual(
      'OpenShift Serverless Operator',
    );
    await browser.wait(until.visibilityOf(operatorHubView.createSubscriptionFormInstallMode));
    await operatorHubView.allNamespacesInstallMode.click();

    expect(operatorHubView.createSubscriptionError.isPresent()).toBe(false);
    expect(operatorHubView.createSubscriptionFormBtn.getAttribute('disabled')).toEqual(null);
    await operatorHubView.createSubscriptionFormBtn.click();
    await crudView.isLoaded();
    await browser.get(`${appHost}/operatorhub/ns/${testName}`);
    await crudView.isLoaded();
    await catalogPageView.clickFilterCheckbox('installState-installed');
    expect(catalogPageView.catalogTileFor('OpenShift Serverless Operator').isDisplayed()).toBe(
      true,
    );
  });

  it(`displays Operator in "Cluster Service Versions" view for "${testName}" namespace`, async () => {
    await retry(() => catalogPageView.catalogTileFor('OpenShift Serverless Operator').click());
    await browser
      .wait(until.presenceOf(installServerlessOperator), 15000)
      .then(() => browser.sleep(500));
    await operatorHubView.viewInstalledOperator();
    await crudView.isLoaded();
    await browser.wait(
      until.visibilityOf(operatorView.rowForOperator('OpenShift Serverless Operator')),
    );
    expect(operatorView.rowForOperator('OpenShift Serverless Operator').isDisplayed()).toBe(true);
  });

  it(`create knative-serving namespace and apply serving.yaml`, async () => {
    await execSync(`oc new-project knative-serving`);
    await execSync(
      `oc apply -f ./packages/knative-plugin/integration-tests/views/serverless-service.yaml`,
    );
    await browser.get(`${appHost}/k8s/cluster/projects/`);
    await crudView.isLoaded();
    await browser.wait(until.elementToBeClickable(knativeServingNS));
    expect(knativeServingNS.isDisplayed()).toBe(true);
  });

  it('Increase the Machine sets count', async () => {
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Compute')));
    await sidenavView.clickNavLink(['Compute', 'Machine Sets']);
    await crudView.isLoaded();

    await browser.wait(until.elementToBeClickable(firstKebabMenu));
    await firstKebabMenu.click();
    await browser.wait(until.elementToBeClickable(crudView.actionForLabel('Edit Machine Count')));
    await crudView.actionForLabel('Edit Machine Count').click();

    await browser.wait(until.elementToBeClickable(machineSetsInput));
    await machineSetsInput.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a'));
    await machineSetsInput.clear().sendKeys('6');
    await browser.wait(until.elementToBeClickable(submitCount));
    await submitCount.click();
    await browser.wait(until.visibilityOf(machineCount));
    expect(machineCount.isDisplayed()).toBe(true);
  });

  it('Serverless is installed', async () => {
    await crudView.isLoaded();
    await switchPerspective(Perspective.Developer);
    expect(sideHeader.getText()).toContain('Developer');
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');
    await browser.wait(until.visibilityOf(pageSidebar));
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Services']);
    await browser.wait(until.visibilityOf(servicesValidation));
    expect(servicesValidation.isDisplayed()).toBe(true);
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Revisions']);
    await browser.wait(until.visibilityOf(revisionsValidation));
    expect(revisionsValidation.isDisplayed()).toBe(true);
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Routes']);
    await browser.wait(until.visibilityOf(routesValidation));
    expect(routesValidation.isDisplayed()).toBe(true);
  });
}


async () => {
    await browser.get(`${appHost}/k8s/cluster/projects`);
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');

    // Extend the default jasmine timeout interval just in case it takes a while for the htpasswd idp to be ready
    jasmine.DEFAULT_TIMEOUT_INTERVAL = JASMINE_EXTENDED_TIMEOUT_INTERVAL;
  }


() => {
    // Set jasmine timeout interval back to the original value after these tests are done
    jasmine.DEFAULT_TIMEOUT_INTERVAL = JASMINE_DEFAULT_TIMEOUT_INTERVAL;
  }


() => {
    checkLogs();
    checkErrors();
  }


async () => {
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Operators')));
    await sidenavView.clickNavLink(['Operators', 'OperatorHub']);
    await crudView.isLoaded();
    await catalogView.categoryTabsPresent();
    await catalogView.categoryTabs.get(0).click();
    await catalogPageView.catalogTileFor('OpenShift Serverless Operator').click();
    await browser.wait(until.visibilityOf(installServerlessOperator));
    await installServerlessOperator.element(by.linkText('Install')).click();
    await operatorHubView.createSubscriptionFormLoaded();
    expect(operatorHubView.createSubscriptionFormName.getText()).toEqual(
      'OpenShift Serverless Operator',
    );
    await browser.wait(until.visibilityOf(operatorHubView.createSubscriptionFormInstallMode));
    await operatorHubView.allNamespacesInstallMode.click();

    expect(operatorHubView.createSubscriptionError.isPresent()).toBe(false);
    expect(operatorHubView.createSubscriptionFormBtn.getAttribute('disabled')).toEqual(null);
    await operatorHubView.createSubscriptionFormBtn.click();
    await crudView.isLoaded();
    await browser.get(`${appHost}/operatorhub/ns/${testName}`);
    await crudView.isLoaded();
    await catalogPageView.clickFilterCheckbox('installState-installed');
    expect(catalogPageView.catalogTileFor('OpenShift Serverless Operator').isDisplayed()).toBe(
      true,
    );
  }


async () => {
    await retry(() => catalogPageView.catalogTileFor('OpenShift Serverless Operator').click());
    await browser
      .wait(until.presenceOf(installServerlessOperator), 15000)
      .then(() => browser.sleep(500));
    await operatorHubView.viewInstalledOperator();
    await crudView.isLoaded();
    await browser.wait(
      until.visibilityOf(operatorView.rowForOperator('OpenShift Serverless Operator')),
    );
    expect(operatorView.rowForOperator('OpenShift Serverless Operator').isDisplayed()).toBe(true);
  }


() => catalogPageView.catalogTileFor('OpenShift Serverless Operator').click()


() => browser.sleep(500)


async () => {
    await execSync(`oc new-project knative-serving`);
    await execSync(
      `oc apply -f ./packages/knative-plugin/integration-tests/views/serverless-service.yaml`,
    );
    await browser.get(`${appHost}/k8s/cluster/projects/`);
    await crudView.isLoaded();
    await browser.wait(until.elementToBeClickable(knativeServingNS));
    expect(knativeServingNS.isDisplayed()).toBe(true);
  }


async () => {
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Compute')));
    await sidenavView.clickNavLink(['Compute', 'Machine Sets']);
    await crudView.isLoaded();

    await browser.wait(until.elementToBeClickable(firstKebabMenu));
    await firstKebabMenu.click();
    await browser.wait(until.elementToBeClickable(crudView.actionForLabel('Edit Machine Count')));
    await crudView.actionForLabel('Edit Machine Count').click();

    await browser.wait(until.elementToBeClickable(machineSetsInput));
    await machineSetsInput.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a'));
    await machineSetsInput.clear().sendKeys('6');
    await browser.wait(until.elementToBeClickable(submitCount));
    await submitCount.click();
    await browser.wait(until.visibilityOf(machineCount));
    expect(machineCount.isDisplayed()).toBe(true);
  }


async () => {
    await crudView.isLoaded();
    await switchPerspective(Perspective.Developer);
    expect(sideHeader.getText()).toContain('Developer');
    await switchPerspective(Perspective.Administrator);
    expect(sideHeader.getText()).toContain('Administrator');
    await browser.wait(until.visibilityOf(pageSidebar));
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Services']);
    await browser.wait(until.visibilityOf(servicesValidation));
    expect(servicesValidation.isDisplayed()).toBe(true);
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Revisions']);
    await browser.wait(until.visibilityOf(revisionsValidation));
    expect(revisionsValidation.isDisplayed()).toBe(true);
    await crudView.isLoaded();
    await browser.wait(until.presenceOf(sidenavView.navSectionFor('Serverless')));
    await sidenavView.clickNavLink(['Serverless', 'Routes']);
    await browser.wait(until.visibilityOf(routesValidation));
    expect(routesValidation.isDisplayed()).toBe(true);
  }


@NgModule({
  imports: [CommonModule, SharedModule, ActivitiesUpdateRoutingModule],
  declarations: [UpdateActivityFormComponent],
  providers: [DatePipe],
  entryComponents: []
})
export class ActivitiesUpdateModule {}


() => {
    test('Tests extracting dictionaries by locale', () => {
        const langSetting: server.LanguageSetting[]  = [
            { local: 'en,en-US', languageId: '*', dictionaries: ['English'] },
            { local: 'en', languageId: '*', dictionaries: ['Misc'] },
            { local: 'fr', languageId: '*', dictionaries: ['French'] },
            { local: '*', languageId: 'java', dictionaries: ['Java'] },
        ];

        const locales = serverSettings.extractDictionariesByLocaleLanguageSettings(langSetting);

        expect(locales.get('en')).not.toBeNull();
        expect(locales.get('en-GB')).toBeUndefined();
        expect(locales.get('en-US')).not.toBeNull();
        expect(locales.get('fr')).not.toBeNull();
        expect(locales.get('*')).not.toBeNull();
        expect(locales.get('en')).toEqual(expect.arrayContaining(['English']));
        expect(locales.get('en')).toEqual(expect.arrayContaining(['Misc']));
        expect(locales.get('en-US')).toEqual(expect.not.arrayContaining(['Misc']));
    });
}


() => {
        const langSetting: server.LanguageSetting[]  = [
            { local: 'en,en-US', languageId: '*', dictionaries: ['English'] },
            { local: 'en', languageId: '*', dictionaries: ['Misc'] },
            { local: 'fr', languageId: '*', dictionaries: ['French'] },
            { local: '*', languageId: 'java', dictionaries: ['Java'] },
        ];

        const locales = serverSettings.extractDictionariesByLocaleLanguageSettings(langSetting);

        expect(locales.get('en')).not.toBeNull();
        expect(locales.get('en-GB')).toBeUndefined();
        expect(locales.get('en-US')).not.toBeNull();
        expect(locales.get('fr')).not.toBeNull();
        expect(locales.get('*')).not.toBeNull();
        expect(locales.get('en')).toEqual(expect.arrayContaining(['English']));
        expect(locales.get('en')).toEqual(expect.arrayContaining(['Misc']));
        expect(locales.get('en-US')).toEqual(expect.not.arrayContaining(['Misc']));
    }


(a: DeleteNote) => this._reminderService.removeReminderByRelatedIdIfSet(a.payload.id)


(a: AddNote) => a.payload.remindAt && a.payload.remindAt > 0


(a: AddNote) => new AddNoteReminder({
        id: a.payload.note.id,
        title: a.payload.note.content.substr(0, 40),
        remindAt: a.payload.remindAt,
      })


(a: AddNoteReminder) => {
        const {id, title, remindAt} = a.payload;
        const reminderId = this._reminderService.addReminder('NOTE', id, title, remindAt);

        return [
          new UpdateNote({
            note: {id, changes: {reminderId}}
          }),
          new SnackOpen({
            type: 'SUCCESS',
            msg: `Added reminder for note`,
            ico: 'schedule',
          }),
        ];
      }


(a: UpdateNoteReminder) => {
        const {title, remindAt, reminderId} = a.payload;
        this._reminderService.updateReminder(reminderId, {
          remindAt,
          title,
        });
        return new SnackOpen({
          type: 'SUCCESS',
          msg: `Updated reminder for note`,
          ico: 'schedule',
        });
      }


(a: RemoveNoteReminder) => {
        const {id, reminderId} = a.payload;
        this._reminderService.removeReminder(reminderId);

        return [
          new UpdateNote({
            note: {
              id,
              changes: {reminderId: null}
            }
          }),
          new SnackOpen({
            type: 'SUCCESS',
            msg: `Deleted reminder for note`,
            ico: 'schedule',
          }),
        ];
      }


@Injectable()
export class NoteEffects {
  @Effect({dispatch: false}) updateNote$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.AddNote,
        NoteActionTypes.DeleteNote,
        NoteActionTypes.UpdateNote,
        NoteActionTypes.UpdateNoteOrder,
      ),
      withLatestFrom(
        this._store$.pipe(select(selectCurrentProjectId)),
        this._store$.pipe(select(selectNoteFeatureState)),
      ),
      tap(this._saveToLs.bind(this)),
      tap(this._updateLastActive.bind(this)),
    );

  @Effect({dispatch: false}) updateNoteUi$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.ToggleShowNotes,
        NoteActionTypes.HideNotes,
      ),
      withLatestFrom(
        this._store$.pipe(select(selectCurrentProjectId)),
        this._store$.pipe(select(selectNoteFeatureState)),
      ),
      tap(this._saveToLs.bind(this))
    );

  @Effect({dispatch: false}) deleteNote$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.DeleteNote,
      ),
      tap((a: DeleteNote) => this._reminderService.removeReminderByRelatedIdIfSet(a.payload.id))
    );

  @Effect() addReminderForNewNote$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.AddNote,
      ),
      filter((a: AddNote) => a.payload.remindAt && a.payload.remindAt > 0),
      map((a: AddNote) => new AddNoteReminder({
        id: a.payload.note.id,
        title: a.payload.note.content.substr(0, 40),
        remindAt: a.payload.remindAt,
      }))
    );

  @Effect() addNoteReminder$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.AddNoteReminder,
      ),
      mergeMap((a: AddNoteReminder) => {
        const {id, title, remindAt} = a.payload;
        const reminderId = this._reminderService.addReminder('NOTE', id, title, remindAt);

        return [
          new UpdateNote({
            note: {id, changes: {reminderId}}
          }),
          new SnackOpen({
            type: 'SUCCESS',
            msg: `Added reminder for note`,
            ico: 'schedule',
          }),
        ];
      })
    );

  @Effect() updateNoteReminder$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.UpdateNoteReminder,
      ),
      map((a: UpdateNoteReminder) => {
        const {title, remindAt, reminderId} = a.payload;
        this._reminderService.updateReminder(reminderId, {
          remindAt,
          title,
        });
        return new SnackOpen({
          type: 'SUCCESS',
          msg: `Updated reminder for note`,
          ico: 'schedule',
        });
      })
    );

  @Effect() removeNoteReminder$: any = this._actions$
    .pipe(
      ofType(
        NoteActionTypes.RemoveNoteReminder,
      ),
      mergeMap((a: RemoveNoteReminder) => {
        const {id, reminderId} = a.payload;
        this._reminderService.removeReminder(reminderId);

        return [
          new UpdateNote({
            note: {
              id,
              changes: {reminderId: null}
            }
          }),
          new SnackOpen({
            type: 'SUCCESS',
            msg: `Deleted reminder for note`,
            ico: 'schedule',
          }),
        ];
      })
    );

  constructor(
    private _actions$: Actions,
    private _store$: Store<any>,
    private _persistenceService: PersistenceService,
    private _reminderService: ReminderService,
  ) {
  }

  private _updateLastActive() {
    this._persistenceService.saveLastActive();
  }

  private async _saveToLs([action, currentProjectId, noteState]) {
    if (currentProjectId) {
      this._persistenceService.note.save(currentProjectId, noteState);
    } else {
      throw new Error('No current project id');
    }
  }
}


private _updateLastActive() {
    this._persistenceService.saveLastActive();
  }


private async _saveToLs([action, currentProjectId, noteState]) {
    if (currentProjectId) {
      this._persistenceService.note.save(currentProjectId, noteState);
    } else {
      throw new Error('No current project id');
    }
  }


export interface UpdateOptions<TCacheData extends NonUndefined> {
    data?: (prevData: TCacheData) => TCacheData;
    errors?: Record<string, (prevError: Error | undefined) => Error | undefined>;
    createSplitFor?: NonUndefined;
    clearSplitFor?: NonUndefined;
}


export interface Cache<TCacheData extends NonUndefined> {
    subscribe(callback: () => void): () => void;
    update(opts: UpdateOptions<TCacheData>): void;
    getData(): TCacheData;
    getError(requestId: string): Error | undefined;
    clear(): void;
}


function MainContent(props: Props) {
    const {
        componentName,
        componentType,
        injects,
        componentFilePath,
        configurationSourceCode,
        renderPreview,
    } = props;
    const [panelType, setPanelType] = useState<PanelType>('source');
    const [source, setSource] = useState(defaultCode(componentName));
    const {cases, selectedCaseIndex, setCaseState, saveCase, updateCase} = useCases(source);
    const {currentComponentType, key, onSourceChange} = useDynamicComponent({componentName, componentType, injects});
    const updateSource = useCallback(
        (source: string) => {
            setSource(source);
            onSourceChange(source);
        },
        [onSourceChange]
    );
    const selectCaseByIndex = useCallback(
        async (index: number) => {
            setCaseState(s => ({...s, selectedIndex: index}));
            const selectedCase = cases?.[index];
            if (selectedCase) {
                updateSource(selectedCase.code);
                await fetch(`/play/cases/${selectedCase.name}/TOUCH`, {method: 'PUT'});
            }
        },
        [cases, setCaseState, updateSource]
    );
    const renderMainContent = () => {
        switch (panelType) {
            case 'source':
                return <Editor source={source} onSourceChange={updateSource} />;
            case 'help':
                return <Help componentFilePath={componentFilePath} configurationSourceCode={configurationSourceCode} />;
            case 'description':
                return <CaseDescription currentCase={cases?.[selectedCaseIndex]} />;
            default:
                return null;
        }
    };

    return (

            <Sidebar panelType={panelType} onNavigate={setPanelType} />

                {renderMainContent()}

            <div style={{gridArea: 'preview', borderLeft: '1px solid #eee'}}


export default function PlayGround(props: Props) {
    return (
        <Guard>
            <MainContent {...props} />
        </Guard>
    );
}


(componentName: string) => dedent`
    export default function Repl() {
        return (
            <${componentName} />
        );
    }
`


(source: string) => {
            setSource(source);
            onSourceChange(source);
        }


async (index: number) => {
            setCaseState(s => ({...s, selectedIndex: index}));
            const selectedCase = cases?.[index];
            if (selectedCase) {
                updateSource(selectedCase.code);
                await fetch(`/play/cases/${selectedCase.name}/TOUCH`, {method: 'PUT'});
            }
        }


s => ({...s, selectedIndex: index})


() => {
        switch (panelType) {
            case 'source':
                return <Editor source={source} onSourceChange={updateSource} />;
            case 'help':
                return <Help componentFilePath={componentFilePath} configurationSourceCode={configurationSourceCode} />;
            case 'description':
                return <CaseDescription currentCase={cases?.[selectedCaseIndex]} />;
            default:
                return null;
        }
    }


interface Props extends DynamicContext {
    componentFilePath: string;
    configurationSourceCode: string;
    renderPreview: (content: ReactNode) => ReactNode;
}


renderMainContent()


renderPreview(<Render key={key} target={currentComponentType} />)


() => {
	return (
		<>
		<Routes>
			<Route path="/" element={<Home />}


export type AppConfiguration = {
  port: number;
  news: {
    apiUrl: string;
    apiKey: string;
  };
};


@NgModule({
    declarations: [RoomContentComponent],
    imports: [CommonModule]
  })
  export class RoomContentModule {}


/**
 * Converts the given xml element (in json format) into XmlComponent.
 * @param element the xml element in json presentation
 */
export function convertToXmlComponent(element: XmlElement): ImportedXmlComponent | string | undefined {
    switch (element.type) {
        case undefined:
        case "element":
            const xmlComponent = new ImportedXmlComponent(element.name as string, element.attributes);
            const childElments = element.elements || [];
            for (const childElm of childElments) {
                const child = convertToXmlComponent(childElm);
                if (child !== undefined) {
                    xmlComponent.push(child);
                }
            }
            return xmlComponent;
        case "text":
            return element.text as string;
        default:
            return undefined;
    }
}


class ImportedXmlComponentAttributes extends XmlAttributeComponent<any> {
    // noop
}


/**
 * Represents imported xml component from xml file.
 */
export class ImportedXmlComponent extends XmlComponent {
    /**
     * Converts the xml string to a XmlComponent tree.
     *
     * @param importedContent xml content of the imported component
     */
    public static fromXmlString(importedContent: string): ImportedXmlComponent {
        const xmlObj = xml2js(importedContent, { compact: false }) as XmlElement;
        return convertToXmlComponent(xmlObj) as ImportedXmlComponent;
    }
    /**
     * Converts the xml string to a XmlComponent tree.
     *
     * @param importedContent xml content of the imported component
     */

    // tslint:disable-next-line:variable-name
    constructor(rootKey: string, _attr?: any) {
        super(rootKey);
        if (_attr) {
            this.root.push(new ImportedXmlComponentAttributes(_attr));
        }
    }

    public push(xmlComponent: XmlComponent | string): void {
        this.root.push(xmlComponent);
    }
}


/**
 * Used for the attributes of root element that is being imported.
 */
export class ImportedRootElementAttributes extends XmlComponent {
    // tslint:disable-next-line:variable-name
    constructor(private readonly _attr: any) {
        super("");
    }

    public prepForXml(): IXmlableObject {
        return {
            _attr: this._attr,
        };
    }
}


/**
     * Converts the xml string to a XmlComponent tree.
     *
     * @param importedContent xml content of the imported component
     */
public static fromXmlString(importedContent: string): ImportedXmlComponent {
        const xmlObj = xml2js(importedContent, { compact: false }) as XmlElement;
        return convertToXmlComponent(xmlObj) as ImportedXmlComponent;
    }


public push(xmlComponent: XmlComponent | string): void {
        this.root.push(xmlComponent);
    }


public prepForXml(): IXmlableObject {
        return {
            _attr: this._attr,
        };
    }


@NgModule({
  imports: [
    CommonModule,
    NgxsModule.forRoot(STATES_MODULES, OPTIONS_CONFIG),
    NgxsReduxDevtoolsPluginModule.forRoot(DEVTOOLS_REDUX_CONFIG),
    NgxsLoggerPluginModule.forRoot(LOGGER_CONFIG),
  ],
  exports: [NgxsModule],
})
export class NgxsStoreModule { }


@Module({})
export class SendGridModule {
  public static forRoot(options: SendGridModuleOptions): DynamicModule {
    return {
      module: SendGridModule,
      imports: [SendGridCoreModule.forRoot(options)],
    };
  }

  public static forRootAsync(options: SendGridModuleAsyncOptions): DynamicModule {
    return {
      module: SendGridModule,
      imports: [SendGridCoreModule.forRootAsync(options)],
    };
  }
}


public static forRoot(options: SendGridModuleOptions): DynamicModule {
    return {
      module: SendGridModule,
      imports: [SendGridCoreModule.forRoot(options)],
    };
  }


public static forRootAsync(options: SendGridModuleAsyncOptions): DynamicModule {
    return {
      module: SendGridModule,
      imports: [SendGridCoreModule.forRootAsync(options)],
    };
  }


(target: Target): ElementSize => {
	const el = getTargetElement(target) as Ref<HTMLElement>;

	return {
		width: el.value.clientWidth,
		height: el.value.clientHeight,
	};
}


(target: Target) => {
	const size = reactive(getInitSize(target));

	onMounted(() => {
		const el = getTargetElement(target) as Ref<HTMLElement>;

		const resizeObserver = new ResizeObserver((entries) => {
			const { clientWidth: width, clientHeight: height } = entries[0].target;

			extend(size, { width, height });
		});

		watch(
			el,
			(newEl, oldEl) => {
				if (!newEl) return;

				resizeObserver.observe(newEl);
				if (oldEl) {
					resizeObserver.unobserve(oldEl);
				}
			},
			{ immediate: true }
		);

		onUnmounted(resizeObserver.disconnect);
	});

	return toRefs(size);
}


() => {
		const el = getTargetElement(target) as Ref<HTMLElement>;

		const resizeObserver = new ResizeObserver((entries) => {
			const { clientWidth: width, clientHeight: height } = entries[0].target;

			extend(size, { width, height });
		});

		watch(
			el,
			(newEl, oldEl) => {
				if (!newEl) return;

				resizeObserver.observe(newEl);
				if (oldEl) {
					resizeObserver.unobserve(oldEl);
				}
			},
			{ immediate: true }
		);

		onUnmounted(resizeObserver.disconnect);
	}


(entries) => {
			const { clientWidth: width, clientHeight: height } = entries[0].target;

			extend(size, { width, height });
		}


(newEl, oldEl) => {
				if (!newEl) return;

				resizeObserver.observe(newEl);
				if (oldEl) {
					resizeObserver.unobserve(oldEl);
				}
			}


interface ElementSize {
	width: number;
	height: number;
}


// 'HelloProps' describes the shape of props.
// State is never set so we use the 'undefined' type.
export default class AnswerView extends React.PureComponent<AnswerViewProps, undefined> {
    button: Button;

    constructor(props: AnswerViewProps) {
        super(props);

        this.onChange = this.onChange.bind(this);
    }

    onChange (e: any) {
      const checked = e.target.checked;

      if (this.props.onAnswerChange) {
        this.props.onAnswerChange({ ...this.props.answer, isCorrect: checked });
      }

      this.setState({ checked: checked });
    }

    render() {
        let color = "";

        if (this.props.highlightIfCorrect && this.props.answer.isCorrect) {
          color = "green";
        }
        else if (this.props.highlightIfIncorrect && !this.props.answer.isCorrect && this.props.checked) {
          color = "red";
        }

        const style = {
          "color": color,
          "display": "flex",
          "fontWeight": (this.props.answer.isCorrect && this.props.highlightIfCorrect ? "bold" : "normal") as React.CSSWideKeyword
        };

        return (
            <Checkbox className={!color ? undefined : `answer${color}` } disabled={ this.props.disabled } key={ this.props.answer.id + "_cb" } checked={ this.props.checked } onChange={ this.onChange }>
              <span style=


export interface AnswerViewProps {
    answer: Answer;
    onAnswerChange?: (answer: Answer) => void;
    checked: boolean;
    highlightIfCorrect: boolean;
    highlightIfIncorrect: boolean;
    disabled?: boolean;
}


onChange (e: any) {
      const checked = e.target.checked;

      if (this.props.onAnswerChange) {
        this.props.onAnswerChange({ ...this.props.answer, isCorrect: checked });
      }

      this.setState({ checked: checked });
    }


render() {
        let color = "";

        if (this.props.highlightIfCorrect && this.props.answer.isCorrect) {
          color = "green";
        }
        else if (this.props.highlightIfIncorrect && !this.props.answer.isCorrect && this.props.checked) {
          color = "red";
        }

        const style = {
          "color": color,
          "display": "flex",
          "fontWeight": (this.props.answer.isCorrect && this.props.highlightIfCorrect ? "bold" : "normal") as React.CSSWideKeyword
        };

        return (
            <Checkbox className={!color ? undefined : `answer${color}` }


function Header<T>({ onInsertRow, onDeleteRows }: HeaderProps<T>): React.ReactElement {
    const classes = useStyles();
    return (

テスト

            <button onClick={onInsertRow}>追加</button>
            <button onClick={onDeleteRows}>削除</button>

    );
}


function Pagination<T>({
    page,
    total,
    lastPage,
    hasPrev,
    hasNext,
    rowsPerPage,
    rowsPerPageOptions,
    onChangePage,
    onChangeRowsPerPage,
}: PaginationProps<T>): React.ReactElement {
    const classes = useStyles();

    const handleClickPageFirst = (event: MouseEvent) => {
        onChangePage(event, 0);
    };
    const handleClickPagePrev = (event: MouseEvent) => {
        onChangePage(event, page - 1);
    };
    const handleClickPageNext = (event: MouseEvent) => {
        onChangePage(event, page + 1);
    };
    const handleClickPageLast = (event: MouseEvent) => {
        onChangePage(event, lastPage);
    };

    return (
        <div className={classes.root}>
            <button disabled={!hasPrev} onClick={handleClickPageFirst}>
                ⏪
            </button>
            <button disabled={!hasPrev}


function ColumnHeader<T>({
    className,
    column,
    sort,
    filter,
}: ColumnHeaderProps<T>): React.ReactElement {
    const classes = useStyles();
    const { filterable, ...filterProps } = filter;
    return (

                    {column.displayName ?? column.name}

                    {sort.sortable && <SortButton {...sort} />}

                {filterable && <input type="text" {...filterProps} />}

    );
}

const useCustomHeaderStyles = makeStyles({
    tbody: {
        backgroundColor: '#ffc',
    },
    cell: {
        color: '#009',
    },
});

export const CustomHeader: React.VFC<Record<string, never>> = () => {
    const classes = useCustomHeaderStyles();
    return (
        <Table<Point2D>
            classes={classes}
            data={data}
            columns={columns}
            getRowKey={getRowKey}
            renderColumnHeader={ColumnHeader}
            renderHeader={Header}
            renderPagination={Pagination}
        />
    );
}


(): number => {
    return Math.floor(Math.random() * 1000) / 100;
}


(_, index) => {
    const name = index === 0 ? '' : `point_${index + 1}`;
    return {
        name,
        x: random(),
        y: random(),
        color: 'red',
    };
}


(item) => item.name


(row: number) => `point_${row + 1}`


(item) => `${item.x ?? ''}`


(item) => `${item.y ?? ''}`


(item) => item.color ?? ''


(item: Point2D | undefined, rowIndex: number): string => {
    if (item) {
        return item.name;
    }
    return `new_point_${rowIndex}`;
}


(values: Partial<Point2D>[]) => {
    console.log(values);
}


(args) => {
    const classes = useSampleStyles();
    return <Table<Point2D> classes={classes} {...args} />;
}


() => {
    const [points, setPoints] = useState<Partial<Point2D>[]>([]);
    return (
        <Table<Partial<Point2D>>
            data={points}
            columns={columns}
            getRowKey={getRowKey}
            onChange={setPoints}
            options={{ sortable: false, filterable: false }}


(_, index) => {
    const id = `p_${index}`;
    const name = `point_${index + 1}`;
    const color: Color = Colors[index % Colors.length];
    return {
        id,
        name,
        x: random(),
        y: random(),
        z: random(),
        color,
    };
}


(item) => item.id


(_: number, cells: Cell<Point3D>[][]) => `p_${cells.length + 1}`


(item) => `${item.color}`


(c) => ({ name: ColorNames[c], value: c })


(item) => `${item.x}`


(item) => `${item.y}`


(item) => `${item.z}`


(
    item: Point3D | undefined,
    rowIndex: number,
    cells?: Cell<Point3D>[][]
): string => {
    return item ? item.id : `p_${cells ? cells.length + 1 : 0}`;
}


() => (
    <Table<Point3D> data={points}


({ cell, entity, onChange }) => {
    const handleClick = () => {
        const value = prompt('新しい名前', cell.value);
        onChange(value);
    };

    const handleClick2 = () => {
        alert(JSON.stringify(entity, null, 4));
    };

    return (
        <>
            <button onClick={handleClick}>{cell.value}</button>
            <button onClick={handleClick2}>Show Entity</button>
        </>


() => {
        const value = prompt('新しい名前', cell.value);
        onChange(value);
    }


() => {
        alert(JSON.stringify(entity, null, 4));
    }


(props: CellRenderProps<Point3D>) => <Button {...props} />


(event: MouseEvent) => {
        onChangePage(event, 0);
    }


(event: MouseEvent) => {
        onChangePage(event, page - 1);
    }


(event: MouseEvent) => {
        onChangePage(event, page + 1);
    }


(event: MouseEvent) => {
        onChangePage(event, lastPage);
    }


(value) => (
                    <option key={`rows-per-page-options-${value}`


() => {
    const classes = useCustomHeaderStyles();
    return (
        <Table<Point2D>
            classes={classes}
            data={data}
            columns={columns}
            getRowKey={getRowKey}
            renderColumnHeader={ColumnHeader}
            renderHeader={Header}
            renderPagination={Pagination}
        />


() => {
    return <UpdateDataSample />;
}


() => {
    return <ForwardSample />;
}


// ====== 最も単純なサンプル ======
// 定義
interface Point2D {
    name: string;
    x: number;
    y: number;
    color?: string;
}


// eslint-disable-next-line @typescript-eslint/no-explicit-any
// const isColor = (item: any): item is Color => {
//     return Colors.includes(item);
// };
interface Point3D {
    id: string;
    name: string;
    x: number;
    y: number;
    z: number;
    color: Color;
}


type Color = typeof Colors[number];


async (_, { username, selectedEmail }, context: Context) => {
  const config = {
    headers: {
      'Content-Type': 'application/json',
    },
    data: {
      email: selectedEmail,
    },
  };
  const url = `users/${username}/preferences/email.json`;
  try {
    let { data } = await context.client.delete(url, config);
    if (data.success === 'OK') {
      return 'success';
    } else {
      return data.success;
    }
  } catch (e) {
    errorHandler(e);
  }
}


export default class MyDocument extends Document {
    render() {
        return (
            <Html>
                <Head>
                    <link rel="preconnect" href="https://fonts.gstatic.com" />
                    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500&family=Lexend:wght@400;500;600&display=swap" rel="stylesheet" />
                    <link rel="shortcut icon" href="/favicon.png" type="image/png"/>

                </Head>
                <body>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        )

    }
}


render() {
        return (
            <Html>
                <Head>
                    <link rel="preconnect" href="https://fonts.gstatic.com" />
                    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500&family=Lexend:wght@400;500;600&display=swap" rel="stylesheet" />
                    <link rel="shortcut icon" href="/favicon.png" type="image/png"/>

                </Head>
                <body>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        )

    }


w => this.websites = w.payload


@Component({
  selector: 'app-websites',
  templateUrl: './websites.component.html',
  styleUrls: ['./websites.component.less']
})
export class WebsitesComponent implements OnInit {

  @Output()
  selectionChange: EventEmitter<string> = new EventEmitter<string>();

  websites: WebsiteStatsDto[];
  take: number;

  constructor(private _apiService: BackendApiService) {
    this.websites = [];
    this.take = 5;
   }

  ngOnInit() {
    this._apiService.getWebsites(this.take).subscribe(w => this.websites = w.payload);
  }

  onSelected(website: string) {
    this.selectionChange.emit(website);
  }
}


ngOnInit() {
    this._apiService.getWebsites(this.take).subscribe(w => this.websites = w.payload);
  }


onSelected(website: string) {
    this.selectionChange.emit(website);
  }


@Component({
  selector: 'app-text',
  templateUrl: './text.component.html',
  styleUrls: ['./text.component.css']
})
export class TextComponent implements OnInit, AfterViewChecked {
  @ViewChild('scrollMe') private myScrollContainer: any;
  constructor() { }

  ngOnInit(): void {
    this.scrollToBottom();
  }

  ngAfterViewChecked() {
    this.scrollToBottom();
  }

  scrollToBottom(): void {
    try {
      this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
    } catch(err) { }
  }

}


ngOnInit(): void {
    this.scrollToBottom();
  }


ngAfterViewChecked() {
    this.scrollToBottom();
  }


scrollToBottom(): void {
    try {
      this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
    } catch(err) { }
  }


x => {
      console.log('loggin succesful');
      this.alertifyService.success('Logowanie przebiegło pomylnie.');
    }


error => {
      console.log('Failde to login');
      this.alertifyService.error('Logowanie nie powiodło się, sprobuj ponownie.');
    }


() => {  // i przeladowuje na zakladke home
      this.route.navigate(['/home/main']);
    }


@Component({
  selector: 'app-navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.css']
})
export class NavigationBarComponent implements OnInit {
  model: any = {}; // przetrzyma wartosci naszych pol z html
  constructor(public authService: AuthService, private route: Router, private alertifyService: AlertifyServicesService) { }

  ngOnInit() {

  }

  login() {
    console.log(this.model);
    this.authService.login(this.model).subscribe( x => {
      console.log('loggin succesful');
      this.alertifyService.success('Logowanie przebiegło pomylnie.');
    }, error => {
      console.log('Failde to login');
      this.alertifyService.error('Logowanie nie powiodło się, sprobuj ponownie.');
    }, () => {  // i przeladowuje na zakladke home
      this.route.navigate(['/home/main']);
    });
  }

  loggedIn() {
   return this.authService.leggedIn();  // sprawdza czy jestesmy zalogowani

    // const token = localStorage.getItem('token');  // pobiera item o nazwie token z'lokalnego magazynu'
  //  return !!token;
    // te dwa wykrzykniki znacza ze jak token nie jest pusty to zwraca true a jak pusty to zwraca false
  }

}


ngOnInit() {

  }


login() {
    console.log(this.model);
    this.authService.login(this.model).subscribe( x => {
      console.log('loggin succesful');
      this.alertifyService.success('Logowanie przebiegło pomylnie.');
    }, error => {
      console.log('Failde to login');
      this.alertifyService.error('Logowanie nie powiodło się, sprobuj ponownie.');
    }, () => {  // i przeladowuje na zakladke home
      this.route.navigate(['/home/main']);
    });
  }


loggedIn() {
   return this.authService.leggedIn();  // sprawdza czy jestesmy zalogowani

    // const token = localStorage.getItem('token');  // pobiera item o nazwie token z'lokalnego magazynu'
  //  return !!token;
    // te dwa wykrzykniki znacza ze jak token nie jest pusty to zwraca true a jak pusty to zwraca false
  }


// @declaration: true
declare function myRandBool(): boolean;


() => {
      this.providers.delete(id)
    }


o => {
      let [id, p] = o
      return Promise.resolve(p.provideWorkspaceSymbols(query, token)).then(item => {
        if (item) {
          (item as any).source = id
          res.push(...item)
        }
      })
    }


item => {
        if (item) {
          (item as any).source = id
          res.push(...item)
        }
      }


export default class WorkspaceSymbolManager implements Disposable {
  private providers: Map<string, WorkspaceSymbolProvider> = new Map()

  public register(provider: WorkspaceSymbolProvider): Disposable {
    let id = uuid()
    this.providers.set(id, provider)
    return Disposable.create(() => {
      this.providers.delete(id)
    })
  }

  public async provideWorkspaceSymbols(
    _document: TextDocument,
    query: string,
    token: CancellationToken
  ): Promise<SymbolInformation[]> {
    let entries = Array.from(this.providers.entries())
    if (!entries.length) return []
    let res: SymbolInformation[] = []
    await Promise.all(entries.map(o => {
      let [id, p] = o
      return Promise.resolve(p.provideWorkspaceSymbols(query, token)).then(item => {
        if (item) {
          (item as any).source = id
          res.push(...item)
        }
      })
    }))
    return res
  }

  public async resolveWorkspaceSymbol(
    symbolInfo: SymbolInformation,
    token: CancellationToken
  ): Promise<SymbolInformation> {
    let provider = this.providers.get((symbolInfo as any).source)
    if (!provider) return
    if (typeof provider.resolveWorkspaceSymbol != 'function') {
      return Promise.resolve(symbolInfo)
    }
    return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token))
  }

  public hasProvider(): boolean {
    return this.providers.size > 0
  }

  public dispose(): void {
    this.providers = new Map()
  }
}


public register(provider: WorkspaceSymbolProvider): Disposable {
    let id = uuid()
    this.providers.set(id, provider)
    return Disposable.create(() => {
      this.providers.delete(id)
    })
  }


public async provideWorkspaceSymbols(
    _document: TextDocument,
    query: string,
    token: CancellationToken
  ): Promise<SymbolInformation[]> {
    let entries = Array.from(this.providers.entries())
    if (!entries.length) return []
    let res: SymbolInformation[] = []
    await Promise.all(entries.map(o => {
      let [id, p] = o
      return Promise.resolve(p.provideWorkspaceSymbols(query, token)).then(item => {
        if (item) {
          (item as any).source = id
          res.push(...item)
        }
      })
    }))
    return res
  }


public async resolveWorkspaceSymbol(
    symbolInfo: SymbolInformation,
    token: CancellationToken
  ): Promise<SymbolInformation> {
    let provider = this.providers.get((symbolInfo as any).source)
    if (!provider) return
    if (typeof provider.resolveWorkspaceSymbol != 'function') {
      return Promise.resolve(symbolInfo)
    }
    return await Promise.resolve(provider.resolveWorkspaceSymbol(symbolInfo, token))
  }


public hasProvider(): boolean {
    return this.providers.size > 0
  }


public dispose(): void {
    this.providers = new Map()
  }


async function getFtpFileList(): Promise<any[]> {
    return new Promise((resolve, reject) => {
        if (ftp == null) {
            reject('ftp is null');
        }
        ftp.ls('.', (err, res) => {
            if (err) {
                reject(err);
            }
            resolve(res);
        });
    });
}


/**
 * INFO: FTP 서버로부터 파일을 가져온다
 * @param filename 가져올 파일 이름
 */
async function getFtpFileToMemory(filename: string): Promise<Buffer> {
    return new Promise((resolve, reject) => {
        if (ftp == null) {
            reject('ftp is null');
        }
        ftp.get(filename, (err, socket) => {
            if (err) {
                reject(err);
            }
            let res: Buffer = Buffer.from('');
            socket.on('data', data => {
                res = Buffer.concat([res, data]);
            });
            socket.on('close', err => {
                if (err) {
                    reject(err);
                }
                resolve(res);
            });
            socket.resume();
        });
    });
}


/**
 * INFO: FTP 서버 파일을 로컬에 저장한다
 * @param filename 저장할 파일 이름
 */
async function saveFtpFileToLocal(filename: string): Promise<void> {
    let res: Buffer = await getFtpFileToMemory(filename);
    let asyncWriteFile = util.promisify(fs.writeFile);
    await asyncWriteFile(filename, res);
}


function initFtpClient() {
    let ftpInfo = envInfo.ftp_info;
    ftp = new jsftp({
        host: ftpInfo.host,
        port: ftpInfo.port,
        user: ftpInfo.user,
        pass: ftpInfo.pass,
    });
}


async function main() {
    try {
        initFtpClient();
        console.log('initFtpClient Ok.');

        //INFO: FTP 서버 파일 목록을 가져온다.
        let fileList = (await getFtpFileList()) as IFileInfo[];
        console.log('getFtpFileList Ok.');
        console.log(fileList);
        let isVersionFileExist: boolean = false;

        //INFO: FTP 서버 파일 중에 원하는 파일이 있는지 검사한다.
        for (let fileInfo of fileList) {
            if (fileInfo.name !== targetFile) {
                continue;
            }
            isVersionFileExist = true;
            break;
        }

        if (!isVersionFileExist) {
            throw new Error(targetFile + ' does not exist');
        }

        console.log('isVersionFileExist Ok.');

        //INFO: 원하는 파일을 서버로부터 읽어들인다.
        let version: string = (await getFtpFileToMemory(targetFile)).toString('utf8');
        console.log('getFtpFile Ok.');
        console.log('version : ' + version);

        //INFO: 원하는 파일을 내려받아 로컬에 저장한다
        await saveFtpFileToLocal(targetFile);
    } catch (ex) {
        console.error(ex);
        process.exit(0);
    } finally {
        if (ftp != null) {
            ftp.destroy();
        }
    }
}


(resolve, reject) => {
        if (ftp == null) {
            reject('ftp is null');
        }
        ftp.ls('.', (err, res) => {
            if (err) {
                reject(err);
            }
            resolve(res);
        });
    }


(err, res) => {
            if (err) {
                reject(err);
            }
            resolve(res);
        }


(resolve, reject) => {
        if (ftp == null) {
            reject('ftp is null');
        }
        ftp.get(filename, (err, socket) => {
            if (err) {
                reject(err);
            }
            let res: Buffer = Buffer.from('');
            socket.on('data', data => {
                res = Buffer.concat([res, data]);
            });
            socket.on('close', err => {
                if (err) {
                    reject(err);
                }
                resolve(res);
            });
            socket.resume();
        });
    }


(err, socket) => {
            if (err) {
                reject(err);
            }
            let res: Buffer = Buffer.from('');
            socket.on('data', data => {
                res = Buffer.concat([res, data]);
            });
            socket.on('close', err => {
                if (err) {
                    reject(err);
                }
                resolve(res);
            });
            socket.resume();
        }


data => {
                res = Buffer.concat([res, data]);
            }


err => {
                if (err) {
                    reject(err);
                }
                resolve(res);
            }


interface IFileInfo {
    name: string;
    type: number;
    size: string;
    owner: string;
    group: string;
}


/**
 *
Creates a new ledger in your AWS account.

 * @example
 * Use a bare-bones client and the command you need to make an API call.
 * ```javascript
 * import { QLDBClient, CreateLedgerCommand } from "@aws-sdk/client-qldb"; // ES Modules import
 * // const { QLDBClient, CreateLedgerCommand } = require("@aws-sdk/client-qldb"); // CommonJS import
 * const client = new QLDBClient(config);
 * const command = new CreateLedgerCommand(input);
 * const response = await client.send(command);
 * ```
 *
 * @see {@link CreateLedgerCommandInput} for command's `input` shape.
 * @see {@link CreateLedgerCommandOutput} for command's `response` shape.
 * @see {@link QLDBClientResolvedConfig | config} for command's `input` shape.
 *
 */
export class CreateLedgerCommand extends $Command<
  CreateLedgerCommandInput,
  CreateLedgerCommandOutput,
  QLDBClientResolvedConfig
> {
  // Start section: command_properties
  // End section: command_properties

  constructor(readonly input: CreateLedgerCommandInput) {
    // Start section: command_constructor
    super();
    // End section: command_constructor
  }

  /**
   * @internal
   */
  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: QLDBClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateLedgerCommandInput, CreateLedgerCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "QLDBClient";
    const commandName = "CreateLedgerCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: CreateLedgerRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateLedgerResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }

  private serialize(input: CreateLedgerCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1CreateLedgerCommand(input, context);
  }

  private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<CreateLedgerCommandOutput> {
    return deserializeAws_restJson1CreateLedgerCommand(output, context);
  }

  // Start section: command_body_extra
  // End section: command_body_extra
}


export interface CreateLedgerCommandInput extends CreateLedgerRequest {}


export interface CreateLedgerCommandOutput extends CreateLedgerResponse, __MetadataBearer {}


/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: QLDBClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateLedgerCommandInput, CreateLedgerCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "QLDBClient";
    const commandName = "CreateLedgerCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: CreateLedgerRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateLedgerResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(input: CreateLedgerCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1CreateLedgerCommand(input, context);
  }


private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<CreateLedgerCommandOutput> {
    return deserializeAws_restJson1CreateLedgerCommand(output, context);
  }


/**
 * Configures extensions for the registry.
 *
 * `extensionIDsByCategory`: Object mapping category name to array of extension ids in that category
 * `extensions`: Object mapping extension id to the configured extension with that id
 *
 * `configureExtensionRegistry` is passed a cache of configured extensions to avoid
 * parsing manifests multiple times during the lifecycle of the extension registry.
 */
export function configureExtensionRegistry(
    nodes: RegistryExtensionFieldsForList[],
    configuredExtensionCache: ConfiguredExtensionCache
): ConfiguredExtensionRegistry {
    const extensions: ConfiguredRegistryExtensions = {}

    const extensionIDsByCategory: ConfiguredExtensionRegistry['extensionIDsByCategory'] = createRecord(
        EXTENSION_CATEGORIES,
        () => ({ primaryExtensionIDs: [], allExtensionIDs: [] })
    )

    for (const node of nodes) {
        // cache parsed extension manifests
        let configuredRegistryExtension = configuredExtensionCache.get(node.id)
        if (!configuredRegistryExtension) {
            configuredRegistryExtension = toConfiguredRegistryExtension(node)
            configuredExtensionCache.set(node.id, configuredRegistryExtension)
        }

        let categories: ExtensionCategory[]
        if (!isErrorLike(configuredRegistryExtension.manifest) && configuredRegistryExtension.manifest?.categories) {
            categories = validCategories(configuredRegistryExtension.manifest.categories) || NO_VALID_CATEGORIES
        } else {
            categories = NO_VALID_CATEGORIES
        }
        // TODO: Add `primaryCategory` to extension schema
        // Primary category is either specified or inferred by array position
        const primaryCategory = categories[0]

        extensionIDsByCategory[primaryCategory].primaryExtensionIDs.push(configuredRegistryExtension.id)
        for (const category of categories) {
            extensionIDsByCategory[category].allExtensionIDs.push(configuredRegistryExtension.id)
        }

        extensions[configuredRegistryExtension.id] = configuredRegistryExtension
    }

    return { extensions, extensionIDsByCategory }
}


/** Groups extensions by category */
export function applyCategoryFilter(
    extensionIDsByCategory: ConfiguredExtensionRegistry['extensionIDsByCategory'],
    categories: ExtensionCategory[],
    selectedCategories: ExtensionCategory[]
): Record<ExtensionCategory, string[]> {
    if (selectedCategories.length === 0) {
        // Primary categories
        return createRecord(categories, category => [...extensionIDsByCategory[category].primaryExtensionIDs])
    }

    // Categorize in toggle order, make sure the same extension doesn't appear twice.
    const filteredCategorizedExtensions = createRecord<ExtensionCategory, string[]>(selectedCategories, () => [])

    // To "blacklist" extension ID after it has been used
    const takenIDs = new Set<string>()

    for (const category of selectedCategories) {
        for (const extensionID of extensionIDsByCategory[category].allExtensionIDs) {
            if (!takenIDs.has(extensionID)) {
                filteredCategorizedExtensions[category].push(extensionID)

                takenIDs.add(extensionID)
            }
        }
    }

    return filteredCategorizedExtensions
}


/**
 * Filters categorized registry extensions by enablement (enabled | disabled | all)
 */
export function applyExtensionsEnablement(
    categorizedExtensions: Record<ExtensionCategory, string[]>,
    filteredCategoryIDs: ExtensionCategory[],
    enablement: ExtensionsEnablement,
    settings: Settings | ErrorLike | null
): Record<ExtensionCategory, string[]> {
    if (enablement === 'all') {
        return categorizedExtensions
    }

    return createRecord(filteredCategoryIDs, category =>
        categorizedExtensions[category].filter(
            extensionID => (enablement === 'enabled') === isExtensionEnabled(settings, extensionID)
        )
    )
}


() => ({ primaryExtensionIDs: [], allExtensionIDs: [] })


category => [...extensionIDsByCategory[category].primaryExtensionIDs]


category =>
        categorizedExtensions[category].filter(
            extensionID => (enablement === 'enabled') === isExtensionEnabled(settings, extensionID)
        )


extensionID => (enablement === 'enabled') === isExtensionEnabled(settings, extensionID)


export interface ConfiguredRegistryExtensions {
    [id: string]: Pick<ConfiguredRegistryExtension<RegistryExtensionFieldsForList>, 'manifest' | 'id'>
}


export interface ConfiguredExtensionRegistry {
    /** Maps categories to ids of extensions  */
    extensionIDsByCategory: Record<
        ExtensionCategory,
        {
            /** IDs of all extensions for which this is the primary category */
            primaryExtensionIDs: string[]
            /** IDs of all extensions that fall into this category */
            allExtensionIDs: string[]
        }
    >

    /** All extensions returned by the query indexed by id */
    extensions: ConfiguredRegistryExtensions
}


e => e.toCredentialHash()


export class VpDocument {
    public static readonly FIRST_CONTEXT_ENTRY = 'https://www.w3.org/2018/credentials/v1';
    public static readonly VERIFIABLE_PRESENTATION_TYPE = 'VerifiablePresentation';
    public static readonly VERIFIABLE_CREDENTIAL = 'verifiableCredential';
    public static readonly CONTEXT = '@context';
    public static readonly ID = 'id';
    public static readonly TYPE = 'type';
    public static readonly PROOF = 'proof';
    public static readonly ISSUER = 'issuer';
    public static readonly ISSUANCE_DATE = 'issuanceDate';

    protected id: string;
    protected context: string[];
    protected type: string[];
    protected credentials: VcDocument[];
    protected proof: any;
    protected issuer: Issuer;
    protected issuanceDate: Timestamp;

    constructor() {
        this.credentials = [];
        this.type = [VpDocument.VERIFIABLE_PRESENTATION_TYPE];
        this.context = [VpDocument.FIRST_CONTEXT_ENTRY];
    }

    public getId(): string {
        return this.id;
    }

    public setId(id: string): void {
        this.id = id;
    }

    public getIssuer(): Issuer {
        return this.issuer;
    }

    public getIssuerDid(): string {
        if (this.issuer) {
            return this.issuer.getId();
        }
        return null;
    }

    public setIssuer(issuer: string | Issuer | DIDDocument): void {
        if (typeof issuer === 'string') {
            this.issuer = new Issuer(issuer);
        } else if (issuer instanceof Issuer) {
            this.issuer = issuer;
        } else if (issuer instanceof DIDDocument) {
            this.issuer = new Issuer(issuer.getDid());
        }
    }

    public getContext(): string[] {
        return this.context;
    }

    public addContext(context: string): void {
        this.context.push(context);
    }

    public getType(): string[] {
        return this.type;
    }

    public addType(type: string): void {
        this.type.push(type);
    }

    public getProof(): any {
        return this.proof;
    }

    public setProof(proof: any): void {
        this.proof = proof;
    }

    public getVerifiableCredential(index: number = 0): VcDocument {
        return this.credentials[index];
    }

    public getVerifiableCredentials(): VcDocument[] {
        return this.credentials;
    }

    public get length(): number {
        return this.credentials.length;
    }

    public addVerifiableCredential(vc: VcDocument): void {
        if (vc) {
            this.credentials.push(vc);
        }
    }

    public addVerifiableCredentials(vcs: VcDocument[]): void {
        if (vcs) {
            for (let index = 0; index < vcs.length; index++) {
                this.credentials.push(vcs[index]);
            }
        }
    }

    public toJson(): string {
        return JSON.stringify(this.toJsonTree());
    }

    public toJsonTree(): IVP {
        const rootObject: any = {};
        if (this.id)
            rootObject[VpDocument.ID] = this.id;
        if (this.type)
            rootObject[VpDocument.TYPE] = this.type;
        if (this.issuer)
            rootObject[VpDocument.ISSUER] = this.issuer.toJsonTree();
        if (this.issuanceDate)
            rootObject[VpDocument.ISSUANCE_DATE] = TimestampUtils.toJSON(this.issuanceDate);

        const context = [];
        if (this.context) {
            for (let index = 0; index < this.context.length; index++) {
                const element = this.context[index];
                context.push(element);
            }
        }
        rootObject[VpDocument.CONTEXT] = context;

        const verifiableCredential = [];
        if (this.credentials) {
            for (let index = 0; index < this.credentials.length; index++) {
                const element = this.credentials[index];
                verifiableCredential.push(element.toJsonTree());
            }
        }
        rootObject[VpDocument.VERIFIABLE_CREDENTIAL] = verifiableCredential;

        if (this.proof) {
            rootObject[VpDocument.PROOF] = this.proof;
        }

        return rootObject;
    }

    public static fromJson(json: string): VpDocument {
        let result: VpDocument;
        try {
            const root = JSON.parse(json);
            result = this.fromJsonTree(root);

        } catch (e) {
            throw new Error('Given JSON string is not a valid VpDocument ' + e.message);
        }
        return result;
    }

    public static fromJsonTree(json: IVP): VpDocument {
        if (!json) {
            throw new Error('JSON Object is empty');
        }

        const result = new VpDocument();
        if (json[VpDocument.ID])
            result.id = json[VpDocument.ID];
        if (json[VpDocument.TYPE])
            result.type = json[VpDocument.TYPE];
        if (json[VpDocument.ISSUER])
            result.issuer = Issuer.fromJsonTree(json[VcDocument.ISSUER]);
        if (json[VpDocument.ISSUANCE_DATE])
            result.issuanceDate = TimestampUtils.fromJson(json[VcDocument.ISSUANCE_DATE]);

        const jsonVerifiableCredential = json[VpDocument.VERIFIABLE_CREDENTIAL];
        if (jsonVerifiableCredential) {
            if (Array.isArray(jsonVerifiableCredential)) {
                for (let i = 0; i < jsonVerifiableCredential.length; i++) {
                    const item = jsonVerifiableCredential[i];
                    const credential = VcDocument.fromJsonTree(item);
                    result.addVerifiableCredential(credential);
                }
            } else {
                const credential = VcDocument.fromJsonTree(jsonVerifiableCredential);
                result.addVerifiableCredential(credential);
            }
        }
        const context = json[VcDocument.CONTEXT];
        if (context) {
            if (Array.isArray(context)) {
                for (let i = 0; i < context.length; i++) {
                    const item = context[i];
                    result.addContext(item);
                }
            } else {
                result.addContext(context);
            }

            result.context = context.slice();
        }

        result.proof = json[VpDocument.PROOF] || null;

        return result;
    }

    public toCredentialHash(): string {
        const map = {};
        map[VpDocument.ID] = this.id;
        map[VpDocument.TYPE] = this.type;
        if (this.credentials) {
            map[VpDocument.VERIFIABLE_CREDENTIAL] = this.credentials.map(e => e.toCredentialHash());
        }
        const json: string = JSON.stringify(map);
        const hash: Uint8Array = Hashing.sha256.digest(json);
        return Hashing.base58.encode(hash);
    }

    public proofFromJson(json: any): void {
        this.setProof(json[VpDocument.PROOF]);
    }

    public getDocument(): IVP {
        return this.toJsonTree();
    }
}


public getId(): string {
        return this.id;
    }


public setId(id: string): void {
        this.id = id;
    }


public getIssuer(): Issuer {
        return this.issuer;
    }


public getIssuerDid(): string {
        if (this.issuer) {
            return this.issuer.getId();
        }
        return null;
    }


public setIssuer(issuer: string | Issuer | DIDDocument): void {
        if (typeof issuer === 'string') {
            this.issuer = new Issuer(issuer);
        } else if (issuer instanceof Issuer) {
            this.issuer = issuer;
        } else if (issuer instanceof DIDDocument) {
            this.issuer = new Issuer(issuer.getDid());
        }
    }


public getContext(): string[] {
        return this.context;
    }


public addContext(context: string): void {
        this.context.push(context);
    }


public getType(): string[] {
        return this.type;
    }


public addType(type: string): void {
        this.type.push(type);
    }


public getProof(): any {
        return this.proof;
    }


public setProof(proof: any): void {
        this.proof = proof;
    }


public getVerifiableCredential(index: number = 0): VcDocument {
        return this.credentials[index];
    }


public getVerifiableCredentials(): VcDocument[] {
        return this.credentials;
    }


public addVerifiableCredential(vc: VcDocument): void {
        if (vc) {
            this.credentials.push(vc);
        }
    }


public addVerifiableCredentials(vcs: VcDocument[]): void {
        if (vcs) {
            for (let index = 0; index < vcs.length; index++) {
                this.credentials.push(vcs[index]);
            }
        }
    }


public toJson(): string {
        return JSON.stringify(this.toJsonTree());
    }


public toJsonTree(): IVP {
        const rootObject: any = {};
        if (this.id)
            rootObject[VpDocument.ID] = this.id;
        if (this.type)
            rootObject[VpDocument.TYPE] = this.type;
        if (this.issuer)
            rootObject[VpDocument.ISSUER] = this.issuer.toJsonTree();
        if (this.issuanceDate)
            rootObject[VpDocument.ISSUANCE_DATE] = TimestampUtils.toJSON(this.issuanceDate);

        const context = [];
        if (this.context) {
            for (let index = 0; index < this.context.length; index++) {
                const element = this.context[index];
                context.push(element);
            }
        }
        rootObject[VpDocument.CONTEXT] = context;

        const verifiableCredential = [];
        if (this.credentials) {
            for (let index = 0; index < this.credentials.length; index++) {
                const element = this.credentials[index];
                verifiableCredential.push(element.toJsonTree());
            }
        }
        rootObject[VpDocument.VERIFIABLE_CREDENTIAL] = verifiableCredential;

        if (this.proof) {
            rootObject[VpDocument.PROOF] = this.proof;
        }

        return rootObject;
    }


public static fromJson(json: string): VpDocument {
        let result: VpDocument;
        try {
            const root = JSON.parse(json);
            result = this.fromJsonTree(root);

        } catch (e) {
            throw new Error('Given JSON string is not a valid VpDocument ' + e.message);
        }
        return result;
    }