@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
598 lines • 69.6 kB
JavaScript
import { Validators } from '@angular/forms';
import { bufferToHexString, hexStringToBuffer, } from '@iotize/common/byte-converter';
import { FACTORY_RESET_MODE_VERSION, TapInfo, TAP_MANAGER_APP_ID, } from '@iotize/ionic';
import { HostProtocol, SpecialFeature, TapResponse, TargetProtocol, } from '@iotize/tap';
import { converters } from '@iotize/tap/service/core';
import { NfcConnectionPriority, NfcPairingMode, } from '@iotize/tap/service/impl/interface';
import { WifiKeyVisibility, WifiMode, WifiSSIDVisibility, } from '@iotize/tap/service/impl/wifi';
import { combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { enumToOptions } from './utility';
const TAP_CONFIG_PATTERN = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/;
const IPV4_PATTERN = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/;
const IPV4_MASK_PATTERN = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/;
const SSID_PATTERN = /^[^ !#;+\]\/"\t][^+\]\/"\t]{0,30}[^ !#;+\]\/"\t]$|^[^ !#;+\]\/"\t]$/;
function regexValidator(pattern, message) {
return (control) => {
const value = control.value;
const valueMatchPattern = pattern.test(value);
return !valueMatchPattern
? { invalidFormat: { value: control.value, message } }
: null;
};
}
const validateTapVersion = regexValidator(TAP_CONFIG_PATTERN, `Must be a valid semantic version (Major.Minor.Patch).`);
function enumFormatter(data) {
return (value) => {
if (Array.isArray(value)) {
if (value.length === 0) {
return '-';
}
return value.map((key) => HostProtocol[key]).join(', ');
}
else {
return data[value];
}
};
}
export function isTapConfigured(version) {
return !(version.major === 0 && version.minor === 0 && version.patch === 0);
}
function stringToEnumArray(v, mapping) {
return v
.split(',')
.map((item) => item.trim())
.map((item) => {
if (!(item in mapping)) {
throw new Error(`Invalid value "${item}". Must one of the following: ${Object.keys(mapping).join(', ')}`);
}
return mapping[item];
});
}
var WifiTxPowerEnum;
(function (WifiTxPowerEnum) {
WifiTxPowerEnum[WifiTxPowerEnum["default"] = 0] = "default";
WifiTxPowerEnum[WifiTxPowerEnum["10 dBm"] = 40] = "10 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["12.5 dBm"] = 50] = "12.5 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["15 dBm"] = 60] = "15 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["17.5 dBm"] = 70] = "17.5 dBm";
WifiTxPowerEnum[WifiTxPowerEnum["20 dBm"] = 80] = "20 dBm";
})(WifiTxPowerEnum || (WifiTxPowerEnum = {}));
const IPV4_VALIDATOR = regexValidator(IPV4_PATTERN, `Not a valid IPv4 address (eg 192.168.20.1)`);
export const defaultInfoResolverConfig = [
{
key: TapInfo.HostProtocol,
input: createEnumField('HostProtocol', HostProtocol),
viewFormatter: enumFormatter(HostProtocol),
},
{
key: TapInfo.configVersion,
input: {
formValidators: [validateTapVersion],
},
viewFormatter: (v) => {
if (v === FACTORY_RESET_MODE_VERSION) {
return 'FACTORY RESET';
}
else if (v === '255.255.65535') {
return 'CONFIGURATION MODE';
}
else if (v) {
return `v${v}`;
}
else {
return 'UNKNOWN';
}
},
editFormatter: {
read: (input) => {
return input;
},
write: (v) => {
return v || FACTORY_RESET_MODE_VERSION;
},
},
},
{
key: TapInfo.CloudEndpoint,
getValue: async (tap) => {
const hostname = (await tap.service.mqtt.getBrokerHostname()).body();
const port = (await tap.service.mqtt.getBrokerPort()).body();
return `${hostname}:${port}`;
},
putValue: async (tap, value) => {
const [hostname, port] = value.split(':');
const setPort = await tap.service.mqtt.putBrokerPort(port || '1883');
setPort.successful();
return tap.service.mqtt.putBrokerHostname(hostname);
},
},
{
key: TapInfo.TargetProtocolConfiguration,
viewFormatter: (v) => `${bufferToHexString(v)}`,
editFormatter: {
read: (input) => {
return input ? hexStringToBuffer(input) : new Uint8Array();
},
write: (v) => {
return v ? bufferToHexString(v) : '';
},
},
getValue: async (tap) => {
const result = await tap.service.target.getModbusTcpConfiguration();
result.successful();
return result.rawBody();
},
putValue: async (tap, value) => {
return await tap.lwm2m.put('/1027//21', value);
},
},
{
input: {
type: 'toggle',
},
key: TapInfo.NFCConnectionPriority,
getValue: async (tap) => {
const value = (await tap.service.interface.getNfcConnectionPriority()).body();
return value === NfcConnectionPriority.NFC_PRIORITY;
},
putValue: (tap, val) => {
const mode = val
? NfcConnectionPriority.NFC_NON_PRIORITY
: NfcConnectionPriority.NFC_PRIORITY;
return tap.service.interface.putNfcConnectionPriority(mode);
},
},
{
key: TapInfo.NFCPairingMode,
input: createEnumField('NfcPairingMode', NfcPairingMode),
},
{
key: TapInfo.DataLogMaxPacketCount,
viewFormatter: (v) => {
return v === 0 ? 'NO LIMIT' : v.toString();
},
input: {
type: 'number',
},
},
{
key: TapInfo.IsTargetConnected,
// viewFormatter: (v: boolean) => v ? 'YES' : 'NO',
getValue: (tap) => tap.service.target.isConnected(),
putValue: (tap, enabled) => {
if (enabled) {
return tap.service.target.connect();
}
else {
return tap.service.target.disconnect();
}
},
input: {
type: 'toggle',
},
},
{
key: TapInfo.universalLink,
icon: 'link',
},
{
key: TapInfo.androidApplicationRecord,
// TODO replace with getAndroidApplicationId()
getValue: async (tap) => {
const appPath = (await tap.service.interface.getAppPath()).body();
if (appPath.startsWith('$4/')) {
return appPath.substring(3);
}
else {
return TAP_MANAGER_APP_ID;
}
},
viewFormatter: (input) => {
if (input === TAP_MANAGER_APP_ID) {
return `${input} (Tap Manager)`;
}
return input;
},
putValue: async (tap, value) => {
return tap.service.interface.putAppPath(`$4/${value}`);
},
},
{
key: TapInfo.useEncryption,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.scramActivated;
},
},
{
key: TapInfo.lockFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableHardwareFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityScramActivated,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.scramActivated;
},
},
{
key: TapInfo.InterfaceSecurityDisableHardwareFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableHardwareFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityDisabledResourceFactoryReset,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableResourceFactoryReset;
},
},
{
key: TapInfo.InterfaceSecurityDisabledLoginWithUID,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.disableLoginWithUID;
},
},
{
key: TapInfo.hashPassword,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return lockOptions.hashPassword;
},
},
{
key: TapInfo.isLoginWithUIDEnabled,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableLoginWithUID;
},
},
{
key: TapInfo.isLWM2MFactoryResetEnabled,
input: {
type: 'toggle',
},
editable: false,
getValue: async (tap) => {
const lockOptions = (await tap.service.interface.getSecurityOptions()).body();
return !lockOptions.disableResourceFactoryReset;
},
},
{
key: TapInfo.appPath,
putValue: (tap, value) => {
return tap.service.interface.putAppPath(value);
},
getValue: (tap) => tap.service.interface.getAppPathResolved(),
},
{
key: TapInfo.TargetProtocol,
getValue: (tap) => {
return tap.service.target.getProtocol();
},
putValue: (tap, protocol) => {
return tap.service.target.putProtocol(protocol);
},
setValue: (tap, protocol) => {
return tap.service.target.setProtocol(protocol);
},
viewFormatter: enumFormatter(TargetProtocol),
input: {
type: 'select',
options: enumToOptions(TargetProtocol).filter((f) => {
return f.key !== TargetProtocol.JTAG;
}),
},
},
{
key: '/interface/available-host-protocols',
viewFormatter: enumFormatter(HostProtocol),
editFormatter: {
write: (v) => {
// console.log('Host protocols: ', v);
if (!v || v.length === 0) {
return 'NONE';
}
return v.map((key) => HostProtocol[key]).join(', ');
},
read: (v) => {
return stringToEnumArray(v, HostProtocol);
},
},
},
{
key: TapInfo.authorizedHostProtocols,
input: {
type: 'select',
multiple: true,
options: [],
},
viewFormatter: enumFormatter(HostProtocol),
init: async (_service, config, infoResolver) => {
const hostProtocols = await infoResolver.getValue(TapInfo.availableHostProtocols);
if (config.input !== undefined) {
config.input.options = hostProtocols.map((key) => {
return { key: key, text: HostProtocol[key] };
});
}
},
},
{
key: TapInfo.AdpVersion,
getValue: (tap) => tap.service.tapnpass.getStatus(),
viewFormatter: (stats) => {
const v = stats.header.version;
return `${v.major}.${v.minor}.${v.patch}`;
},
},
{
key: TapInfo.WifiHostname,
viewFormatter: (v) => {
if (v === '0.0.0.0') {
return 'NO IP';
}
return v;
},
},
{
key: TapInfo.WifiSSID,
input: {
formValidators: [
regexValidator(SSID_PATTERN, `This is not a valid SSID. It can be any alphanumeric, case-sensitive entry from 1 to 32 characters. Trailing or leading spaces are not allowed.`),
],
},
},
{
key: TapInfo.WifiSSIDVisibility,
input: createEnumField('WifiSSIDVisibility', WifiSSIDVisibility),
viewFormatter: enumFormatter(WifiSSIDVisibility),
},
{
key: TapInfo.WifiKeyVisibility,
input: createEnumField('WifiKeyVisibility', WifiKeyVisibility),
viewFormatter: enumFormatter(WifiKeyVisibility),
},
{
key: TapInfo.WifiTxPower,
viewFormatter: enumFormatter(WifiTxPowerEnum),
input: createEnumField('WifiTxPowerEnum', WifiTxPowerEnum),
},
{
key: TapInfo.NetworkInfraIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
viewFormatter: (value) => {
if (value === '0.0.0.0') {
return 'Dynamic (DHCP)';
}
return value;
},
},
{
key: TapInfo.NetworkIpMask,
input: {
formValidators: [
regexValidator(IPV4_MASK_PATTERN, `Not a valid IPv4 mask (eg 192.168.20.1)`),
],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.NetworkGatewayIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.NetworkDNSIp,
input: {
formValidators: [IPV4_VALIDATOR],
},
isDisplayed: ({ tapConfigItemStateService }) => {
return combineLatest([
tapConfigItemStateService.valueChange(TapInfo.WifiMode),
tapConfigItemStateService.valueChange(TapInfo.NetworkInfraIp),
]).pipe(map(([mode, ip]) => {
return mode === WifiMode.NETWORK && ip !== '0.0.0.0';
}));
},
},
{
key: TapInfo.WifiMode,
input: createEnumField('WifiMode', WifiMode),
},
{
key: TapInfo.isHostProtocolAuthorized,
input: {
type: 'toggle',
},
getValue: async (tap, protocol) => {
if (protocol === undefined) {
throw new Error('Illegal argument error: missing protocol');
}
const protocols = (await tap.service.interface.getAuthorizedHostProtocol()).body();
return protocols.find((p) => p === protocol) !== undefined;
},
putValue: async (tap, value, protocol) => {
const protocols = (await tap.service.interface.getAuthorizedHostProtocol()).body();
if (protocol === undefined) {
throw new Error('Illegal argument error: missing protocol');
}
const indexOfProtocol = protocols.findIndex((p) => p === protocol);
if (value) {
if (indexOfProtocol === -1) {
protocols.push(protocol);
}
}
else {
if (indexOfProtocol >= 0) {
protocols.splice(indexOfProtocol, 1);
}
}
return tap.service.interface.putAuthorizedHostProtocol(protocols);
},
},
{
key: TapInfo.WifiKey,
input: {
type: 'password',
formValidators: [Validators.minLength(8), Validators.maxLength(128)],
},
},
{
key: TapInfo.variableMetaData,
input: {},
getValue: async (tap, variableId) => {
const metaData = (await tap.service.variable.getRawMeta(variableId)).body();
return converters.ascii.decode(metaData);
},
putValue: (tap, value, bundleId) => {
const data = converters.ascii.encode(value);
return tap.service.variable.putRawMeta(bundleId, data);
},
},
{
key: TapInfo.profilePassword,
input: {
type: 'password',
formValidators: [Validators.minLength(1), Validators.maxLength(16)],
},
viewFormatter: () => {
return '********';
},
putValue: async (tap, value, profileId) => {
await tap.auth.changePassword(value, profileId);
return TapResponse.SUCCESS();
},
},
{
key: TapInfo.DeviceMemoryFree,
viewFormatter(value) {
return Math.floor((value / 1024) * 100) / 100 + ' KB';
},
},
{
key: TapInfo.TimeLocalTime,
viewFormatter(localTime) {
if (!localTime) {
return '';
}
const date = new Date(Date.UTC(localTime.year, 0, localTime.dayOfYear));
date.setHours(localTime.hours);
date.setMinutes(localTime.minutes);
date.setSeconds(localTime.seconds);
// {"seconds":54,"minutes":3,"hours":8,"dayOfMonth":8,"month":8,"year":122,"dayOfWeek":4,"dayOfYear":250,"isdst":0}
return `${date.toUTCString()}`;
},
},
{
key: TapInfo.InterfaceSpecialFeatureSWDDirect,
...createSpecialFeatureDAO(SpecialFeature.SWD_DIRECT_ACCESS),
},
{
key: TapInfo.InterfaceSpecialFeatureSerial,
...createSpecialFeatureDAO(SpecialFeature.SERIAL_ACCESS),
},
{
key: TapInfo.InterfaceSpecialFeatureModbusDirect,
...createSpecialFeatureDAO(SpecialFeature.MODBUS_DIRECT_ACCESS),
},
{
key: '/wifi/enabled',
input: {
type: 'toggle',
},
getValue: async (tap) => {
const response = await tap.service.wifi.getDisabled();
return !response.body();
},
putValue: (tap, enabled) => {
return tap.service.wifi.putDisabled(!enabled);
},
},
];
function createSpecialFeatureDAO(feature) {
return {
input: {
type: 'number',
formValidators: [Validators.min(0), Validators.max(65535)],
},
getValue: async (tap) => {
const result = (await tap.service.interface.getSpecialFeatureProfile(feature)).body();
if (result === 65535 - (feature - 100)) {
return 'UNAUTHORIZED';
}
else {
return result;
}
},
putValue: async (tap, body) => {
return await tap.service.interface.putSpecialFeatureProfile(feature, body);
},
};
}
function createEnumField(enumId, enumData) {
return {
type: 'select',
enum: {
id: enumId,
data: enumData,
},
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL2NvbmZpZy9zcmMvbGliL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdDLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFFLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsaUJBQWlCLEdBQ2xCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNMLDBCQUEwQixFQUUxQixPQUFPLEVBQ1Asa0JBQWtCLEdBQ25CLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxZQUFZLEVBQ1osY0FBYyxFQUVkLFdBQVcsRUFFWCxjQUFjLEdBQ2YsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsY0FBYyxHQUNmLE1BQU0sb0NBQW9DLENBQUM7QUFFNUMsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixRQUFRLEVBQ1Isa0JBQWtCLEdBQ25CLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUUxQyxNQUFNLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO0FBQzVELE1BQU0sWUFBWSxHQUFHLGlDQUFpQyxDQUFDO0FBQ3ZELE1BQU0saUJBQWlCLEdBQUcsaUNBQWlDLENBQUM7QUFDNUQsTUFBTSxZQUFZLEdBQ2hCLHFFQUFxRSxDQUFDO0FBRXhFLFNBQVMsY0FBYyxDQUFDLE9BQWUsRUFBRSxPQUFlO0lBQ3RELE9BQU8sQ0FBQyxPQUF3QixFQUFpQyxFQUFFO1FBQ2pFLE1BQU0s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QUFLLEVBQUUsR0FBUSxFQUFFLElBQVksRUFBRSxFQUFFO1lBQ3pDLE9BQU8sTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FDekQsT0FBTyxFQUNQLElBQUksQ0FDTCxDQUFDO1FBQ0osQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxlQUFlLENBQ3RCLE1BQWMsRUFDZCxRQUFtQjtJQUVuQixPQUFPO1FBQ0wsSUFBSSxFQUFFLFFBQVE7UUFDZCxJQUFJLEVBQUU7WUFDSixFQUFFLEVBQUUsTUFBTTtZQUNWLElBQUksRUFBRSxRQUFRO1NBQ2Y7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgVmFsaWRhdG9yRm4sIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICBidWZmZXJUb0hleFN0cmluZyxcbiAgaGV4U3RyaW5nVG9CdWZmZXIsXG59IGZyb20gJ0Bpb3RpemUvY29tbW9uL2J5dGUtY29udmVydGVyJztcbmltcG9ydCB7XG4gIEZBQ1RPUllfUkVTRVRfTU9ERV9WRVJTSU9OLFxuICBMd20ybUVudW0sXG4gIFRhcEluZm8sXG4gIFRBUF9NQU5BR0VSX0FQUF9JRCxcbn0gZnJvbSAnQGlvdGl6ZS9pb25pYyc7XG5pbXBvcnQge1xuICBIb3N0UHJvdG9jb2wsXG4gIFNwZWNpYWxGZWF0dXJlLFxuICBUYXAsXG4gIFRhcFJlc3BvbnNlLFxuICBUYXBWZXJzaW9uLFxuICBUYXJnZXRQcm90b2NvbCxcbn0gZnJvbSAnQGlvdGl6ZS90YXAnO1xuaW1wb3J0IHsgY29udmVydGVycyB9IGZyb20gJ0Bpb3RpemUvdGFwL3NlcnZpY2UvY29yZSc7XG5pbXBvcnQge1xuICBOZmNDb25uZWN0aW9uUHJpb3JpdHksXG4gIE5mY1BhaXJpbmdNb2RlLFxufSBmcm9tICdAaW90aXplL3RhcC9zZXJ2aWNlL2ltcGwvaW50ZXJmYWNlJztcbmltcG9ydCB7IEFkcFN0YXRzIH0gZnJvbSAnQGlvdGl6ZS90YXAvc2VydmljZS9pbXBsL3RhcG5wYXNzJztcbmltcG9ydCB7XG4gIFdpZmlLZXlWaXNpYmlsaXR5LFxuICBXaWZpTW9kZSxcbiAgV2lmaVNTSURWaXNpYmlsaXR5LFxufSBmcm9tICdAaW90aXplL3RhcC9zZXJ2aWNlL2ltcGwvd2lmaSc7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUYXBDb25maWdJdGVtRXh0ZW5kZWQgfSBmcm9tICcuL3RhcC1jb25maWctaXRlbS90YXAtY29uZmlnLWl0ZW0uZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBlbnVtVG9PcHRpb25zIH0gZnJvbSAnLi91dGlsaXR5JztcblxuY29uc3QgVEFQX0NPTkZJR19QQVRURVJOID0gL14oWzAtOV0rKVxcLihbMC05XSspXFwuKFswLTldKykkLztcbmNvbnN0IElQVjRfUEFUVEVSTiA9IC9eKD86WzAtOV17MSwzfVxcLil7M31bMC05XXsxLDN9JC87XG5jb25zdCBJUFY0X01BU0tfUEFUVEVSTiA9IC9eKD86WzAtOV17MSwzfVxcLil7M31bMC05XXsxLDN9JC87XG5jb25zdCBTU0lEX1BBVFRFUk4gPVxuICAvXlteICEjOytcXF1cXC9cIlxcdF1bXitcXF1cXC9cIlxcdF17MCwzMH1bXiAhIzsrXFxdXFwvXCJcXHRdJHxeW14gISM7K1xcXVxcL1wiXFx0XSQvO1xuXG5mdW5jdGlvbiByZWdleFZhbGlkYXRvcihwYXR0ZXJuOiBSZWdFeHAsIG1lc3NhZ2U6IHN0cmluZyk6IFZhbGlkYXRvckZuIHtcbiAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiB7IFtrZXk6IHN0cmluZ106IGFueSB9IHwgbnVsbCA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSBjb250cm9sLnZhbHVlO1xuICAgIGNvbnN0IHZhbHVlTWF0Y2hQYXR0ZXJuID0gcGF0dGVybi50ZXN0KHZhbHVlKTtcbiAgICByZXR1cm4gIXZhbHVlTWF0Y2hQYXR0ZXJuXG4gICAgICA/IHsgaW52YWxpZEZvcm1hdDogeyB2YWx1ZTogY29udHJvbC52YWx1ZSwgbWVzc2FnZSB9IH1cbiAgICAgIDogbnVsbDtcbiAgfTtcbn1cblxuY29uc3QgdmFsaWRhdGVUYXBWZXJzaW9uOiBWYWxpZGF0b3JGbiA9IHJlZ2V4VmFsaWRhdG9yKFxuICBUQVBfQ09ORklHX1BBVFRFUk4sXG4gIGBNdXN0IGJlIGEgdmFsaWQgc2VtYW50aWMgdmVyc2lvbiAoTWFqb3IuTWlub3IuUGF0Y2gpLmBcbik7XG5cbmZ1bmN0aW9uIGVudW1Gb3JtYXR0ZXIoZGF0YTogYW55KTogKHZhbHVlOiBhbnkpID0+IHN0cmluZyB7XG4gIHJldHVybiAodmFsdWU6IGFueSkgPT4ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgaWYgKHZhbHVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gJy0nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlLm1hcCgoa2V5KSA9PiBIb3N0UHJvdG9jb2xba2V5XSkuam9pbignLCAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRhdGFbdmFsdWVdIGFzIHN0cmluZztcbiAgICB9XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1RhcENvbmZpZ3VyZWQodmVyc2lvbjogVGFwVmVyc2lvbikge1xuICByZXR1cm4gISh2ZXJzaW9uLm1ham9yID09PSAwICYmIHZlcnNpb24ubWlub3IgPT09IDAgJiYgdmVyc2lvbi5wYXRjaCA9PT0gMCk7XG59XG5cbmZ1bmN0aW9uIHN0cmluZ1RvRW51bUFycmF5PFQ+KHY6IHN0cmluZywgbWFwcGluZzogYW55KTogVFtdIHtcbiAgcmV0dXJuIHZcbiAgICAuc3BsaXQoJywnKVxuICAgIC5tYXAoKGl0ZW0pID0+IGl0ZW0udHJpbSgpKVxuICAgIC5tYXAoKGl0ZW0pID0+IHtcbiAgICAgIGlmICghKGl0ZW0gaW4gbWFwcGluZykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBJbnZhbGlkIHZhbHVlIFwiJHtpdGVtfVwiLiBNdXN0IG9uZSBvZiB0aGUgZm9sbG93aW5nOiAke09iamVjdC5rZXlzKFxuICAgICAgICAgICAgbWFwcGluZ1xuICAgICAgICAgICkuam9pbignLCAnKX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbWFwcGluZ1tpdGVtIGFzIGFueV0gYXMgdW5rbm93biBhcyBUO1xuICAgIH0pO1xufVxuXG5lbnVtIFdpZmlUeFBvd2VyRW51bSB7XG4gICdkZWZhdWx0JyA9IDAsXG4gICcxMCBkQm0nID0gNDAsXG4gICcxMi41IGRCbScgPSA1MCxcbiAgJzE1IGRCbScgPSA2MCxcbiAgJzE3LjUgZEJtJyA9IDcwLFxuICAnMjAgZEJtJyA9IDgwLFxufVxuXG5jb25zdCBJUFY0X1ZBTElEQVRPUiA9IHJlZ2V4VmFsaWRhdG9yKFxuICBJUFY0X1BBVFRFUk4sXG4gIGBOb3QgYSB2YWxpZCBJUHY0IGFkZHJlc3MgKGVnIDE5Mi4xNjguMjAuMSlgXG4pO1xuXG5leHBvcnQgY29uc3QgZGVmYXVsdEluZm9SZXNvbHZlckNvbmZpZzogVGFwQ29uZmlnSXRlbUV4dGVuZGVkW10gPSBbXG4gIHtcbiAgICBrZXk6IFRhcEluZm8uSG9zdFByb3RvY29sLFxuICAgIGlucHV0OiBjcmVhdGVFbnVtRmllbGQoJ0hvc3RQcm90b2NvbCcsIEhvc3RQcm90b2NvbCksXG4gICAgdmlld0Zvcm1hdHRlcjogZW51bUZvcm1hdHRlcihIb3N0UHJvdG9jb2wpLFxuICB9LFxuICB7XG4gICAga2V5OiBUYXBJbmZvLmNvbmZpZ1ZlcnNpb24sXG4gICAgaW5wdXQ6IHtcbiAgICAgIGZvcm1WYWxpZGF0b3JzOiBbdmFsaWRhdGVUYXBWZXJzaW9uXSxcbiAgICB9LFxuICAgIHZpZXdGb3JtYXR0ZXI6ICh2OiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICh2ID09PSBGQUNUT1JZX1JFU0VUX01PREVfVkVSU0lPTikge1xuICAgICAgICByZXR1cm4gJ0ZBQ1RPUlkgUkVTRVQnO1xuICAgICAgfSBlbHNlIGlmICh2ID09PSAnMjU1LjI1NS42NTUzNScpIHtcbiAgICAgICAgcmV0dXJuICdDT05GSUdVUkFUSU9OIE1PREUnO1xuICAgICAgfSBlbHNlIGlmICh2KSB7XG4gICAgICAgIHJldHVybiBgdiR7dn1gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuICdVTktOT1dOJztcbiAgICAgIH1cbiAgICB9LFxuICAgIGVkaXRGb3JtYXR0ZXI6IHtcbiAgICAgIHJlYWQ6IChpbnB1dDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgfSxcbiAgICAgIHdyaXRlOiAodjogc3RyaW5nIHwgdW5kZWZpbmVkKSA9PiB7XG4gICAgICAgIHJldHVybiB2IHx8IEZBQ1RPUllfUkVTRVRfTU9ERV9WRVJTSU9OO1xuICAgICAgfSxcbiAgICB9LFxuICB9LFxuICB7XG4gICAga2V5OiBUYXBJbmZvLkNsb3VkRW5kcG9pbnQsXG4gICAgZ2V0VmFsdWU6IGFzeW5jICh0YXApID0+IHtcbiAgICAgIGNvbnN0IGhvc3RuYW1lID0gKGF3YWl0IHRhcC5zZXJ2aWNlLm1xdHQuZ2V0QnJva2VySG9zdG5hbWUoKSkuYm9keSgpO1xuICAgICAgY29uc3QgcG9ydCA9IChhd2FpdCB0YXAuc2VydmljZS5tcXR0LmdldEJyb2tlclBvcnQoKSkuYm9keSgpO1xuICAgICAgcmV0dXJuIGAke2hvc3RuYW1lfToke3BvcnR9YDtcbiAgICB9LFxuICAgIHB1dFZhbHVlOiBhc3luYyAodGFwOiBUYXAsIHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IFtob3N0bmFtZSwgcG9ydF0gPSB2YWx1ZS5zcGxpdCgnOicpO1xuICAgICAgY29uc3Qgc2V0UG9ydCA9IGF3YWl0IHRhcC5zZXJ2aWNlLm1xdHQucHV0QnJva2VyUG9ydChwb3J0IHx8ICcxODgzJyk7XG4gICAgICBzZXRQb3J0LnN1Y2Nlc3NmdWwoKTtcbiAgICAgIHJldHVybiB0YXAuc2VydmljZS5tcXR0LnB1dEJyb2tlckhvc3RuYW1lKGhvc3RuYW1lKTtcbiAgICB9LFxuICB9LFxuICB7XG4gICAga2V5OiBUYXBJbmZvLlRhcmdldFByb3RvY29sQ29uZmlndXJhdGlvbixcbiAgICB2aWV3Rm9ybWF0dGVyOiAodjogVWludDhBcnJheSkgPT4gYCR7YnVmZmVyVG9IZXhTdHJpbmcodil9YCxcbiAgICBlZGl0Rm9ybWF0dGVyOiB7XG4gICAgICByZWFkOiAoaW5wdXQ6IHN0cmluZyk6IFVpbnQ4QXJyYXkgPT4ge1xuICAgICAgICByZXR1cm4gaW5wdXQgPyBoZXhTdHJpbmdUb0J1ZmZlcihpbnB1dCkgOiBuZXcgVWludDhBcnJheSgpO1xuICAgICAgfSxcbiAgICAgIHdyaXRlOiAodjogVWludDhBcnJheSB8IHVuZGVmaW5lZCkgPT4ge1xuICAgICAgICByZXR1cm4gdiA/IGJ1ZmZlclRvSGV4U3RyaW5nKHYpIDo