export default function NaeAuthLoginPage(props: Props) {
  const { lang = 'en' } = props
  const history = useHistory()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const goToSignUp = () => {
    history.push('/register')
  }

  const doLogin = () => {
    NaeApiAuth.doLogin(email, password)
      .then((res) => {
        if (res.isError) {
          alert(res.error.description)
          return
        }
        window.localStorage.setItem('token', res.token)
        history.push('/')
      })
      .catch((e) => alert(e.message))
  }

  return (
    <div className='full-height v-center'>
      <Container className='mt-n20vh'>
        <Row>
          <Col sm={3} />
          <Col>
            <Card>
              <Card.Header>{texts[lang].form}</Card.Header>
              <Card.Body>
                <Form>
                  <Form.Group>
                    <Form.Label>{texts[lang].username}:</Form.Label>

                    <Form.Control
                      value={email}
                      onChange={(e) => setEmail(e.target.value)}


() => {
    history.push('/register')
  }


() => {
    NaeApiAuth.doLogin(email, password)
      .then((res) => {
        if (res.isError) {
          alert(res.error.description)
          return
        }
        window.localStorage.setItem('token', res.token)
        history.push('/')
      })
      .catch((e) => alert(e.message))
  }


(res) => {
        if (res.isError) {
          alert(res.error.description)
          return
        }
        window.localStorage.setItem('token', res.token)
        history.push('/')
      }


(e) => alert(e.message)


interface Props {
  lang?: string
}


/**
 * Given a test function which sets the stage and verifies a dependency scenario
 * between two CloudFormation resources, returns two tests which exercise both
 * "construct dependency" (i.e. node.addDependency) and "resource dependency"
 * (i.e. resource.addDependsOn).
 *
 * @param testFunction The test function
 */
function matrixForResourceDependencyTest(testFunction: (test: Test, addDep: (source: CfnResource, target: CfnResource) => void) => void) {
  return {
    'construct dependency'(test: Test) {
      testFunction(test, (source, target) => source.node.addDependency(target));
    },
    'resource dependency'(test: Test) {
      testFunction(test, (source, target) => source.addDependsOn(target));
    },
  };
}


function assertAssemblyDependency(test: Test, assembly: cxapi.CloudAssembly, stack: Stack, expectedDeps: string[]) {
  const stack1Art = assembly.getStackArtifact(stack.artifactId);
  const stack1Deps = stack1Art.dependencies.map(x => x.id);
  test.deepEqual(stack1Deps, expectedDeps);
}


function assertNoDependsOn(test: Test, assembly: cxapi.CloudAssembly, stack: Stack) {
  let templateText;
  if (!(stack instanceof NestedStack)) {
    templateText = JSON.stringify(assembly.getStackArtifact(stack.artifactId).template);
  } else {
    templateText = fs.readFileSync(path.join(assembly.directory, stack.templateFile), 'utf-8');
  }

  // verify templates do not have any "DependsOn"
  test.ok(!templateText.includes('DependsOn'));
}


(test, addDep) => {
      // GIVEN
      const parent = new Stack(undefined, 'root');
      const nested = new NestedStack(parent, 'Nested');
      const resourceInParent = new CfnResource(parent, 'ResourceInParent', { type: 'PARENT' });
      const resourceInNested = new CfnResource(nested, 'ResourceInNested', { type: 'NESTED' });

      // WHEN
      addDep(resourceInNested, resourceInParent);

      // THEN: the dependency needs to transfer from the resource within the
      // nested stack to the nested stack resource itself so the nested stack
      // will only be deployed the dependent resource
      expect(parent).to(haveResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInParent'] }, ResourcePart.CompleteDefinition));
      expect(nested).toMatch({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource
      test.done();
    }


(test, addDep) => {
      // GIVEN
      const grantparent = new Stack(undefined, 'Grandparent');
      const parent = new NestedStack(grantparent, 'Parent');
      const nested = new NestedStack(parent, 'Nested');
      const resourceInGrandparent = new CfnResource(grantparent, 'ResourceInGrandparent', { type: 'GRANDPARENT' });
      const resourceInNested = new CfnResource(nested, 'ResourceInNested', { type: 'NESTED' });

      // WHEN
      addDep(resourceInNested, resourceInGrandparent);

      // THEN: the dependency needs to transfer from the resource within the
      // nested stack to the *parent* nested stack
      expect(grantparent).to(haveResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInGrandparent'] }, ResourcePart.CompleteDefinition));
      expect(nested).toMatch({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource
      test.done();
    }


(test, addDep) => {
      // GIVEN
      const parent = new Stack(undefined, 'root');
      const nested = new NestedStack(parent, 'Nested');
      const resourceInParent = new CfnResource(parent, 'ResourceInParent', { type: 'PARENT' });
      const resourceInNested = new CfnResource(nested, 'ResourceInNested', { type: 'NESTED' });

      // WHEN
      addDep(resourceInParent, resourceInNested);

      // THEN: resource in parent needs to depend on the nested stack
      expect(parent).to(haveResource('PARENT', {
        DependsOn: [parent.resolve(nested.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));
      test.done();
    }


(test, addDep) => {
      // GIVEN
      const grandparent = new Stack(undefined, 'Grandparent');
      const parent = new NestedStack(grandparent, 'Parent');
      const nested = new NestedStack(parent, 'Nested');
      const resourceInGrandparent = new CfnResource(grandparent, 'ResourceInGrandparent', { type: 'GRANDPARENT' });
      const resourceInNested = new CfnResource(nested, 'ResourceInNested', { type: 'NESTED' });

      // WHEN
      addDep(resourceInGrandparent, resourceInNested);

      // THEN: resource in grantparent needs to depend on the top-level nested stack
      expect(grandparent).to(haveResource('GRANDPARENT', {
        DependsOn: [grandparent.resolve(parent.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));

      test.done();
    }


(test, addDep) => {
      // GIVEN
      const app = new App();
      const stack1 = new Stack(app, 'Stack1');
      const nested1 = new NestedStack(stack1, 'Nested1');
      const resourceInNested1 = new CfnResource(nested1, 'ResourceInNested', { type: 'NESTED' });
      const stack2 = new Stack(app, 'Stack2');
      const resourceInStack2 = new CfnResource(stack2, 'ResourceInSibling', { type: 'SIBLING' });

      // WHEN
      addDep(resourceInStack2, resourceInNested1);

      // THEN: stack2 should depend on stack1 and no "DependsOn" inside templates
      const assembly = app.synth();
      assertAssemblyDependency(test, assembly, stack1, []);
      assertAssemblyDependency(test, assembly, stack2, ['Stack1']);
      assertNoDependsOn(test, assembly, stack1);
      assertNoDependsOn(test, assembly, stack2);
      assertNoDependsOn(test, assembly, nested1);
      test.done();
    }


(test, addDep) => {
      // GIVEN
      const app = new App();
      const stack1 = new Stack(app, 'Stack1');
      const nested1 = new NestedStack(stack1, 'Nested1');
      const resourceInNested1 = new CfnResource(nested1, 'ResourceInNested', { type: 'NESTED' });
      const stack2 = new Stack(app, 'Stack2');
      const resourceInStack2 = new CfnResource(stack2, 'ResourceInSibling', { type: 'SIBLING' });

      // WHEN
      addDep(resourceInNested1, resourceInStack2);

      // THEN: stack1 should depend on stack2 and no "DependsOn" inside templates
      const assembly = app.synth();
      assertAssemblyDependency(test, assembly, stack1, ['Stack2']);
      assertAssemblyDependency(test, assembly, stack2, []);
      assertNoDependsOn(test, assembly, stack1);
      assertNoDependsOn(test, assembly, stack2);
      assertNoDependsOn(test, assembly, nested1);
      test.done();
    }


(test, addDep) => {
      // GIVEN
      const app = new App();
      const stack = new Stack(app, 'Stack1');
      const nested1 = new NestedStack(stack, 'Nested1');
      const nested2 = new NestedStack(stack, 'Nested2');
      const resourceInNested1 = new CfnResource(nested1, 'ResourceInNested1', { type: 'NESTED1' });
      const resourceInNested2 = new CfnResource(nested2, 'ResourceInNested2', { type: 'NESTED2' });

      // WHEN
      addDep(resourceInNested1, resourceInNested2);

      // THEN: dependency transfered to nested stack resources
      expect(stack).to(haveResource('AWS::CloudFormation::Stack', {
        DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));

      expect(stack).notTo(haveResource('AWS::CloudFormation::Stack', {
        DependsOn: [stack.resolve(nested1.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));

      test.done();
    }


() => nested1.addDependency(root)


() => nested2.addDependency(nested1)


() => nested2.addDependency(root)


(source, target) => source.node.addDependency(target)


(source, target) => source.addDependsOn(target)


x => x.id


'between two resources in a top-level stack'(test: Test) {
      // GIVEN
      const app = new App();
      const stack = new Stack(app, 'Stack');
      const r1 = new CfnResource(stack, 'r1', { type: 'r1' });
      const r2 = new CfnResource(stack, 'r2', { type: 'r2' });

      // WHEN
      r1.addDependsOn(r2);

      // THEN
      test.deepEqual(app.synth().getStackArtifact(stack.artifactId).template, {
        Resources:
          { r1: { Type: 'r1', DependsOn: ['r2'] }, r2: { Type: 'r2' } },
      });

      test.done();
    }


'top level stack depends on itself'(test: Test) {
      // GIVEN
      const app = new App();
      const stack = new Stack(app, 'Stack');

      // WHEN
      stack.addDependency(stack);

      // THEN
      const assembly = app.synth();
      assertAssemblyDependency(test, assembly, stack, []);
      assertNoDependsOn(test, assembly, stack);
      test.done();
    }


'nested stack depends on itself'(test: Test) {
      // GIVEN
      const app = new App();
      const parent = new Stack(app, 'Parent');
      const nested = new NestedStack(parent, 'Nested');

      // WHEN
      nested.addDependency(nested);

      // THEN
      assertNoDependsOn(test, app.synth(), parent);
      test.done();
    }


'nested stack cannot depend on any of its parents'(test: Test) {
      // GIVEN
      const root = new Stack();
      const nested1 = new NestedStack(root, 'Nested1');
      const nested2 = new NestedStack(nested1, 'Nested2');

      // THEN
      test.throws(() => nested1.addDependency(root), /Nested stack 'Default\/Nested1' cannot depend on a parent stack 'Default'/);
      test.throws(() => nested2.addDependency(nested1), /Nested stack 'Default\/Nested1\/Nested2' cannot depend on a parent stack 'Default\/Nested1'/);
      test.throws(() => nested2.addDependency(root), /Nested stack 'Default\/Nested1\/Nested2' cannot depend on a parent stack 'Default'/);
      test.done();
    }


'any parent stack is by definition dependent on the nested stack so dependency is ignored'(test: Test) {
      // GIVEN
      const root = new Stack();
      const nested1 = new NestedStack(root, 'Nested1');
      const nested2 = new NestedStack(nested1, 'Nested2');

      // WHEN
      root.addDependency(nested1);
      root.addDependency(nested2);
      nested1.addDependency(nested2);

      // THEN
      test.done();
    }


'sibling nested stacks transfer to resources'(test: Test) {
      // GIVEN
      const stack = new Stack();
      const nested1 = new NestedStack(stack, 'Nested1');
      const nested2 = new NestedStack(stack, 'Nested2');

      // WHEN
      nested1.addDependency(nested2);

      // THEN
      expect(stack).to(haveResource('AWS::CloudFormation::Stack', {
        DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));
      test.done();
    }


'nested stack depends on a deeply nested stack'(test: Test) {
      // GIVEN
      const stack = new Stack();
      const nested1 = new NestedStack(stack, 'Nested1');
      const nested2 = new NestedStack(stack, 'Nested2');
      const nested21 = new NestedStack(nested2, 'Nested21');

      // WHEN
      nested1.addDependency(nested21);

      // THEN: transfered to a resource dep between the resources in the common stack
      expect(stack).to(haveResource('AWS::CloudFormation::Stack', {
        DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));
      test.done();
    }


'deeply nested stack depends on a parent nested stack'(test: Test) {
      // GIVEN
      const stack = new Stack();
      const nested1 = new NestedStack(stack, 'Nested1');
      const nested2 = new NestedStack(stack, 'Nested2');
      const nested21 = new NestedStack(nested2, 'Nested21');

      // WHEN
      nested21.addDependency(nested1);

      // THEN: transfered to a resource dep between the resources in the common stack
      expect(stack).to(haveResource('AWS::CloudFormation::Stack', {
        DependsOn: [stack.resolve(nested1.nestedStackResource!.logicalId)],
      }, ResourcePart.CompleteDefinition));
      test.done();
    }


'top-level stack depends on a nested stack within a sibling'(test: Test) {
      // GIVEN
      const app = new App();
      const stack1 = new Stack(app, 'Stack1');
      const nested1 = new NestedStack(stack1, 'Nested1');
      const stack2 = new Stack(app, 'Stack2');

      // WHEN
      stack2.addDependency(nested1);

      // THEN: assembly-level dependency between stack2 and stack1
      const assembly = app.synth();
      assertAssemblyDependency(test, assembly, stack2, ['Stack1']);
      assertAssemblyDependency(test, assembly, stack1, []);
      assertNoDependsOn(test, assembly, stack1);
      assertNoDependsOn(test, assembly, stack2);
      assertNoDependsOn(test, assembly, nested1);
      test.done();
    }


'nested stack within a sibling depends on top-level stack'(test: Test) {
      // GIVEN
      const app = new App();
      const stack1 = new Stack(app, 'Stack1');
      const nested1 = new NestedStack(stack1, 'Nested1');
      const stack2 = new Stack(app, 'Stack2');

      // WHEN
      nested1.addDependency(stack2);

      // THEN: assembly-level dependency between stack2 and stack1
      const assembly = app.synth();
      assertAssemblyDependency(test, assembly, stack2, []);
      assertAssemblyDependency(test, assembly, stack1, ['Stack2']);
      assertNoDependsOn(test, assembly, stack1);
      assertNoDependsOn(test, assembly, stack2);
      assertNoDependsOn(test, assembly, nested1);
      test.done();
    }


'construct dependency'(test: Test) {
      testFunction(test, (source, target) => source.node.addDependency(target));
    }


'resource dependency'(test: Test) {
      testFunction(test, (source, target) => source.addDependsOn(target));
    }


(p, i) => {
                                return <Table.Row key={`${p.key}-${i}`}>
                                    <Table.Cell>{p.key}</Table.Cell>
                                    <Table.Cell><Ellipsis text={JSON.stringify(p.value)} /> </Table.Cell>
                                </Table.Row>
                            }


k => ({ key: k, value: properties[k] })


p => p.value !== null && p.key !== null


p => p.key !== 'isNormalised'


(a, b) => stringOrder(a.key, b.key)


class PropertiesTable extends React.Component<InnerProps> {

    render() {
        const { items } = this.props
        const totalProperties = items.length

        if (totalProperties === 0) {
            return
No properties

        }

        return (

Key

Value

                    {
                        items
                            .map((p, i) => {
                                return <Table.Row key={`${p.key}-${i}`}>

{p.key}

<Ellipsis text={JSON.stringify(p.value)} />

                            })
                    }

        )
    }
}


export default class PaginatedPropertiesTable extends React.Component<Props> {
    render() {
        const { properties } = this.props

        // Convert to a list, sort and filter
        let items: Property[]

        if (properties != null) {
            items = Object.keys(properties)
                .map(k => ({ key: k, value: properties[k] }))
                .filter(p => p.value !== null && p.key !== null)
                // discard this internal Blaeen thing
                .filter(p => p.key !== 'isNormalised')

            items.sort((a, b) => stringOrder(a.key, b.key))

        } else {
            items = []
        }

        return (
            <Paginated items={items}>
                <PropertiesTable
                    {...this.props}
                    items={[]}
                />
            </Paginated>
        )
    }
}


export type Props = {
    properties: PropertiesMap

}


export type InnerProps = {
    items: Property[]
}


render() {
        const { items } = this.props
        const totalProperties = items.length

        if (totalProperties === 0) {
            return
No properties

        }

        return (

Key

Value

                    {
                        items
                            .map((p, i) => {
                                return <Table.Row key={`${p.key}-${i}`}>

{p.key}

<Ellipsis text={JSON.stringify(p.value)} />

                            })
                    }

        )
    }


render() {
        const { properties } = this.props

        // Convert to a list, sort and filter
        let items: Property[]

        if (properties != null) {
            items = Object.keys(properties)
                .map(k => ({ key: k, value: properties[k] }))
                .filter(p => p.value !== null && p.key !== null)
                // discard this internal Blaeen thing
                .filter(p => p.key !== 'isNormalised')

            items.sort((a, b) => stringOrder(a.key, b.key))

        } else {
            items = []
        }

        return (
            <Paginated items={items}>
                <PropertiesTable
                    {...this.props}
                    items={[]}
                />
            </Paginated>
        )
    }


export function normalizeItems<T, V>(
  tree: T[] = [],
  normalize: Normalizer<T, V> = defaultNormalizer,
  filter: Filter<T, V> = defaultFilter,
  sort?: Sorter<T, V>
) {
  const normalizeItem = (data: T) => {
    const { children, ...norm } = normalize(data)
    const normTree: Normalized<T, V> = { ...norm, data }

    if (children) {
      normTree.children = normalizeItems(children, normalize, filter, sort)
    }

    return normTree
  }

  const normTree = tree.map(normalizeItem).filter(filter)
  return sort ? sortBy(normTree, sort) : normTree
}


export function denormalizeItems<T, V>(tree: Normalized<T, V>[]) {
  return tree.map((item) => item.data)
}


export function listTreeItems<T, V>(
  tree: Normalized<T, V>[]
): Normalized<T, V>[] {
  return tree.flatMap((item) =>
    item.children
      ? [item, ...listTreeItems(item.children)].filter((item) => !item.disabled)
      : item
  )
}


export function labelize<T, V>(
  items: T[] = [],
  normalize: Normalizer<T, V>,
  join: string = ", "
) {
  return items.map((item) => normalize(item).label).join(join)
}


(data: T) => {
    const { children, ...norm } = normalize(data)
    const normTree: Normalized<T, V> = { ...norm, data }

    if (children) {
      normTree.children = normalizeItems(children, normalize, filter, sort)
    }

    return normTree
  }


(item) => item.data


(item) =>
    item.children
      ? [item, ...listTreeItems(item.children)].filter((item) => !item.disabled)
      : item


(item) => !item.disabled


(item) => normalize(item).label


(item) => {
  if (item instanceof Object && "value" in item && "label" in item) {
    return { value: item.value, label: item.label }
  } else {
    return { value: item, label: String(item) }
  }
}


export interface Normalized<T, V> {
  data: T
  value: V
  label: string
  disabled?: boolean
  children?: Normalized<T, V>[]
}


export interface Option<V = string> {
  value: V
  label: string
}


export type Filter<T, V> = (item: Normalized<T, V>) => boolean


export type Sorter<T, V> = (item: Normalized<T, V>) => string | number


export type Normalizer<T, V = T> = (item: T) => {
  value: V
  label: string
  disabled?: boolean
  children?: T[]
}


function LineChart(props: ChartProps) {
  const data = makeDataFromProps(props);
  return <Line data={data} options={options} />;
}


(props: ChartProps) => {
  return canvas => {
    const ctx = canvas.getContext("2d");

    const gradientFill = ctx.createLinearGradient(0, 100, 0, 0);
    gradientFill.addColorStop(0.1, "#fff");
    gradientFill.addColorStop(1, chartColorLight);
    return {
      labels: props.data.map(data => data.label),
      datasets: [
        {
          label: props.unit,
          borderColor: chartColor,
          pointBorderColor: "#FFF",
          pointBackgroundColor: chartColor,
          pointBorderWidth: 2,
          pointHoverRadius: 4,
          pointHoverBorderWidth: 1,
          pointRadius: 4,
          fill: true,
          backgroundColor: gradientFill,
          borderWidth: 2,
          data: props.data.map(data => data.value)
        }
      ]
    };
  };
}


canvas => {
    const ctx = canvas.getContext("2d");

    const gradientFill = ctx.createLinearGradient(0, 100, 0, 0);
    gradientFill.addColorStop(0.1, "#fff");
    gradientFill.addColorStop(1, chartColorLight);
    return {
      labels: props.data.map(data => data.label),
      datasets: [
        {
          label: props.unit,
          borderColor: chartColor,
          pointBorderColor: "#FFF",
          pointBackgroundColor: chartColor,
          pointBorderWidth: 2,
          pointHoverRadius: 4,
          pointHoverBorderWidth: 1,
          pointRadius: 4,
          fill: true,
          backgroundColor: gradientFill,
          borderWidth: 2,
          data: props.data.map(data => data.value)
        }
      ]
    };
  }


data => data.label


data => data.value


@Component({
    selector: 'sc-unsubscribe',
    templateUrl: './unsubscribe.page.html',
    styleUrls: ['./unsubscribe.page.scss'],
})
export class UnsubscribePage implements OnInit {
    valid: boolean = null;
    error: Trx;

    constructor(private activatedRoute: ActivatedRoute, private commsService: CommsService, private authState: AuthState) {
        // If there's no key; prompt for one
        const key = this.activatedRoute.snapshot.params['key'];
        this.unsubscribe(key);
    }

    ngOnInit() {}

    // Unsubscribes the user with a given key
    //
    async unsubscribe(key: string) {
        // Quit if key is null
        if (!key) {
            this.valid = false;
            return;
        }

        // Verify the key with the server
        const resp = await this.commsService.unsubscribe(key);

        // Stop if response is an exception
        if (resp instanceof CustomError) {
            this.error = resp;
            this.valid = false;
            return;
        }

        // Update comms setting state
        if (this.authState.commSettings) {
            this.authState.commSettings = { ...this.authState.commSettings, marketingEmail: false };
        }

        this.valid = true;
    }
}


// Unsubscribes the user with a given key
//
async unsubscribe(key: string) {
        // Quit if key is null
        if (!key) {
            this.valid = false;
            return;
        }

        // Verify the key with the server
        const resp = await this.commsService.unsubscribe(key);

        // Stop if response is an exception
        if (resp instanceof CustomError) {
            this.error = resp;
            this.valid = false;
            return;
        }

        // Update comms setting state
        if (this.authState.commSettings) {
            this.authState.commSettings = { ...this.authState.commSettings, marketingEmail: false };
        }

        this.valid = true;
    }


() => {
  it('create an instance', () => {
    const pipe = new StringReplacePipe();
    expect(pipe).toBeTruthy();
  });
}


() => {
    const pipe = new StringReplacePipe();
    expect(pipe).toBeTruthy();
  }


(req: IncomingMessage, res: ServerResponse, next?: () => void) => {
      const requestHandler = this.server.getRequestHandler();
      return requestHandler(req, res, next);
    }


() => {
      if (listener) {
        listener();
      }

      this.listener(this.app);
    }


resolve =>
      this.app.close(() => {
        resolve();
      })


() => {
        resolve();
      }


p => {
      serverManager.usePlugin(p);
    }


() => {
      ConfigContext.set(this.options.config as UserConfig);
      AppContext.set({
        ...appContext,
        distDirectory: path.join(
          options.pwd,
          options.config.output?.path || 'dist',
        ),
      });
    }


p => ({
      server: p,
      cli: undefined,
    })


export class Server {
  public options: ModernServerOptions;

  private server!: ModernServer | ModernDevServer;

  private app!: httpServer;

  private runner!: ServerHookRunner;

  constructor(options: ModernServerOptions) {
    this.options = options;
  }

  public getRequestHandler() {
    return (req: IncomingMessage, res: ServerResponse, next?: () => void) => {
      const requestHandler = this.server.getRequestHandler();
      return requestHandler(req, res, next);
    };
  }

  public ready(readyOptions: ReadyOptions = {}) {
    this.server.ready(readyOptions);
  }

  public async init() {
    const { options } = this;

    options.logger = options.logger || defaultLogger;
    options.metrics = options.metrics || defaultMetrics;

    // initialize server
    if (options.dev) {
      this.server = this.createDevServer();
    } else {
      this.server = this.createProdServer();
    }
    // check if https is configured when start dev server
    this.app = await this.server.createHTTPServer(this.getRequestHandler());

    this.runner = await this.createHookRunner();

    // runner can only be used after server init
    await this.server.init(this.runner);

    return this;
  }

  public listen(port = 8080, listener: any) {
    this.app.listen(process.env.PORT || port, () => {
      if (listener) {
        listener();
      }

      this.listener(this.app);
    });
  }

  public listener(app: httpServer) {
    this.server.onListening(app);
  }

  public async close() {
    await this.server.close();
    await new Promise<void>(resolve =>
      this.app.close(() => {
        resolve();
      }),
    );
  }

  private createProdServer() {
    const { options } = this;

    if (options.apiOnly) {
      return new ModernAPIServer(options);
    } else if (options.ssrOnly) {
      return new ModernSSRServer(options);
    } else if (options.webOnly) {
      return new ModernWebServer(options);
    } else {
      return new ModernServer(options);
    }
  }

  private createDevServer() {
    const { options } = this;
    const {
      ModernAPIDevServer,
      ModernSSRDevServer,
      ModernDevServer,
    } = require('./dev-server');

    if (options.apiOnly) {
      return new ModernAPIDevServer(options);
    } else if (options.ssrOnly) {
      return new ModernSSRDevServer(options);
    } else {
      return new ModernDevServer(options);
    }
  }

  private async createHookRunner() {
    const { options } = this;

    options.plugins?.forEach(p => {
      serverManager.usePlugin(p);
    });

    const appContext = await this.initAppContext();
    serverManager.run(() => {
      ConfigContext.set(this.options.config as UserConfig);
      AppContext.set({
        ...appContext,
        distDirectory: path.join(
          options.pwd,
          options.config.output?.path || 'dist',
        ),
      });
    });

    return serverManager.init({});
  }

  private async initAppContext() {
    const appDirectory = await initAppDir();

    const loaded = await loadUserConfig(appDirectory);

    const plugins = this.options.plugins?.map(p => ({
      server: p,
      cli: undefined,
    }));

    const appContext = initAppContext(
      appDirectory,
      plugins || [],
      loaded.filePath,
    );
    return appContext;
  }
}


public getRequestHandler() {
    return (req: IncomingMessage, res: ServerResponse, next?: () => void) => {
      const requestHandler = this.server.getRequestHandler();
      return requestHandler(req, res, next);
    };
  }


public ready(readyOptions: ReadyOptions = {}) {
    this.server.ready(readyOptions);
  }


public async init() {
    const { options } = this;

    options.logger = options.logger || defaultLogger;
    options.metrics = options.metrics || defaultMetrics;

    // initialize server
    if (options.dev) {
      this.server = this.createDevServer();
    } else {
      this.server = this.createProdServer();
    }
    // check if https is configured when start dev server
    this.app = await this.server.createHTTPServer(this.getRequestHandler());

    this.runner = await this.createHookRunner();

    // runner can only be used after server init
    await this.server.init(this.runner);

    return this;
  }


public listen(port = 8080, listener: any) {
    this.app.listen(process.env.PORT || port, () => {
      if (listener) {
        listener();
      }

      this.listener(this.app);
    });
  }


public listener(app: httpServer) {
    this.server.onListening(app);
  }


public async close() {
    await this.server.close();
    await new Promise<void>(resolve =>
      this.app.close(() => {
        resolve();
      }),
    );
  }


private createProdServer() {
    const { options } = this;

    if (options.apiOnly) {
      return new ModernAPIServer(options);
    } else if (options.ssrOnly) {
      return new ModernSSRServer(options);
    } else if (options.webOnly) {
      return new ModernWebServer(options);
    } else {
      return new ModernServer(options);
    }
  }


private createDevServer() {
    const { options } = this;
    const {
      ModernAPIDevServer,
      ModernSSRDevServer,
      ModernDevServer,
    } = require('./dev-server');

    if (options.apiOnly) {
      return new ModernAPIDevServer(options);
    } else if (options.ssrOnly) {
      return new ModernSSRDevServer(options);
    } else {
      return new ModernDevServer(options);
    }
  }


private async createHookRunner() {
    const { options } = this;

    options.plugins?.forEach(p => {
      serverManager.usePlugin(p);
    });

    const appContext = await this.initAppContext();
    serverManager.run(() => {
      ConfigContext.set(this.options.config as UserConfig);
      AppContext.set({
        ...appContext,
        distDirectory: path.join(
          options.pwd,
          options.config.output?.path || 'dist',
        ),
      });
    });

    return serverManager.init({});
  }


private async initAppContext() {
    const appDirectory = await initAppDir();

    const loaded = await loadUserConfig(appDirectory);

    const plugins = this.options.plugins?.map(p => ({
      server: p,
      cli: undefined,
    }));

    const appContext = initAppContext(
      appDirectory,
      plugins || [],
      loaded.filePath,
    );
    return appContext;
  }


() => {
  let component: AddEditTopicComponent;
  let fixture: ComponentFixture<AddEditTopicComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AddEditTopicComponent],
      imports: [FormsModule],
      providers: [{ provide: DialogService }, { provide: UserService }]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AddEditTopicComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
}


() => {
    TestBed.configureTestingModule({
      declarations: [AddEditTopicComponent],
      imports: [FormsModule],
      providers: [{ provide: DialogService }, { provide: UserService }]
    }).compileComponents();
  }


() => {
    fixture = TestBed.createComponent(AddEditTopicComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }


({ collectionName, classes }: HeaderProps) => {
  const history = useHistory();
  return (
    <Box mt="50px">
      <Grid container alignItems="center" spacing={1}>
        <Grid item>
          <Button onClick={() => history.goBack()}>
            <ArrowBackIcon color="primary" />
          </Button>
        </Grid>
        <Grid item>
          <Typography className={classes.name} color="textSecondary">
            {collectionName}
          </Typography>
        </Grid>
        {/* TODO: Add collection name edit functionality */}
        {/* <Grid item>
          <IconButton>
            <EditIcon fontSize="small" color="primary" />
          </IconButton>
        </Grid> */}
      </Grid>
    </Box>


() => history.goBack()


() =>
  createStyles({
    name: {
      fontSize: 24,
    },
  })


interface HeaderIncomingProps {
  collectionName: string;
}


type HeaderProps = HeaderIncomingProps & WithStyles<typeof styles>;


export interface BackendTimingInfo {
    kernelMs: number;
}


export interface TensorStorage {
    read(dataId: DataId): Promise<TypedArray>;
    readSync(dataId: DataId): TypedArray;
    disposeData(dataId: DataId): void;
    write(dataId: DataId, values: TypedArray): void;
    fromPixels(pixels: ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, numChannels: number): Tensor3D;
    register(dataId: DataId, shape: number[], dtype: DataType): void;
    memory(): {
        unreliable: boolean;
    };
}


export interface BackendTimer {
    time(f: () => void): Promise<BackendTimingInfo>;
}


export interface KernelBackend extends TensorStorage, BackendTimer {
    matMul(a: Tensor2D, b: Tensor2D, transposeA: boolean, transposeB: boolean): Tensor2D;
    slice<T extends Tensor>(x: T, begin: number[], size: number[]): T;
    stridedSlice<T extends Tensor>(x: T, begin: number[], end: number[], strides: number[], beginMask: number, endMask: number): T;
    reverse<T extends Tensor>(a: T, axis: number[]): T;
    concat(a: Tensor2D, b: Tensor2D): Tensor2D;
    neg<T extends Tensor>(a: T): T;
    add(a: Tensor, b: Tensor): Tensor;
    subtract(a: Tensor, b: Tensor): Tensor;
    multiply(a: Tensor, b: Tensor): Tensor;
    realDivide(a: Tensor, b: Tensor): Tensor;
    floorDiv(a: Tensor, b: Tensor): Tensor;
    sum(x: Tensor, axes: number[]): Tensor;
    argMin(x: Tensor, axis: number): Tensor;
    argMax(x: Tensor, axis: number): Tensor;
    equal(a: Tensor, b: Tensor): Tensor;
    notEqual(a: Tensor, b: Tensor): Tensor;
    less(a: Tensor, b: Tensor): Tensor;
    lessEqual(a: Tensor, b: Tensor): Tensor;
    greater(a: Tensor, b: Tensor): Tensor;
    greaterEqual(a: Tensor, b: Tensor): Tensor;
    logicalNot<T extends Tensor>(a: T): T;
    logicalAnd(a: Tensor, b: Tensor): Tensor;
    logicalOr(a: Tensor, b: Tensor): Tensor;
    where(condition: Tensor, a: Tensor, b: Tensor, dtype: DataType): Tensor;
    topKValues<T extends Tensor>(x: T, k: number): Tensor1D;
    topKIndices(x: Tensor, k: number): Tensor1D;
    min(x: Tensor, axes: number[]): Tensor;
    minimum(a: Tensor, b: Tensor): Tensor;
    mod(a: Tensor, b: Tensor): Tensor;
    max(x: Tensor, axes: number[]): Tensor;
    maximum(a: Tensor, b: Tensor): Tensor;
    squaredDifference(a: Tensor, b: Tensor): Tensor;
    ceil<T extends Tensor>(x: T): T;
    floor<T extends Tensor>(x: T): T;
    round<T extends Tensor>(x: T): T;
    sign<T extends Tensor>(x: T): T;
    pow<T extends Tensor>(a: T, b: Tensor): T;
    exp<T extends Tensor>(x: T): T;
    expm1<T extends Tensor>(x: T): T;
    log<T extends Tensor>(x: T): T;
    log1p<T extends Tensor>(x: T): T;
    sqrt<T extends Tensor>(x: T): T;
    rsqrt<T extends Tensor>(x: T): T;
    square<T extends Tensor>(x: T): T;
    reciprocal<T extends Tensor>(x: T): T;
    relu<T extends Tensor>(x: T): T;
    elu<T extends Tensor>(x: T): T;
    eluDer<T extends Tensor>(dy: T, y: T): T;
    selu<T extends Tensor>(x: T): T;
    int<T extends Tensor>(x: T): T;
    clip<T extends Tensor>(x: T, min: number, max: number): T;
    abs<T extends Tensor>(x: T): T;
    sigmoid<T extends Tensor>(x: T): T;
    softplus<T extends Tensor>(x: T): T;
    sin<T extends Tensor>(x: T): T;
    cos<T extends Tensor>(x: T): T;
    tan<T extends Tensor>(x: T): T;
    asin<T extends Tensor>(x: T): T;
    acos<T extends Tensor>(x: T): T;
    atan<T extends Tensor>(x: T): T;
    atan2<T extends Tensor>(a: T, b: T): T;
    sinh<T extends Tensor>(x: T): T;
    cosh<T extends Tensor>(x: T): T;
    tanh<T extends Tensor>(x: T): T;
    asinh<T extends Tensor>(x: T): T;
    acosh<T extends Tensor>(x: T): T;
    atanh<T extends Tensor>(x: T): T;
    erf<T extends Tensor>(x: T): T;
    step<T extends Tensor>(x: T, alpha: number): T;
    conv2d(x: Tensor4D, filter: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    conv2dDerInput(dy: Tensor4D, filter: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    conv2dDerFilter(x: Tensor4D, dY: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    depthwiseConv2D(input: Tensor4D, filter: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    depthwiseConv2DDerInput(dy: Tensor4D, filter: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    depthwiseConv2DDerFilter(x: Tensor4D, dY: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    maxPool(x: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    maxPoolBackprop(dy: Tensor4D, x: Tensor4D, y: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    avgPool(x: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    avgPoolBackprop(dy: Tensor4D, x: Tensor4D, convInfo: Conv2DInfo): Tensor4D;
    reshape<T extends Tensor, R extends Rank>(x: T, shape: ShapeMap[R]): Tensor<R>;
    cast<T extends Tensor>(x: T, dtype: DataType): T;
    tile<T extends Tensor>(x: T, reps: number[]): T;
    pad<T extends Tensor>(x: T, paddings: Array<[number, number]>, constantValue: number): T;
    transpose<T extends Tensor>(x: T, perm: number[]): T;
    gather<T extends Tensor>(x: T, indices: Tensor1D, axis: number): T;
    resizeBilinear(x: Tensor4D, newHeight: number, newWidth: number, alignCorners: boolean): Tensor4D;
    resizeBilinearBackprop(dy: Tensor4D, x: Tensor4D, alignCorners: boolean): Tensor4D;
    resizeNearestNeighbor(x: Tensor4D, newHEight: number, newWidth: number, alignCorners: boolean): Tensor4D;
    batchNormalization(x: Tensor4D, mean: Tensor4D | Tensor1D, variance: Tensor4D | Tensor1D, varianceEpsilon: number, scale?: Tensor4D | Tensor1D, offset?: Tensor4D | Tensor1D): Tensor4D;
    localResponseNormalization4D(x: Tensor4D, radius: number, bias: number, alpha: number, beta: number): Tensor4D;
    multinomial(logits: Tensor2D, normalized: boolean, numSamples: number, seed: number): Tensor2D;
    oneHot(indices: Tensor1D, depth: number, onValue: number, offValue: number): Tensor2D;
    cumsum(x: Tensor, axis: number, exclusive: boolean, reverse: boolean): Tensor;
    dispose(): void;
}


export function MyPlants() {
  const [myPlants, setMyPlants] = useState<PlantProps[]>([])
  const [loading, setLoading] = useState(true)
  const [nextWatered, setNextWatered] = useState<string>()

  useEffect(() => {
    async function loadStorageData() {
      const plantsStoraged = await loadPlant()

      const nextTime = formatDistance(
        new Date(plantsStoraged[0].dateTimeNotification).getTime(),
        new Date().getTime(),
        { locale: pt }
      )

      setNextWatered(
        `Não esqueça de regar a ${plantsStoraged[0].name} daqui a ${nextTime}`
      )

      setMyPlants(plantsStoraged)
      setLoading(false)
    }

    loadStorageData()
  }, [myPlants])

  function handleRemove(plant: PlantProps) {
    Alert.alert('Remover', `Deseja remover a ${plant.name}?`, [
      {
        text: 'Não 🙏',
        style: 'cancel'
      },
      {
        text: 'Sim 😥',
        onPress: async () => {
          try {
            await removePlant(plant.id)

            setMyPlants((oldData) =>
              oldData.filter((item) => item.id !== plant.id)
            )

          } catch (error) {
            Alert.alert('Não foi possível remover! 😥')
          }
        }
      }
    ])
  }

  if (loading)
    return <Load />

  return (
    <SafeAreaView style={styles.container}>
      <Header />

      <View style={styles.spotlight}>
        <Image
          source={waterdrop}
          style={styles.spotlightImage}
        />
        <Text style={styles.spotlightText}>
          {nextWatered}
        </Text>
      </View>

      <View style={styles.plants}>
        <Text style={styles.plantsTitle}>
          Próximas regadas
          </Text>

        <FlatList
          data={myPlants}
          keyExtractor={(item) => String(item.id)}


async function loadStorageData() {
      const plantsStoraged = await loadPlant()

      const nextTime = formatDistance(
        new Date(plantsStoraged[0].dateTimeNotification).getTime(),
        new Date().getTime(),
        { locale: pt }
      )

      setNextWatered(
        `Não esqueça de regar a ${plantsStoraged[0].name} daqui a ${nextTime}`
      )

      setMyPlants(plantsStoraged)
      setLoading(false)
    }


function handleRemove(plant: PlantProps) {
    Alert.alert('Remover', `Deseja remover a ${plant.name}?`, [
      {
        text: 'Não 🙏',
        style: 'cancel'
      },
      {
        text: 'Sim 😥',
        onPress: async () => {
          try {
            await removePlant(plant.id)

            setMyPlants((oldData) =>
              oldData.filter((item) => item.id !== plant.id)
            )

          } catch (error) {
            Alert.alert('Não foi possível remover! 😥')
          }
        }
      }
    ])
  }


() => {
    async function loadStorageData() {
      const plantsStoraged = await loadPlant()

      const nextTime = formatDistance(
        new Date(plantsStoraged[0].dateTimeNotification).getTime(),
        new Date().getTime(),
        { locale: pt }
      )

      setNextWatered(
        `Não esqueça de regar a ${plantsStoraged[0].name} daqui a ${nextTime}`
      )

      setMyPlants(plantsStoraged)
      setLoading(false)
    }

    loadStorageData()
  }


async () => {
          try {
            await removePlant(plant.id)

            setMyPlants((oldData) =>
              oldData.filter((item) => item.id !== plant.id)
            )

          } catch (error) {
            Alert.alert('Não foi possível remover! 😥')
          }
        }


(oldData) =>
              oldData.filter((item) => item.id !== plant.id)


(item) => item.id !== plant.id


(file: UploadFile) => {
    this.previewImage = file.url || file.thumbUrl;
    this.previewVisible = true;
  }


(res:any)=>{
      console.log(JSON.stringify(res))
    }


(item: UploadXHRArgs) => {
    alert(JSON.stringify(item))
    // 构建一个 FormData 对象，用于存储文件或其他参数
    const formData = new FormData();
    // tslint:disable-next-line:no-any
    formData.append('file', item.file as any);
    formData.append('id', '1000');
    formData.append('key', item.name);
    formData.append('token', item.name);
    const req = new HttpRequest('POST', item.action, formData, {
      reportProgress: true,
      withCredentials: true
    });
    this.https.request(req).subscribe(()=>{

    })
  }


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

  constructor(
    private fb: FormBuilder,
    private http: _HttpClient,
    public msg: NzMessageService,
    private modalSrv: NzModalService,
    private _message: NzMessageService,
    private router: Router,
    private https:HttpClient,
  ) {
  }

  form: FormGroup;
  forms: FormGroup;

  selectedValue = 0;

  selectData: any[] = [];

  controlArray: Array<{ id: number, controlInstance: string }> = [];
  comments = [];
  images = [];
  loading = false;

  indexData = 'asdasdasdsdasd';

  ngOnInit(): void {

      this.form = this.fb.group({
      content: [null, [Validators.required]],
      title: [null, [Validators.required]],
      sendTime: [null, [Validators.required]],
      device: [null, [Validators.required]],
      time: [null, [Validators.required]],
      comment: [this.comments],
      image: [],
    });

    this.controlArray[0] = {
      id: 0,
      controlInstance: 'passenger0',
    };

    this.form.addControl(this.controlArray[0].controlInstance, new FormControl(this.indexData, Validators.required));
  }

  submit() {
    for (let i = 0; i < this.controlArray.length; i++) {
      let a = this.controlArray[i].controlInstance;
      let b = this.form.value[a];
      this.comments.push(b);
    }

    for (let j = 0; j < this.fileList.length; j++) {
      this.images.push(this.fileList[j].url);
    }

    console.log(this.form.value);
  }

  addField(e?: MouseEvent): void {
    if (e) {
      e.preventDefault();
    }
    const id = (this.controlArray.length > 0) ? this.controlArray[this.controlArray.length - 1].id + 1 : 0;

    const control = {
      id,
      controlInstance: `passenger${id}`,
    };
    const index = this.controlArray.push(control);
    console.log(this.controlArray[this.controlArray.length - 1]);
    this.form.addControl(this.controlArray[index - 1].controlInstance, new FormControl(null, Validators.required));
  }

  removeField(i: { id: number, controlInstance: string }, e: MouseEvent): void {
    e.preventDefault();
    if (this.controlArray.length > 1) {
      const index = this.controlArray.indexOf(i);
      this.controlArray.splice(index, 1);
      this.form.removeControl(i.controlInstance);
    }
  }

  fileList = [
    {
      uid:1,
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
    {
      uid:2,
      url: 'http://www.baidu.com/yyy.png',
    },{
      uid:3,
    url: 'http://img5.imgtn.bdimg.com/it/u=1486955621,651015270&fm=26&gp=0.jpg',
    },
  ];
  previewImage = '';
  previewVisible = false;

  handlePreview = (file: UploadFile) => {
    this.previewImage = file.url || file.thumbUrl;
    this.previewVisible = true;
  };

  a(file: UploadFile){
    alert(JSON.stringify(file))
  }

  onOk(result: Date): void {
    this.form.value.sendTime = result;
  }

  checkOptionsOne = [];
  device=[];

  log(value: object[]): void {
    this.device=[];
    for (let y=0;y<value.length;y++){
      if (value[y]['checked']){
        this.device.push(value[y]['label'])
      }
    }
    console.log(this.device);
  }

  //输入地址获取图片
  onBlur(){
    this.http.get("http://www.taotongxue.cn/mobile/taobao/getPic?itemId="+this.form.value.content).subscribe((res:any)=>{
      console.log(JSON.stringify(res))
    })
  }

  //获取商品id
  onChange(){
    this.http.post(BaseConfig.host+"/back/sns/regex",null,{"regexText": this.form.value.content}).subscribe((res:any)=>{
      console.log(JSON.stringify(res))
    })
  }

  customReq = (item: UploadXHRArgs) => {
    alert(JSON.stringify(item))
    // 构建一个 FormData 对象，用于存储文件或其他参数
    const formData = new FormData();
    // tslint:disable-next-line:no-any
    formData.append('file', item.file as any);
    formData.append('id', '1000');
    formData.append('key', item.name);
    formData.append('token', item.name);
    const req = new HttpRequest('POST', item.action, formData, {
      reportProgress: true,
      withCredentials: true
    });
    this.https.request(req).subscribe(()=>{

    })
  }

  del(item:any){
    for (let i=0;i<this.fileList.length;i++){
      if (this.fileList[i].uid==item.uid){
        this.fileList.splice(i,1);
      }
    }
  }

}


ngOnInit(): void {

      this.form = this.fb.group({
      content: [null, [Validators.required]],
      title: [null, [Validators.required]],
      sendTime: [null, [Validators.required]],
      device: [null, [Validators.required]],
      time: [null, [Validators.required]],
      comment: [this.comments],
      image: [],
    });

    this.controlArray[0] = {
      id: 0,
      controlInstance: 'passenger0',
    };

    this.form.addControl(this.controlArray[0].controlInstance, new FormControl(this.indexData, Validators.required));
  }


submit() {
    for (let i = 0; i < this.controlArray.length; i++) {
      let a = this.controlArray[i].controlInstance;
      let b = this.form.value[a];
      this.comments.push(b);
    }

    for (let j = 0; j < this.fileList.length; j++) {
      this.images.push(this.fileList[j].url);
    }

    console.log(this.form.value);
  }


addField(e?: MouseEvent): void {
    if (e) {
      e.preventDefault();
    }
    const id = (this.controlArray.length > 0) ? this.controlArray[this.controlArray.length - 1].id + 1 : 0;

    const control = {
      id,
      controlInstance: `passenger${id}`,
    };
    const index = this.controlArray.push(control);
    console.log(this.controlArray[this.controlArray.length - 1]);
    this.form.addControl(this.controlArray[index - 1].controlInstance, new FormControl(null, Validators.required));
  }


removeField(i: { id: number, controlInstance: string }, e: MouseEvent): void {
    e.preventDefault();
    if (this.controlArray.length > 1) {
      const index = this.controlArray.indexOf(i);
      this.controlArray.splice(index, 1);
      this.form.removeControl(i.controlInstance);
    }
  }


a(file: UploadFile){
    alert(JSON.stringify(file))
  }


onOk(result: Date): void {
    this.form.value.sendTime = result;
  }


log(value: object[]): void {
    this.device=[];
    for (let y=0;y<value.length;y++){
      if (value[y]['checked']){
        this.device.push(value[y]['label'])
      }
    }
    console.log(this.device);
  }


//输入地址获取图片
onBlur(){
    this.http.get("http://www.taotongxue.cn/mobile/taobao/getPic?itemId="+this.form.value.content).subscribe((res:any)=>{
      console.log(JSON.stringify(res))
    })
  }


//获取商品id
onChange(){
    this.http.post(BaseConfig.host+"/back/sns/regex",null,{"regexText": this.form.value.content}).subscribe((res:any)=>{
      console.log(JSON.stringify(res))
    })
  }


del(item:any){
    for (let i=0;i<this.fileList.length;i++){
      if (this.fileList[i].uid==item.uid){
        this.fileList.splice(i,1);
      }
    }
  }


async () => {
    testRepository.addEntry(Id.chootleBotGroup("10"), Id.discordGroup("100"));

    const { internalId: domainId, err: error } =
      testRepository.getDomainGroup(Id.discordGroup("100"));

    expect(error).toBe(undefined);
    expect(domainId).toEqual(Id.chootleBotGroup("10"));
  }


async () => {
    testRepository.addEntry(Id.chootleBotGroup("10"), Id.discordGroup("100"));

    const { externalId: domainId, err: error } =
      testRepository.getExternalGroup(Id.chootleBotGroup("10"));

    expect(error).toBe(undefined);
    expect(domainId).toEqual(Id.discordGroup("100"));
  }


@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    CartPageRoutingModule,
  ],
  declarations: [CartPage]
})
export class CartPageModule { }


<T = any, R = T, V = object>(
  args: UseSubscriptionArgs<V>,
  handler?: SubscriptionHandler<T, R>
): UseSubscriptionResponse<R> => {
  const client = useClient();

  // Update handler on constant ref, since handler changes shouldn't
  // trigger a new subscription run
  const handlerRef = useRef(handler);
  handlerRef.current = handler;

  // This creates a request which will keep a stable reference
  // if request.key doesn't change
  const request = useRequest(args.query, args.variables);

  // Create a new subscription-source from client.executeSubscription
  const makeSubscription$ = useCallback(
    (opts?: Partial<OperationContext>) => {
      return client.executeSubscription(request, { ...args.context, ...opts });
    },
    [client, request, args.context]
  );

  const [state, update] = useSubjectValue(
    subscription$$ =>
      pipe(
        subscription$$,
        switchMap(subscription$ => {
          if (!subscription$) return fromValue({ fetching: false });

          return concat([
            // Initially set fetching to true
            fromValue({ fetching: true }),
            pipe(
              subscription$,
              map(({ stale, data, error, extensions }) => ({
                fetching: true,
                stale: !!stale,
                data,
                error,
                extensions,
              }))
            ),
            // When the source proactively closes, fetching is set to false
            fromValue({ fetching: false }),
          ]);
        }),
        // The individual partial results are merged into each previous result
        scan((result, partial: any) => {
          const { current: handler } = handlerRef;
          // If a handler has been passed, it's used to merge new data in
          const data =
            partial.data !== undefined
              ? typeof handler === 'function'
                ? handler(result.data, partial.data)
                : partial.data
              : result.data;
          return { ...result, stale: false, ...partial, data };
        }, initialState)
      ),
    useMemo(() => (args.pause ? null : makeSubscription$()), [
      args.pause,
      makeSubscription$,
    ]),
    initialState
  );

  // This is the imperative execute function passed to the user
  const executeSubscription = useCallback(
    (opts?: Partial<OperationContext>) => update(makeSubscription$(opts)),
    [update, makeSubscription$]
  );

  return [state, executeSubscription];
}


(opts?: Partial<OperationContext>) => {
      return client.executeSubscription(request, { ...args.context, ...opts });
    }


subscription$$ =>
      pipe(
        subscription$$,
        switchMap(subscription$ => {
          if (!subscription$) return fromValue({ fetching: false });

          return concat([
            // Initially set fetching to true
            fromValue({ fetching: true }),
            pipe(
              subscription$,
              map(({ stale, data, error, extensions }) => ({
                fetching: true,
                stale: !!stale,
                data,
                error,
                extensions,
              }))
            ),
            // When the source proactively closes, fetching is set to false
            fromValue({ fetching: false }),
          ]);
        }),
        // The individual partial results are merged into each previous result
        scan((result, partial: any) => {
          const { current: handler } = handlerRef;
          // If a handler has been passed, it's used to merge new data in
          const data =
            partial.data !== undefined
              ? typeof handler === 'function'
                ? handler(result.data, partial.data)
                : partial.data
              : result.data;
          return { ...result, stale: false, ...partial, data };
        }, initialState)
      )


subscription$ => {
          if (!subscription$) return fromValue({ fetching: false });

          return concat([
            // Initially set fetching to true
            fromValue({ fetching: true }),
            pipe(
              subscription$,
              map(({ stale, data, error, extensions }) => ({
                fetching: true,
                stale: !!stale,
                data,
                error,
                extensions,
              }))
            ),
            // When the source proactively closes, fetching is set to false
            fromValue({ fetching: false }),
          ]);
        }


({ stale, data, error, extensions }) => ({
                fetching: true,
                stale: !!stale,
                data,
                error,
                extensions,
              })


(result, partial: any) => {
          const { current: handler } = handlerRef;
          // If a handler has been passed, it's used to merge new data in
          const data =
            partial.data !== undefined
              ? typeof handler === 'function'
                ? handler(result.data, partial.data)
                : partial.data
              : result.data;
          return { ...result, stale: false, ...partial, data };
        }


() => (args.pause ? null : makeSubscription$())


(opts?: Partial<OperationContext>) => update(makeSubscription$(opts))


export interface UseSubscriptionArgs<V> {
  query: DocumentNode | string;
  variables?: V;
  pause?: boolean;
  context?: Partial<OperationContext>;
}


export interface UseSubscriptionState<T> {
  fetching: boolean;
  stale: boolean;
  data?: T;
  error?: CombinedError;
  extensions?: Record<string, any>;
}


export type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;


export type UseSubscriptionResponse<T> = [
  UseSubscriptionState<T>,
  (opts?: Partial<OperationContext>) => void
];


() => {
      const index = this._fns.findIndex((v) => v === fn);

      if (index > -1) {
        this._fns.splice(index, 1);
      }
    }


(v) => v === fn


() => {
      const successIndex = this._fnsSuccess.findIndex((v) => v === successFn);
      const errorIndex = this._fnsError.findIndex((v) => v === errorFn);

      if (successIndex > -1) {
        this._fnsSuccess.splice(successIndex, 1);
      }

      if (errorIndex > -1) {
        this._fnsError.splice(errorIndex, 1);
      }
    }


(v) => v === successFn


(v) => v === errorFn


(url: string, config?: IRuntimeRequestCommonOptions = {}) => {
        return this.request({
          method: method.toUpperCase(),
          url,
          ...config,
        });
      }


(resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new RuntimeError(`timeout of ${ms}ms`));
      }, ms);

      promise
        .then((value) => {
          clearTimeout(timer);
          resolve(value);
        })
        .catch((reason) => {
          clearTimeout(timer);
          reject(reason);
        });
    }


() => {
        reject(new RuntimeError(`timeout of ${ms}ms`));
      }


(value) => {
          clearTimeout(timer);
          resolve(value);
        }


(reason) => {
          clearTimeout(timer);
          reject(reason);
        }


() =>
      fetch(url.toString(), {
        method: config.method,
        body: body,
        headers: headers,

        // common options
        cache: config.cache,
        credentials: config.credentials,
        integrity: config.integrity,
        keepalive: config.keepalive,
        mode: config.mode,
        redirect: config.redirect,
        referrer: config.referrer,
        referrerPolicy: config.referrerPolicy,
        signal: config.signal,
        window: config.window,
      })


async (resp) => {
        if (!resp.ok) return Promise.reject(RuntimeError.fromResponse(resp));
        const contentType = resp.headers.get("content-type");
        switch (contentType) {
          case "application/json":
            return { data: await resp.json(), resp };
          case "application/x-www-form-urlencoded":
            return { data: await resp.formData(), resp };
          case "application/octet-stream":
            return { data: await resp.blob(), resp };
          default:
            return { data: await resp.text(), resp };
        }
      }


({ data, resp }) => {
        return this._responseInterceptor.runSuccess<T>(config, resp, data);
      }


(err) => {
        const runtimeErr = err instanceof RuntimeError ? err : err instanceof Error ? RuntimeError.fromError(err) : new RuntimeError(err + "");

        return this._responseInterceptor.runError<T>(config, runtimeErr);
      }


class RequestInterceptor implements IRequestInterceptor {
  private _fns: IRequestInterceptorFn[] = [];
  public use(fn: IRequestInterceptorFn) {
    this._fns.push(fn);

    return () => {
      const index = this._fns.findIndex((v) => v === fn);

      if (index > -1) {
        this._fns.splice(index, 1);
      }
    };
  }

  async run(config: IRuntimeRequestOptions): Promise<IRuntimeRequestOptions> {
    for (const fn of this._fns) {
      config = await fn(config);
    }

    return config;
  }
}


class ResponseInterceptor implements IResponseInterceptor {
  private _fnsSuccess: IResponseInterceptorSuccessFn<any>[] = [];
  private _fnsError: IResponseInterceptorErrorFn<any>[] = [];
  public use(successFn: IResponseInterceptorSuccessFn<any>, errorFn: IResponseInterceptorErrorFn<any>) {
    this._fnsSuccess.push(successFn);
    this._fnsError.push(errorFn);

    return () => {
      const successIndex = this._fnsSuccess.findIndex((v) => v === successFn);
      const errorIndex = this._fnsError.findIndex((v) => v === errorFn);

      if (successIndex > -1) {
        this._fnsSuccess.splice(successIndex, 1);
      }

      if (errorIndex > -1) {
        this._fnsError.splice(errorIndex, 1);
      }
    };
  }

  async runSuccess<T>(config: IRuntimeRequestOptions, response: Response, data: T): Promise<T> {
    for (const fn of this._fnsSuccess) {
      data = await fn(config, response, data);
    }

    return data;
  }

  async runError<T>(config: IRuntimeRequestOptions, err: RuntimeError): Promise<T> {
    let res!: T;

    for (const fn of this._fnsError) {
      res = await fn(config, err);
    }

    return res;
  }
}


export class RuntimeForm<T extends IRuntimeForm> {
  constructor(private _form: T) {}
  public formData(): FormData {
    const form = new FormData();

    for (const key in this._form) {
      if (this._form[key] !== undefined) {
        form.append(key, this._form[key]);
      }
    }

    return form;
  }
}


export class RuntimeError extends Error {
  constructor(message: string, private _resp?: Response) {
    super(message);
  }

  public get response(): Response | undefined {
    return this._resp;
  }

  static fromResponse(resp: Response) {
    return new RuntimeError(resp.statusText, resp);
  }

  static fromError(err: Error) {
    return new RuntimeError(err.message || "unknown error: " + err);
  }
}


export class Runtime implements IRuntime {
  constructor(private _domain: string, private _prefix: string) {
    const methods = ["get", "post", "delete", "put", "head", "options", "trace", "patch"];

    for (const method of methods) {
      // @ts-ignore ignore error
      this[method] = (url: string, config?: IRuntimeRequestCommonOptions = {}) => {
        return this.request({
          method: method.toUpperCase(),
          url,
          ...config,
        });
      };
    }
  }

  private _requestInterceptor = new RequestInterceptor();
  private _responseInterceptor = new ResponseInterceptor();

  private _defaults = {
    timeout: 60 * 1000, // 60s,
    headers: {
      common: {
        "Content-Type": "application/json",
      },
    } as IRuntimeHeaderConfig,
  };

  public get interceptors() {
    const self = this;
    return {
      get request() {
        return self._requestInterceptor as IRequestInterceptor;
      },
      get response() {
        return self._responseInterceptor as IResponseInterceptor;
      },
    };
  }

  public get defaults() {
    return this._defaults;
  }

  private _timeout<T>(ms: number, promise: Promise<T>) {
    return new Promise<T>((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new RuntimeError(`timeout of ${ms}ms`));
      }, ms);

      promise
        .then((value) => {
          clearTimeout(timer);
          resolve(value);
        })
        .catch((reason) => {
          clearTimeout(timer);
          reject(reason);
        });
    });
  }

  public get baseURL(): string {
    const baseUrl = this._domain.replace(/\/$/, "") + (!/^\//.test(this._prefix) ? "/" : "") + this._prefix;

    return baseUrl.replace(/\/$/, "");
  }

  public set domain(domain: string) {
    this._domain = domain;
  }

  public set prefix(prefix: string) {
    this._prefix = prefix;
  }

  public async request<T>(config: IRuntimeRequestOptions): Promise<T> {
    const url = new URL(this.baseURL + config.url);
    config.header = config.header || {};

    const defaults = this.defaults;

    // set default header
    for (const key in defaults.headers.common) {
      config.header[key] = defaults.headers.common[key];
    }

    // set header for this method
    for (const key in defaults.headers[config.method] || {}) {
      config.header[key] = defaults.headers[config.method][key];
    }

    if (config.query) {
      for (const key in config.query) {
        const value = config.query[key];
        if (value !== undefined) {
          url.searchParams.append(key, value);
        }
      }
    }

    if (config.path) {
      for (const key in config.path) {
        const t1 = encodeURI("{");
        const t2 = encodeURI("}");
        const reg = new RegExp(`${t1}${key}${t2}`, "g");
        url.pathname = url.pathname.replace(reg, config.path[key]);
      }
    }

    config = await this._requestInterceptor.run(config);

    const headers = new Headers();

    for (const key in config.header) {
      const value = config.header[key];
      if (value !== undefined) {
        headers.set(key, value);
      }
    }

    const timeout = config.timeout || defaults.timeout;

    const body =
      config.body === undefined
        ? undefined
        : ["GET", "HEAD"].indexOf(config.method.toUpperCase()) > -1
        ? undefined
        : config.body instanceof RuntimeForm
        ? config.body.formData()
        : config.body instanceof Blob
        ? config.body
        : typeof config.body === "object"
        ? JSON.stringify(config.body)
        : config.body.toString();

    const exec = () =>
      fetch(url.toString(), {
        method: config.method,
        body: body,
        headers: headers,

        // common options
        cache: config.cache,
        credentials: config.credentials,
        integrity: config.integrity,
        keepalive: config.keepalive,
        mode: config.mode,
        redirect: config.redirect,
        referrer: config.referrer,
        referrerPolicy: config.referrerPolicy,
        signal: config.signal,
        window: config.window,
      });

    return (timeout ? this._timeout(timeout, exec()) : exec())
      .then(async (resp) => {
        if (!resp.ok) return Promise.reject(RuntimeError.fromResponse(resp));
        const contentType = resp.headers.get("content-type");
        switch (contentType) {
          case "application/json":
            return { data: await resp.json(), resp };
          case "application/x-www-form-urlencoded":
            return { data: await resp.formData(), resp };
          case "application/octet-stream":
            return { data: await resp.blob(), resp };
          default:
            return { data: await resp.text(), resp };
        }
      })
      .then(({ data, resp }) => {
        return this._responseInterceptor.runSuccess<T>(config, resp, data);
      })
      .catch((err) => {
        const runtimeErr = err instanceof RuntimeError ? err : err instanceof Error ? RuntimeError.fromError(err) : new RuntimeError(err + "");

        return this._responseInterceptor.runError<T>(config, runtimeErr);
      });
  }
}


// Generate by swagger2ts
/* default type by generation start */
interface MapAny {
  [key: string]: any
}


interface MapString {
  [key: string]: string | undefined
}


/* default type by generation end */
/**
 * ButtonDTO
 */
export interface ButtonDTO {
  name?: string /* 名称(50字符以内) */
  permission?: string /* 权限(255字符以内) */
  pid?: number /* 上级节点ID */
  show?: boolean /* 显示 */
}


/**
 * MenuTreeVO
 */
export interface MenuTreeVO {
  category?: "BUTTON" | "MENU" /* 类型 */
  children?: Array<MenuTreeVO> /* 子菜单 */
  icon?: string /* 图标 */
  id?: number /* id */
  module?: string /* 组件 */
  name?: string /* 名称 */
  params?: string /* 路由参数 */
  permission?: string /* 权限 */
  route?: string /* 路由地址 */
  target?: string /* 打开方式(50字符以内) */
}


/**
 * RoleDTO
 */
export interface RoleDTO {
  description?: string /* 描述(255字符以内) */
  name?: string /* 角色(100字符以内) */
  pid?: number /* 归属 */
}


/**
 * SitemapDTO
 */
export interface SitemapDTO {
  icon?: string /* 图标(255字符以内) */
  module?: string /* 组件(255字符以内) */
  name?: string /* 名称(50字符以内) */
  params?: string /* 路由参数(255字符以内) */
  pid?: number /* 上级节点ID */
  route?: string /* 路由地址(255字符以内) */
  target?: string /* 打开方式(50字符以内) */
}


/**
 * 菜单树
 */
export interface 菜单树 {
  category?: "BUTTON" | "MENU" /* 分类 */
  children?: Array<菜单树> /* 子菜单 */
  deleted?: boolean /* 删除 */
  gmtModified?: string /* 更新时间 */
  icon?: string /* 图标 */
  id?: number /* id */
  locked?: boolean /* 锁 */
  module?: string /* 组件 */
  name?: string /* 名称 */
  params?: string /* 路由参数 */
  permission?: string /* 权限 */
  pid?: number /* 上级节点ID */
  route?: string /* 路由地址 */
  show?: boolean /* 显示 */
  target?: string /* 打开方式 */
}


/**
 * 角色树查询
 */
export interface 角色树查询 {
  children?: Array<角色树查询> /* 子菜单 */
  description?: string /* 描述 */
  gmtModified?: string /* 更新时间 */
  id?: number /* id */
  locked?: boolean /* 锁 */
  name?: string /* 名称 */
  pid?: number /* 上级节点ID */
}


export interface SwaggerApi{
  /**
   * @tag 公共接口
   * @summary 按钮
   */
  get(url: "/button", options?: {} & IDefaultOptions): Promise<Array<MenuTreeVO>>

  /**
   * @tag 公共接口
   * @summary 导航条
   */
  get(url: "/navbar", options?: {} & IDefaultOptions): Promise<Array<MenuTreeVO>>

  /**
   * @tag 角色管理
   * @summary 查询
   */
  get(url: "/role", options?: {} & IDefaultOptions): Promise<Array<角色树查询>>

  /**
   * @tag 角色管理
   * @summary 新增
   */
  post(url: "/role", options: {body: RoleDTO} & IDefaultOptions): Promise<null>

  /**
   * @tag 角色管理
   * @summary 删除
   * @description 角色删除是一个危险的操作，不提供批量服务
   */
  delete(url: "/role/{id}", options: {path: {
    id: number
  }} & IDefaultOptions): Promise<null>

  /**
   * @tag 角色管理
   * @summary 修改
   * @description 角色编辑不能修改从属关系,仅提供名称修改
   */
  put(url: "/role/{id}", options: {path: {
    id: number
  }, body: RoleDTO} & IDefaultOptions): Promise<null>

  /**
   * @tag 角色管理
   * @summary 权限查询
   */
  get(url: "/role/{id}/authority", options: {path: {
    id: number
  }} & IDefaultOptions): Promise<Array<number | undefined>>

  /**
   * @tag 角色管理
   * @summary 权限设置
   */
  post(url: "/role/{id}/authority", options: {path: {
    id: number
  }, body: Array<number | undefined>} & IDefaultOptions): Promise<null>

  /**
   * @tag 角色管理
   * @summary 菜单查询
   * @description 根据角色id查询菜单信息
   */
  get(url: "/role/{id}/menu", options: {path: {
    id: number
  }} & IDefaultOptions): Promise<Array<number | undefined>>

  /**
   * @tag 角色管理
   * @summary 菜单设置
   * @description 设置角色的菜单信息
   */
  post(url: "/role/{id}/menu", options: {path: {
    id: number
  }, body: Array<number | undefined>} & IDefaultOptions): Promise<null>

  /**
   * @tag 菜单管理
   * @summary 查询
   * @description 系统管理，菜单树结构
   */
  get(url: "/sitemap", options?: {} & IDefaultOptions): Promise<Array<菜单树>>

  /**
   * @tag 菜单管理
   * @summary 新增
   * @description 添加菜单
   */
  post(url: "/sitemap", options: {body: SitemapDTO} & IDefaultOptions): Promise<null>

  /**
   * @tag 菜单管理
   * @summary 添加按钮
   */
  post(url: "/sitemap/button", options: {body: ButtonDTO} & IDefaultOptions): Promise<null>

  /**
   * @tag 菜单管理
   * @summary 修改按钮
   */
  put(url: "/sitemap/button/{id}", options: {path: {
    id: number
  }, body: ButtonDTO} & IDefaultOptions): Promise<null>

  /**
   * @tag 菜单管理
   * @summary 删除
   * @description 删除菜单， 级联删除子项
   */
  delete(url: "/sitemap/{id}", options: {path: {
    id: number
  }} & IDefaultOptions): Promise<null>

  /**
   * @tag 菜单管理
   * @summary 更新
   * @description 编辑菜单
   */
  put(url: "/sitemap/{id}", options: {path: {
    id: number
  }, body: SitemapDTO} & IDefaultOptions): Promise<null>
}


// swagger runtime. generate by swagger2ts
interface IRuntimeHeaderMapString {
  [key: string]: string;
}


interface IRuntimeHeaderConfig {
  common: IRuntimeHeaderMapString;
  [method: string]: IRuntimeHeaderMapString;
}


interface IRuntimeRequestCommonOptions extends Omit<RequestInit, "body" | "method"> {
  path?: {
    [key: string]: string;
  };
  query?: {
    [key: string]: string;
  };
  header?: {
    [key: string]: string;
  };
  body?: any;
  timeout?: number;
}


interface IRuntimeRequestOptions extends IRuntimeRequestCommonOptions {
  url: string;
  method: Uppercase<string>;
}


interface IRequestInterceptor {
  use(fn: IRequestInterceptorFn): IInterceptorCancelFn;
}


interface IResponseInterceptor {
  use(success: IResponseInterceptorSuccessFn<any>, error: IResponseInterceptorErrorFn<any>): IInterceptorCancelFn;
}


interface IRuntimeForm {
  [key: string]: any;
}


export interface IRuntime {
  readonly interceptors: { readonly request: IRequestInterceptor; readonly response: IResponseInterceptor };
  readonly defaults: { readonly timeout: number; readonly headers: IRuntimeHeaderConfig };
  readonly baseURL: string;
  domain: string;
  prefix: string;
  request<T>(config: IRuntimeRequestOptions): Promise<T>;
}


type IDefaultOptions = Omit<RequestInit, "body" | "method"> & { timeout?: number }


type IInterceptorCancelFn = () => void;


type IRequestInterceptorFn = (config: IRuntimeRequestOptions) => Promise<IRuntimeRequestOptions>;


type IResponseInterceptorSuccessFn<T> = (config: IRuntimeRequestOptions, response: Response, data: T) => Promise<T>;


type IResponseInterceptorErrorFn<T> = (config: IRuntimeRequestOptions, Error: RuntimeError) => Promise<T>;


export type IClient = SwaggerApi & IRuntime


public use(fn: IRequestInterceptorFn) {
    this._fns.push(fn);

    return () => {
      const index = this._fns.findIndex((v) => v === fn);

      if (index > -1) {
        this._fns.splice(index, 1);
      }
    };
  }


async run(config: IRuntimeRequestOptions): Promise<IRuntimeRequestOptions> {
    for (const fn of this._fns) {
      config = await fn(config);
    }

    return config;
  }


public use(successFn: IResponseInterceptorSuccessFn<any>, errorFn: IResponseInterceptorErrorFn<any>) {
    this._fnsSuccess.push(successFn);
    this._fnsError.push(errorFn);

    return () => {
      const successIndex = this._fnsSuccess.findIndex((v) => v === successFn);
      const errorIndex = this._fnsError.findIndex((v) => v === errorFn);

      if (successIndex > -1) {
        this._fnsSuccess.splice(successIndex, 1);
      }

      if (errorIndex > -1) {
        this._fnsError.splice(errorIndex, 1);
      }
    };
  }


async runSuccess<T>(config: IRuntimeRequestOptions, response: Response, data: T): Promise<T> {
    for (const fn of this._fnsSuccess) {
      data = await fn(config, response, data);
    }

    return data;
  }


async runError<T>(config: IRuntimeRequestOptions, err: RuntimeError): Promise<T> {
    let res!: T;

    for (const fn of this._fnsError) {
      res = await fn(config, err);
    }

    return res;
  }


public formData(): FormData {
    const form = new FormData();

    for (const key in this._form) {
      if (this._form[key] !== undefined) {
        form.append(key, this._form[key]);
      }
    }

    return form;
  }


static fromResponse(resp: Response) {
    return new RuntimeError(resp.statusText, resp);
  }


static fromError(err: Error) {
    return new RuntimeError(err.message || "unknown error: " + err);
  }


private _timeout<T>(ms: number, promise: Promise<T>) {
    return new Promise<T>((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new RuntimeError(`timeout of ${ms}ms`));
      }, ms);

      promise
        .then((value) => {
          clearTimeout(timer);
          resolve(value);
        })
        .catch((reason) => {
          clearTimeout(timer);
          reject(reason);
        });
    });
  }


public async request<T>(config: IRuntimeRequestOptions): Promise<T> {
    const url = new URL(this.baseURL + config.url);
    config.header = config.header || {};

    const defaults = this.defaults;

    // set default header
    for (const key in defaults.headers.common) {
      config.header[key] = defaults.headers.common[key];
    }

    // set header for this method
    for (const key in defaults.headers[config.method] || {}) {
      config.header[key] = defaults.headers[config.method][key];
    }

    if (config.query) {
      for (const key in config.query) {
        const value = config.query[key];
        if (value !== undefined) {
          url.searchParams.append(key, value);
        }
      }
    }

    if (config.path) {
      for (const key in config.path) {
        const t1 = encodeURI("{");
        const t2 = encodeURI("}");
        const reg = new RegExp(`${t1}${key}${t2}`, "g");
        url.pathname = url.pathname.replace(reg, config.path[key]);
      }
    }

    config = await this._requestInterceptor.run(config);

    const headers = new Headers();

    for (const key in config.header) {
      const value = config.header[key];
      if (value !== undefined) {
        headers.set(key, value);
      }
    }

    const timeout = config.timeout || defaults.timeout;

    const body =
      config.body === undefined
        ? undefined
        : ["GET", "HEAD"].indexOf(config.method.toUpperCase()) > -1
        ? undefined
        : config.body instanceof RuntimeForm
        ? config.body.formData()
        : config.body instanceof Blob
        ? config.body
        : typeof config.body === "object"
        ? JSON.stringify(config.body)
        : config.body.toString();

    const exec = () =>
      fetch(url.toString(), {
        method: config.method,
        body: body,
        headers: headers,

        // common options
        cache: config.cache,
        credentials: config.credentials,
        integrity: config.integrity,
        keepalive: config.keepalive,
        mode: config.mode,
        redirect: config.redirect,
        referrer: config.referrer,
        referrerPolicy: config.referrerPolicy,
        signal: config.signal,
        window: config.window,
      });

    return (timeout ? this._timeout(timeout, exec()) : exec())
      .then(async (resp) => {
        if (!resp.ok) return Promise.reject(RuntimeError.fromResponse(resp));
        const contentType = resp.headers.get("content-type");
        switch (contentType) {
          case "application/json":
            return { data: await resp.json(), resp };
          case "application/x-www-form-urlencoded":
            return { data: await resp.formData(), resp };
          case "application/octet-stream":
            return { data: await resp.blob(), resp };
          default:
            return { data: await resp.text(), resp };
        }
      })
      .then(({ data, resp }) => {
        return this._responseInterceptor.runSuccess<T>(config, resp, data);
      })
      .catch((err) => {
        const runtimeErr = err instanceof RuntimeError ? err : err instanceof Error ? RuntimeError.fromError(err) : new RuntimeError(err + "");

        return this._responseInterceptor.runError<T>(config, runtimeErr);
      });
  }


/**
 *
Using a device ID, returns a DeviceEventsResponse object containing an
 *  array of events for the device.

 */
export class ListDeviceEventsCommand extends $Command<
  ListDeviceEventsCommandInput,
  ListDeviceEventsCommandOutput,
  IoT1ClickDevicesServiceClientResolvedConfig
> {
  private resolved = false;
  // Start section: command_properties
  // End section: command_properties

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

  /**
   * @internal
   */
  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: IoT1ClickDevicesServiceClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<ListDeviceEventsCommandInput, ListDeviceEventsCommandOutput> {
    if (!this.resolved) {
      this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));
      this.resolved = true;
    }

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

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

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

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

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


export type ListDeviceEventsCommandInput = ListDeviceEventsRequest;


export type ListDeviceEventsCommandOutput = ListDeviceEventsResponse & __MetadataBearer;


/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: IoT1ClickDevicesServiceClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<ListDeviceEventsCommandInput, ListDeviceEventsCommandOutput> {
    if (!this.resolved) {
      this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));
      this.resolved = true;
    }

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

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


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


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


export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
  return {
    Component,
    display: {
      needsAccounts: true,
      needsApi: [
        'tx.sudo.setKey'
      ],
      needsSudo: true
    },
    icon: 'unlock',
    name: 'sudo',
    text: t<string>('nav.sudo', 'Sudo', { ns: 'apps-routing' })
  };
}


() => {
			this.cellType = NOTEBOOK_CELL_TYPE.bindTo(this._contextKeyService);
			this.cellEditable = NOTEBOOK_CELL_EDITABLE.bindTo(this._contextKeyService);
			this.cellFocused = NOTEBOOK_CELL_FOCUSED.bindTo(this._contextKeyService);
			this.cellEditorFocused = NOTEBOOK_CELL_EDITOR_FOCUSED.bindTo(this._contextKeyService);
			this.markdownEditMode = NOTEBOOK_CELL_MARKDOWN_EDIT_MODE.bindTo(this._contextKeyService);
			this.cellRunState = NOTEBOOK_CELL_EXECUTION_STATE.bindTo(this._contextKeyService);
			this.cellExecuting = NOTEBOOK_CELL_EXECUTING.bindTo(this._contextKeyService);
			this.cellHasOutputs = NOTEBOOK_CELL_HAS_OUTPUTS.bindTo(this._contextKeyService);
			this.cellContentCollapsed = NOTEBOOK_CELL_INPUT_COLLAPSED.bindTo(this._contextKeyService);
			this.cellOutputCollapsed = NOTEBOOK_CELL_OUTPUT_COLLAPSED.bindTo(this._contextKeyService);
			this.cellLineNumbers = NOTEBOOK_CELL_LINE_NUMBERS.bindTo(this._contextKeyService);

			if (element) {
				this.updateForElement(element);
			}
		}


e => {
			if (this.element && e.affectsCell(this.element.uri)) {
				this.updateForExecutionState();
			}
		}


e => this.onDidChangeState(e)


() => this.updateForOutputs()


() => this.updateForFocusState()


() => {
			this.updateForFocusState();
			this.updateForExecutionState();
			this.updateForEditState();
			this.updateForCollapseState();
			this.updateForOutputs();

			this.cellLineNumbers.set(this.element!.lineNumbers);
		}


() => {
			if (e.internalMetadataChanged) {
				this.updateForExecutionState();
			}

			if (e.editStateChanged) {
				this.updateForEditState();
			}

			if (e.focusModeChanged) {
				this.updateForFocusState();
			}

			if (e.cellLineNumberChanged) {
				this.cellLineNumbers.set(this.element!.lineNumbers);
			}

			if (e.inputCollapsedChanged || e.outputCollapsedChanged) {
				this.updateForCollapseState();
			}
		}


export class CellContextKeyPart extends CellPart {
	private cellContextKeyManager: CellContextKeyManager;

	constructor(
		notebookEditor: INotebookEditorDelegate,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
	) {
		super();

		this.cellContextKeyManager = this._register(this.instantiationService.createInstance(CellContextKeyManager, notebookEditor, undefined));
	}

	protected override didRenderCell(element: ICellViewModel): void {
		this.cellContextKeyManager.updateForElement(element);
	}
}


export class CellContextKeyManager extends Disposable {

	private cellType!: IContextKey<'code' | 'markup'>;
	private cellEditable!: IContextKey<boolean>;
	private cellFocused!: IContextKey<boolean>;
	private cellEditorFocused!: IContextKey<boolean>;
	private cellRunState!: IContextKey<NotebookCellExecutionStateContext>;
	private cellExecuting!: IContextKey<boolean>;
	private cellHasOutputs!: IContextKey<boolean>;
	private cellContentCollapsed!: IContextKey<boolean>;
	private cellOutputCollapsed!: IContextKey<boolean>;
	private cellLineNumbers!: IContextKey<'on' | 'off' | 'inherit'>;

	private markdownEditMode!: IContextKey<boolean>;

	private readonly elementDisposables = this._register(new DisposableStore());

	constructor(
		private readonly notebookEditor: INotebookEditorDelegate,
		private element: ICellViewModel | undefined,
		@IContextKeyService private readonly _contextKeyService: IContextKeyService,
		@INotebookExecutionStateService private readonly _notebookExecutionStateService: INotebookExecutionStateService
	) {
		super();

		this._contextKeyService.bufferChangeEvents(() => {
			this.cellType = NOTEBOOK_CELL_TYPE.bindTo(this._contextKeyService);
			this.cellEditable = NOTEBOOK_CELL_EDITABLE.bindTo(this._contextKeyService);
			this.cellFocused = NOTEBOOK_CELL_FOCUSED.bindTo(this._contextKeyService);
			this.cellEditorFocused = NOTEBOOK_CELL_EDITOR_FOCUSED.bindTo(this._contextKeyService);
			this.markdownEditMode = NOTEBOOK_CELL_MARKDOWN_EDIT_MODE.bindTo(this._contextKeyService);
			this.cellRunState = NOTEBOOK_CELL_EXECUTION_STATE.bindTo(this._contextKeyService);
			this.cellExecuting = NOTEBOOK_CELL_EXECUTING.bindTo(this._contextKeyService);
			this.cellHasOutputs = NOTEBOOK_CELL_HAS_OUTPUTS.bindTo(this._contextKeyService);
			this.cellContentCollapsed = NOTEBOOK_CELL_INPUT_COLLAPSED.bindTo(this._contextKeyService);
			this.cellOutputCollapsed = NOTEBOOK_CELL_OUTPUT_COLLAPSED.bindTo(this._contextKeyService);
			this.cellLineNumbers = NOTEBOOK_CELL_LINE_NUMBERS.bindTo(this._contextKeyService);

			if (element) {
				this.updateForElement(element);
			}
		});

		this._register(this._notebookExecutionStateService.onDidChangeCellExecution(e => {
			if (this.element && e.affectsCell(this.element.uri)) {
				this.updateForExecutionState();
			}
		}));
	}

	public updateForElement(element: ICellViewModel | undefined) {
		this.elementDisposables.clear();
		this.element = element;

		if (!element) {
			return;
		}

		this.elementDisposables.add(element.onDidChangeState(e => this.onDidChangeState(e)));

		if (element instanceof CodeCellViewModel) {
			this.elementDisposables.add(element.onDidChangeOutputs(() => this.updateForOutputs()));
		}

		this.elementDisposables.add(this.notebookEditor.onDidChangeActiveCell(() => this.updateForFocusState()));

		if (this.element instanceof MarkupCellViewModel) {
			this.cellType.set('markup');
		} else if (this.element instanceof CodeCellViewModel) {
			this.cellType.set('code');
		}

		this._contextKeyService.bufferChangeEvents(() => {
			this.updateForFocusState();
			this.updateForExecutionState();
			this.updateForEditState();
			this.updateForCollapseState();
			this.updateForOutputs();

			this.cellLineNumbers.set(this.element!.lineNumbers);
		});
	}

	private onDidChangeState(e: CellViewModelStateChangeEvent) {
		this._contextKeyService.bufferChangeEvents(() => {
			if (e.internalMetadataChanged) {
				this.updateForExecutionState();
			}

			if (e.editStateChanged) {
				this.updateForEditState();
			}

			if (e.focusModeChanged) {
				this.updateForFocusState();
			}

			if (e.cellLineNumberChanged) {
				this.cellLineNumbers.set(this.element!.lineNumbers);
			}

			if (e.inputCollapsedChanged || e.outputCollapsedChanged) {
				this.updateForCollapseState();
			}
		});
	}

	private updateForFocusState() {
		if (!this.element) {
			return;
		}

		const activeCell = this.notebookEditor.getActiveCell();
		this.cellFocused.set(this.notebookEditor.getActiveCell() === this.element);

		if (activeCell === this.element) {
			this.cellEditorFocused.set(this.element.focusMode === CellFocusMode.Editor);
		} else {
			this.cellEditorFocused.set(false);
		}

	}

	private updateForExecutionState() {
		if (!this.element) {
			return;
		}

		const internalMetadata = this.element.internalMetadata;
		this.cellEditable.set(!this.notebookEditor.isReadOnly);

		const exeState = this._notebookExecutionStateService.getCellExecution(this.element.uri);
		if (this.element instanceof MarkupCellViewModel) {
			this.cellRunState.reset();
			this.cellExecuting.reset();
		} else if (exeState?.state === NotebookCellExecutionState.Executing) {
			this.cellRunState.set('executing');
			this.cellExecuting.set(true);
		} else if (exeState?.state === NotebookCellExecutionState.Pending || exeState?.state === NotebookCellExecutionState.Unconfirmed) {
			this.cellRunState.set('pending');
			this.cellExecuting.set(true);
		} else if (internalMetadata.lastRunSuccess === true) {
			this.cellRunState.set('succeeded');
			this.cellExecuting.set(false);
		} else if (internalMetadata.lastRunSuccess === false) {
			this.cellRunState.set('failed');
			this.cellExecuting.set(false);
		} else {
			this.cellRunState.set('idle');
			this.cellExecuting.set(false);
		}
	}

	private updateForEditState() {
		if (!this.element) {
			return;
		}

		if (this.element instanceof MarkupCellViewModel) {
			this.markdownEditMode.set(this.element.getEditState() === CellEditState.Editing);
		} else {
			this.markdownEditMode.set(false);
		}
	}

	private updateForCollapseState() {
		if (!this.element) {
			return;
		}

		this.cellContentCollapsed.set(!!this.element.isInputCollapsed);
		this.cellOutputCollapsed.set(!!this.element.isOutputCollapsed);
	}

	private updateForOutputs() {
		if (this.element instanceof CodeCellViewModel) {
			this.cellHasOutputs.set(this.element.outputsViewModels.length > 0);
		} else {
			this.cellHasOutputs.set(false);
		}
	}
}


protected override didRenderCell(element: ICellViewModel): void {
		this.cellContextKeyManager.updateForElement(element);
	}


public updateForElement(element: ICellViewModel | undefined) {
		this.elementDisposables.clear();
		this.element = element;

		if (!element) {
			return;
		}

		this.elementDisposables.add(element.onDidChangeState(e => this.onDidChangeState(e)));

		if (element instanceof CodeCellViewModel) {
			this.elementDisposables.add(element.onDidChangeOutputs(() => this.updateForOutputs()));
		}

		this.elementDisposables.add(this.notebookEditor.onDidChangeActiveCell(() => this.updateForFocusState()));

		if (this.element instanceof MarkupCellViewModel) {
			this.cellType.set('markup');
		} else if (this.element instanceof CodeCellViewModel) {
			this.cellType.set('code');
		}

		this._contextKeyService.bufferChangeEvents(() => {
			this.updateForFocusState();
			this.updateForExecutionState();
			this.updateForEditState();
			this.updateForCollapseState();
			this.updateForOutputs();

			this.cellLineNumbers.set(this.element!.lineNumbers);
		});
	}


private onDidChangeState(e: CellViewModelStateChangeEvent) {
		this._contextKeyService.bufferChangeEvents(() => {
			if (e.internalMetadataChanged) {
				this.updateForExecutionState();
			}

			if (e.editStateChanged) {
				this.updateForEditState();
			}

			if (e.focusModeChanged) {
				this.updateForFocusState();
			}

			if (e.cellLineNumberChanged) {
				this.cellLineNumbers.set(this.element!.lineNumbers);
			}

			if (e.inputCollapsedChanged || e.outputCollapsedChanged) {
				this.updateForCollapseState();
			}
		});
	}


private updateForFocusState() {
		if (!this.element) {
			return;
		}

		const activeCell = this.notebookEditor.getActiveCell();
		this.cellFocused.set(this.notebookEditor.getActiveCell() === this.element);

		if (activeCell === this.element) {
			this.cellEditorFocused.set(this.element.focusMode === CellFocusMode.Editor);
		} else {
			this.cellEditorFocused.set(false);
		}

	}


private updateForExecutionState() {
		if (!this.element) {
			return;
		}

		const internalMetadata = this.element.internalMetadata;
		this.cellEditable.set(!this.notebookEditor.isReadOnly);

		const exeState = this._notebookExecutionStateService.getCellExecution(this.element.uri);
		if (this.element instanceof MarkupCellViewModel) {
			this.cellRunState.reset();
			this.cellExecuting.reset();
		} else if (exeState?.state === NotebookCellExecutionState.Executing) {
			this.cellRunState.set('executing');
			this.cellExecuting.set(true);
		} else if (exeState?.state === NotebookCellExecutionState.Pending || exeState?.state === NotebookCellExecutionState.Unconfirmed) {
			this.cellRunState.set('pending');
			this.cellExecuting.set(true);
		} else if (internalMetadata.lastRunSuccess === true) {
			this.cellRunState.set('succeeded');
			this.cellExecuting.set(false);
		} else if (internalMetadata.lastRunSuccess === false) {
			this.cellRunState.set('failed');
			this.cellExecuting.set(false);
		} else {
			this.cellRunState.set('idle');
			this.cellExecuting.set(false);
		}
	}


private updateForEditState() {
		if (!this.element) {
			return;
		}

		if (this.element instanceof MarkupCellViewModel) {
			this.markdownEditMode.set(this.element.getEditState() === CellEditState.Editing);
		} else {
			this.markdownEditMode.set(false);
		}
	}


private updateForCollapseState() {
		if (!this.element) {
			return;
		}

		this.cellContentCollapsed.set(!!this.element.isInputCollapsed);
		this.cellOutputCollapsed.set(!!this.element.isOutputCollapsed);
	}


private updateForOutputs() {
		if (this.element instanceof CodeCellViewModel) {
			this.cellHasOutputs.set(this.element.outputsViewModels.length > 0);
		} else {
			this.cellHasOutputs.set(false);
		}
	}


export declare function useDispatcher(dis: disArgs): void;


declare type disArgs = Dispatcher | DispatcherRegisterOptions | (Dispatcher | DispatcherRegisterOptions)[];


export class ImportDeclarationStructurePrinter extends NodePrinter<OptionalKind<ImportDeclarationStructure>> {
    private readonly multipleWriter = new NewLineFormattingStructuresPrinter(this);

    printTexts(writer: CodeBlockWriter, structures: ReadonlyArray<OptionalKind<ImportDeclarationStructure>> | undefined) {
        this.multipleWriter.printText(writer, structures);
    }

    protected printTextInternal(writer: CodeBlockWriter, structure: OptionalKind<ImportDeclarationStructure>) {
        const hasNamedImport = structure.namedImports != null && structure.namedImports.length > 0;
        // validation
        if (hasNamedImport && structure.namespaceImport != null)
            throw new errors.InvalidOperationError("An import declaration cannot have both a namespace import and a named import.");

        writer.write("import");

        // type only
        if (structure.isTypeOnly)
            writer.write(" type");
        // default import
        if (structure.defaultImport != null) {
            writer.write(` ${structure.defaultImport}`);
            writer.conditionalWrite(hasNamedImport || structure.namespaceImport != null, ",");
        }
        // namespace import
        if (structure.namespaceImport != null)
            writer.write(` * as ${structure.namespaceImport}`);
        // named imports
        if (structure.namedImports != null && structure.namedImports.length > 0) {
            writer.space();
            this.factory.forNamedImportExportSpecifier().printTextsWithBraces(writer, structure.namedImports);
        }
        // from keyword
        writer.conditionalWrite(structure.defaultImport != null || hasNamedImport || structure.namespaceImport != null, " from");
        writer.write(" ");
        writer.quote(structure.moduleSpecifier);
        writer.write(";");
    }
}


printTexts(writer: CodeBlockWriter, structures: ReadonlyArray<OptionalKind<ImportDeclarationStructure>> | undefined) {
        this.multipleWriter.printText(writer, structures);
    }


protected printTextInternal(writer: CodeBlockWriter, structure: OptionalKind<ImportDeclarationStructure>) {
        const hasNamedImport = structure.namedImports != null && structure.namedImports.length > 0;
        // validation
        if (hasNamedImport && structure.namespaceImport != null)
            throw new errors.InvalidOperationError("An import declaration cannot have both a namespace import and a named import.");

        writer.write("import");

        // type only
        if (structure.isTypeOnly)
            writer.write(" type");
        // default import
        if (structure.defaultImport != null) {
            writer.write(` ${structure.defaultImport}`);
            writer.conditionalWrite(hasNamedImport || structure.namespaceImport != null, ",");
        }
        // namespace import
        if (structure.namespaceImport != null)
            writer.write(` * as ${structure.namespaceImport}`);
        // named imports
        if (structure.namedImports != null && structure.namedImports.length > 0) {
            writer.space();
            this.factory.forNamedImportExportSpecifier().printTextsWithBraces(writer, structure.namedImports);
        }
        // from keyword
        writer.conditionalWrite(structure.defaultImport != null || hasNamedImport || structure.namespaceImport != null, " from");
        writer.write(" ");
        writer.quote(structure.moduleSpecifier);
        writer.write(";");
    }