// Columns
// ===============================================================================================
/**
   * Get all the available columns in the current schema/database. Can be filtered to a specific table
   */
async columns(table?: string) {
    const query = this.knex
      .select<{ table_name: string; column_name: string }[]>(
        'table_name',
        'column_name'
      )
      .from('information_schema.columns')
      .whereIn('table_schema', this.explodedSchema);

    if (table) {
      query.andWhere({ table_name: table });
    }

    const records = await query;

    return records.map(({ table_name, column_name }) => ({
      table: table_name,
      column: column_name,
    }));
  }


/**
   * Get the column info for all columns, columns in a given table, or a specific column.
   */
columnInfo(): Promise<Column[]>;


columnInfo(table: string): Promise<Column[]>;


columnInfo(table: string, column: string): Promise<Column>;


async columnInfo<T>(table?: string, column?: string) {
    const { knex } = this;

    const query = knex
      .select(
        'c.column_name',
        'c.table_name',
        'c.data_type',
        'c.column_default',
        'c.character_maximum_length',
        'c.is_nullable',
        'c.numeric_precision',
        'c.numeric_scale',
        'c.table_schema',

        knex
          .select(knex.raw(`'YES'`))
          .from('pg_index')
          .join('pg_attribute', function () {
            this.on('pg_attribute.attrelid', '=', 'pg_index.indrelid').andOn(
              knex.raw('pg_attribute.attnum = any(pg_index.indkey)')
            );
          })
          .whereRaw('pg_index.indrelid = c.table_name::regclass')
          .andWhere(knex.raw('pg_attribute.attname = c.column_name'))
          .andWhere(knex.raw('pg_index.indisprimary'))
          .as('is_primary'),

        knex
          .select(
            knex.raw(
              'pg_catalog.col_description(pg_catalog.pg_class.oid, c.ordinal_position:: int)'
            )
          )
          .from('pg_catalog.pg_class')
          .whereRaw(
            `pg_catalog.pg_class.oid = (select('"' || c.table_name || '"'):: regclass:: oid)`
          )
          .andWhere({ 'pg_catalog.pg_class.relname': 'c.table_name' })
          .as('column_comment'),

        knex.raw(
          'pg_get_serial_sequence(c.table_name, c.column_name) as serial'
        ),

        'ffk.referenced_table_schema',
        'ffk.referenced_table_name',
        'ffk.referenced_column_name'
      )
      .from(knex.raw('information_schema.columns c'))
      .joinRaw(
        `
        LEFT JOIN (
          SELECT
            k1.table_schema,
            k1.table_name,
            k1.column_name,
            k2.table_schema AS referenced_table_schema,
            k2.table_name AS referenced_table_name,
            k2.column_name AS referenced_column_name
          FROM
            information_schema.key_column_usage k1
            JOIN information_schema.referential_constraints fk using (
              constraint_schema, constraint_name
            )
            JOIN information_schema.key_column_usage k2 ON k2.constraint_schema = fk.unique_constraint_schema
            AND k2.constraint_name = fk.unique_constraint_name
            AND k2.ordinal_position = k1.position_in_unique_constraint
        ) ffk ON ffk.table_name = c.table_name
        AND ffk.column_name = c.column_name
      `
      )
      .whereIn('c.table_schema', this.explodedSchema);

    if (table) {
      query.andWhere({ 'c.table_name': table });
    }

    if (column) {
      const rawColumn = await query
        .andWhere({ 'c.column_name': column })
        .first();

      return {
        name: rawColumn.column_name,
        table: rawColumn.table_name,
        type: rawColumn.data_type,
        default_value: rawColumn.column_default
          ? this.parseDefaultValue(rawColumn.column_default)
          : null,
        max_length: rawColumn.character_maximum_length,
        precision: rawColumn.numeric_precision,
        scale: rawColumn.numeric_scale,
        is_nullable: rawColumn.is_nullable === 'YES',
        is_primary_key: rawColumn.is_primary === 'YES',
        has_auto_increment: rawColumn.serial !== null,
        foreign_key_column: rawColumn.referenced_column_name,
        foreign_key_table: rawColumn.referenced_table_name,
        comment: rawColumn.column_comment,
        schema: rawColumn.table_schema,
        foreign_key_schema: rawColumn.referenced_table_schema,
      } as T extends string ? Column : Column[];
    }

    const records: RawColumn[] = await query;

    return records.map(
      (rawColumn): Column => {
        return {
          name: rawColumn.column_name,
          table: rawColumn.table_name,
          type: rawColumn.data_type,
          default_value: rawColumn.column_default
            ? this.parseDefaultValue(rawColumn.column_default)
            : null,
          max_length: rawColumn.character_maximum_length,
          precision: rawColumn.numeric_precision,
          scale: rawColumn.numeric_scale,
          is_nullable: rawColumn.is_nullable === 'YES',
          is_primary_key: rawColumn.is_primary === 'YES',
          has_auto_increment: rawColumn.serial !== null,
          foreign_key_column: rawColumn.referenced_column_name,
          foreign_key_table: rawColumn.referenced_table_name,

          comment: rawColumn.column_comment,
          schema: rawColumn.table_schema,
          foreign_key_schema: rawColumn.referenced_table_schema,
        };
      }
    ) as T extends string ? Column : Column[];
  }


/**
   * Check if the given table contains the given column
   */
async hasColumn(table: string, column: string) {
    const subquery = this.knex
      .select()
      .from('information_schema.columns')
      .whereIn('table_schema', this.explodedSchema)
      .andWhere({
        table_name: table,
        column_name: column,
      });
    const record = await this.knex
      .select<{ exists: boolean }>(this.knex.raw('exists (?)', [subquery]))
      .first();
    return record?.exists || false;
  }


/**
   * Get the primary key column for the given table
   */
async primary(table: string): Promise<string> {
    const result = await this.knex
      .select('information_schema.key_column_usage.column_name')
      .from('information_schema.key_column_usage')
      .leftJoin(
        'information_schema.table_constraints',
        'information_schema.table_constraints.constraint_name',
        'information_schema.key_column_usage.constraint_name'
      )
      .whereIn(
        'information_schema.table_constraints.table_schema',
        this.explodedSchema
      )
      .andWhere({
        'information_schema.table_constraints.constraint_type': 'PRIMARY KEY',
        'information_schema.table_constraints.table_name': table,
      })
      .first();

    return result ? result.column_name : null;
  }


/**
 * User Agent Core.
 * @remarks
 * Core designates the functions specific to a particular type
 * of SIP entity, i.e., specific to either a stateful or stateless
 * proxy, a user agent or registrar.  All cores, except those for
 * the stateless proxy, are transaction users.
 * https://tools.ietf.org/html/rfc3261#section-6
 *
 * UAC Core: The set of processing functions required of a UAC that
 * reside above the transaction and transport layers.
 * https://tools.ietf.org/html/rfc3261#section-6
 *
 * UAS Core: The set of processing functions required at a UAS that
 * resides above the transaction and transport layers.
 * https://tools.ietf.org/html/rfc3261#section-6
 * @public
 */
export declare class UserAgentCore {
    /** Configuration. */
    configuration: UserAgentCoreConfiguration;
    /** Delegate. */
    delegate: UserAgentCoreDelegate;
    /** Dialogs. */
    dialogs: Map<string, Dialog>;
    /** Subscribers. */
    subscribers: Map<string, SubscribeUserAgentClient>;
    /** UACs. */
    userAgentClients: Map<string, UserAgentClient>;
    /** UASs. */
    userAgentServers: Map<string, UserAgentServer>;
    private logger;
    /**
     * Constructor.
     * @param configuration - Configuration.
     * @param delegate - Delegate.
     */
    constructor(configuration: UserAgentCoreConfiguration, delegate?: UserAgentCoreDelegate);
    /** Destructor. */
    dispose(): void;
    /** Reset. */
    reset(): void;
    /** Logger factory. */
    get loggerFactory(): LoggerFactory;
    /** Transport. */
    get transport(): Transport;
    /**
     * Send INVITE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    invite(request: OutgoingRequestMessage, delegate?: OutgoingInviteRequestDelegate): OutgoingInviteRequest;
    /**
     * Send MESSAGE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    message(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingMessageRequest;
    /**
     * Send PUBLISH.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    publish(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingPublishRequest;
    /**
     * Send REGISTER.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    register(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingRegisterRequest;
    /**
     * Send SUBSCRIBE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    subscribe(request: OutgoingRequestMessage, delegate?: OutgoingSubscribeRequestDelegate): OutgoingSubscribeRequest;
    /**
     * Send a request.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
    request(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingRequest;
    /**
     * Outgoing request message factory function.
     * @param method - Method.
     * @param requestURI - Request-URI.
     * @param fromURI - From URI.
     * @param toURI - To URI.
     * @param options - Request options.
     * @param extraHeaders - Extra headers to add.
     * @param body - Message body.
     */
    makeOutgoingRequestMessage(method: string, requestURI: URI, fromURI: URI, toURI: URI, options: OutgoingRequestMessageOptions, extraHeaders?: Array<string>, body?: Body): OutgoingRequestMessage;
    /**
     * Handle an incoming request message from the transport.
     * @param message - Incoming request message from transport layer.
     */
    receiveIncomingRequestFromTransport(message: IncomingRequestMessage): void;
    /**
     * Handle an incoming response message from the transport.
     * @param message - Incoming response message from transport layer.
     */
    receiveIncomingResponseFromTransport(message: IncomingResponseMessage): void;
    /**
     * A stateless UAS is a UAS that does not maintain transaction state.
     * It replies to requests normally, but discards any state that would
     * ordinarily be retained by a UAS after a response has been sent.  If a
     * stateless UAS receives a retransmission of a request, it regenerates
     * the response and re-sends it, just as if it were replying to the first
     * instance of the request. A UAS cannot be stateless unless the request
     * processing for that method would always result in the same response
     * if the requests are identical. This rules out stateless registrars,
     * for example.  Stateless UASs do not use a transaction layer; they
     * receive requests directly from the transport layer and send responses
     * directly to the transport layer.
     * https://tools.ietf.org/html/rfc3261#section-8.2.7
     * @param message - Incoming request message to reply to.
     * @param statusCode - Status code to reply with.
     */
    replyStateless(message: IncomingRequestMessage, options: ResponseOptions): OutgoingResponse;
    /**
     * In Section 18.2.1, replace the last paragraph with:
     *
     * Next, the server transport attempts to match the request to a
     * server transaction.  It does so using the matching rules described
     * in Section 17.2.3.  If a matching server transaction is found, the
     * request is passed to that transaction for processing.  If no match
     * is found, the request is passed to the core, which may decide to
     * construct a new server transaction for that request.
     * https://tools.ietf.org/html/rfc6026#section-8.10
     * @param message - Incoming request message from transport layer.
     */
    private receiveRequestFromTransport;
    /**
     * UAC and UAS procedures depend strongly on two factors.  First, based
     * on whether the request or response is inside or outside of a dialog,
     * and second, based on the method of a request.  Dialogs are discussed
     * thoroughly in Section 12; they represent a peer-to-peer relationship
     * between user agents and are established by specific SIP methods, such
     * as INVITE.
     * @param message - Incoming request message.
     */
    private receiveRequest;
    /**
     * Once a dialog has been established between two UAs, either of them
     * MAY initiate new transactions as needed within the dialog.  The UA
     * sending the request will take the UAC role for the transaction.  The
     * UA receiving the request will take the UAS role.  Note that these may
     * be different roles than the UAs held during the transaction that
     * established the dialog.
     * https://tools.ietf.org/html/rfc3261#section-12.2
     * @param message - Incoming request message.
     */
    private receiveInsideDialogRequest;
    /**
     * Assuming all of the checks in the previous subsections are passed,
     * the UAS processing becomes method-specific.
     *  https://tools.ietf.org/html/rfc3261#section-8.2.5
     * @param message - Incoming request message.
     */
    private receiveOutsideDialogRequest;
    /**
     * Responses are first processed by the transport layer and then passed
     * up to the transaction layer.  The transaction layer performs its
     * processing and then passes the response up to the TU.  The majority
     * of response processing in the TU is method specific.  However, there
     * are some general behaviors independent of the method.
     * https://tools.ietf.org/html/rfc3261#section-8.1.3
     * @param message - Incoming response message from transport layer.
     */
    private receiveResponseFromTransport;
}


/** Destructor. */
dispose(): void;


/** Reset. */
reset(): void;


/**
     * Send INVITE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
invite(request: OutgoingRequestMessage, delegate?: OutgoingInviteRequestDelegate): OutgoingInviteRequest;


/**
     * Send MESSAGE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
message(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingMessageRequest;


/**
     * Send PUBLISH.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
publish(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingPublishRequest;


/**
     * Send REGISTER.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
register(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingRegisterRequest;


/**
     * Send SUBSCRIBE.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
subscribe(request: OutgoingRequestMessage, delegate?: OutgoingSubscribeRequestDelegate): OutgoingSubscribeRequest;


/**
     * Send a request.
     * @param request - Outgoing request.
     * @param delegate - Request delegate.
     */
request(request: OutgoingRequestMessage, delegate?: OutgoingRequestDelegate): OutgoingRequest;


/**
     * Outgoing request message factory function.
     * @param method - Method.
     * @param requestURI - Request-URI.
     * @param fromURI - From URI.
     * @param toURI - To URI.
     * @param options - Request options.
     * @param extraHeaders - Extra headers to add.
     * @param body - Message body.
     */
makeOutgoingRequestMessage(method: string, requestURI: URI, fromURI: URI, toURI: URI, options: OutgoingRequestMessageOptions, extraHeaders?: Array<string>, body?: Body): OutgoingRequestMessage;


/**
     * Handle an incoming request message from the transport.
     * @param message - Incoming request message from transport layer.
     */
receiveIncomingRequestFromTransport(message: IncomingRequestMessage): void;


/**
     * Handle an incoming response message from the transport.
     * @param message - Incoming response message from transport layer.
     */
receiveIncomingResponseFromTransport(message: IncomingResponseMessage): void;


/**
     * A stateless UAS is a UAS that does not maintain transaction state.
     * It replies to requests normally, but discards any state that would
     * ordinarily be retained by a UAS after a response has been sent.  If a
     * stateless UAS receives a retransmission of a request, it regenerates
     * the response and re-sends it, just as if it were replying to the first
     * instance of the request. A UAS cannot be stateless unless the request
     * processing for that method would always result in the same response
     * if the requests are identical. This rules out stateless registrars,
     * for example.  Stateless UASs do not use a transaction layer; they
     * receive requests directly from the transport layer and send responses
     * directly to the transport layer.
     * https://tools.ietf.org/html/rfc3261#section-8.2.7
     * @param message - Incoming request message to reply to.
     * @param statusCode - Status code to reply with.
     */
replyStateless(message: IncomingRequestMessage, options: ResponseOptions): OutgoingResponse;


@Component({
  selector: 'datatable-row-wrapper',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div *ngIf="groupHeader && groupHeader.template" class="datatable-group-header" [ngStyle]="getGroupHeaderStyle()">
      <ng-template
        *ngIf="groupHeader && groupHeader.template"
        [ngTemplateOutlet]="groupHeader.template"
        [ngTemplateOutletContext]="groupContext"
      >
      </ng-template>
    </div>
    <ng-content *ngIf="(groupHeader && groupHeader.template && expanded) || (!groupHeader || !groupHeader.template)">
    </ng-content>
    <div
      *ngIf="rowDetail && rowDetail.template && expanded"
      [style.height.px]="detailRowHeight"
      class="datatable-row-detail"
    >
      <ng-template
        *ngIf="rowDetail && rowDetail.template"
        [ngTemplateOutlet]="rowDetail.template"
        [ngTemplateOutletContext]="rowContext"
      >
      </ng-template>
    </div>
  `,
  host: {
    class: 'datatable-row-wrapper'
  }
})
export class DataTableRowWrapperComponent implements OnChanges {
  @Input() innerWidth: number;
  @Input() rowDetail: any;
  @Input() groupHeader: any;
  @Input() offsetX: number;
  @Input() detailRowHeight: any;
  @Input() row: any;
  @Input() groupedRows: any;
  @Output() rowContextmenu = new EventEmitter<{ event: MouseEvent; row: any }>(false);

  @Input() set rowIndex(val: number) {
    this._rowIndex = val;
    this.rowContext.rowIndex = val;
    this.groupContext.rowIndex = val;
    this.cd.markForCheck();
  }

  get rowIndex(): number {
    return this._rowIndex;
  }

  @Input() set expanded(val: boolean) {
    this._expanded = val;
    this.groupContext.expanded = val;
    this.rowContext.expanded = val;
    this.cd.markForCheck();
  }

  get expanded(): boolean {
    return this._expanded;
  }

  groupContext: any = {
    group: this.row,
    expanded: this.expanded,
    rowIndex: this.rowIndex
  };

  rowContext: any = {
    row: this.row,
    expanded: this.expanded,
    rowIndex: this.rowIndex
  };

  private _expanded: boolean = false;
  private _rowIndex: number;

  constructor(private cd: ChangeDetectorRef) {
  }

  ngOnChanges({ row: rowChange }: SimpleChanges): void {
    if (rowChange) {
      this.rowContext.row = this.row;
      this.groupContext.group = this.row;
      this.cd.markForCheck();
    }
  }

  @HostListener('contextmenu', ['$event'])
  onContextmenu($event: MouseEvent): void {
    this.rowContextmenu.emit({ event: $event, row: this.row });
  }

  getGroupHeaderStyle(): any {
    const styles = {};

    styles['transform'] = 'translate3d(' + this.offsetX + 'px, 0px, 0px)';
    styles['backface-visibility'] = 'hidden';
    styles['width'] = this.innerWidth;

    return styles;
  }
}


ngOnChanges({ row: rowChange }: SimpleChanges): void {
    if (rowChange) {
      this.rowContext.row = this.row;
      this.groupContext.group = this.row;
      this.cd.markForCheck();
    }
  }


@HostListener('contextmenu', ['$event'])
  onContextmenu($event: MouseEvent): void {
    this.rowContextmenu.emit({ event: $event, row: this.row });
  }


getGroupHeaderStyle(): any {
    const styles = {};

    styles['transform'] = 'translate3d(' + this.offsetX + 'px, 0px, 0px)';
    styles['backface-visibility'] = 'hidden';
    styles['width'] = this.innerWidth;

    return styles;
  }


() => {
  actions.operators = {
    ...actions.operators,
    getCSV: jest.fn(),
    getResource: jest.fn(),
  };
  const mockDispatch = jest.fn(res => res);
  spyOnUseDispatch = jest.spyOn(ReactRedux, "useDispatch").mockReturnValue(mockDispatch);
}


res => res


() => {
  actions.operators = { ...kubeaActions };
  spyOnUseDispatch.mockRestore();
}


() => {
  const props = { ...defaultProps, cluster: "other-cluster" };
  const wrapper = mountWrapper(defaultStore, <OperatorInstanceUpdateForm {...props} />);
  expect(wrapper.find(OperatorNotSupported)).toExist();
}


() => {
  const getResource = jest.fn();
  const getCSV = jest.fn();
  actions.operators.getResource = getResource;
  actions.operators.getCSV = getCSV;
  mountWrapper(defaultStore, <OperatorInstanceUpdateForm {...defaultProps} />);
  expect(getCSV).toHaveBeenCalledWith(
    defaultProps.cluster,
    defaultProps.namespace,
    defaultProps.csvName,
  );
  expect(getResource).toHaveBeenCalledWith(
    defaultProps.cluster,
    defaultProps.namespace,
    defaultProps.csvName,
    defaultProps.crdName,
    defaultProps.resourceName,
  );
}


() => {
  const wrapper = mountWrapper(
    getStore({
      operators: {
        resource: defaultResource,
        csv: defaultCSV,
      },
    }),
    <OperatorInstanceUpdateForm {...defaultProps} />,
  );
  expect(wrapper.find(OperatorInstanceFormBody).props()).toMatchObject({
    defaultValues: "kind: Foo\napiVersion: v1\n",
    deployedValues: "kind: Foo\napiVersion: v1\nmetadata:\n  name: my-foo\n",
  });
}


() => {
  const wrapper = mountWrapper(defaultStore, <OperatorInstanceUpdateForm {...defaultProps} />);
  expect(wrapper.find(Alert)).toIncludeText("Resource my-foo not found");
}


() => {
  const updateResource = jest.fn();
  actions.operators.updateResource = updateResource;
  const wrapper = mountWrapper(
    getStore({
      operators: {
        resource: defaultResource,
        csv: defaultCSV,
      },
    }),
    <OperatorInstanceUpdateForm {...defaultProps} />,
  );

  const form = wrapper.find("form");
  form.simulate("submit", { preventDefault: jest.fn() });

  expect(updateResource).toHaveBeenCalledWith(
    defaultProps.cluster,
    defaultProps.namespace,
    defaultResource.apiVersion,
    defaultProps.crdName,
    defaultProps.resourceName,
    defaultResource,
  );
}


(howMany: number, word: string) => {
  return `${howMany} ${pluralize(word, howMany)}`;
}


@Injectable()
export class AuthService {
    constructor(private readonly configService: ConfigService) {
        const mongoConStr = this.configService.get<string>('MONGODB_WRITE_CONNECTHION_STRING')
        console.log(mongoConStr)
    }
}


@Injectable()
export class StudentService {
    products = [
        { id: 1, name: 'One Plus 7', price: 48000 },
        { id: 2, name: 'I Phone X', price: 64999 },
      ];
    constructor(@InjectModel('Student') private studentRepository:Model<student>){}
    getData()
    {
        return this.products;
    }

    async addCustomer(createCustomerDTO): Promise<student> {
        const newCustomer = await this.studentRepository.create(createCustomerDTO)
        return newCustomer;
    }
}


getData()
    {
        return this.products;
    }


async addCustomer(createCustomerDTO): Promise<student> {
        const newCustomer = await this.studentRepository.create(createCustomerDTO)
        return newCustomer;
    }


/**
 *
Creates an application, optionally including an AWS SAM file to create the first application version in the same call.

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

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

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

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

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

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

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

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


export interface CreateApplicationCommandInput extends CreateApplicationRequest {}


export interface CreateApplicationCommandOutput extends CreateApplicationResponse, __MetadataBearer {}


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

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

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


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


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


export class AnnouncementsMongoDbPersistence
    extends IdentifiableMongoDbPersistence<AnnouncementV1, string>
    implements IAnnouncementsPersistence {

    constructor() {
        super('announcements');
    }

    private composeFilter(filter: FilterParams): any {
        filter = filter || new FilterParams();

        let criteria = [];

        let search = filter.getAsNullableString('search');
        if (search != null) {
            let searchRegex = new RegExp(search, "i");
            let searchCriteria = [];
            searchCriteria.push({ 'title.en': { $regex: searchRegex } });
            searchCriteria.push({ 'title.sp': { $regex: searchRegex } });
            searchCriteria.push({ 'title.fr': { $regex: searchRegex } });
            searchCriteria.push({ 'title.de': { $regex: searchRegex } });
            searchCriteria.push({ 'title.ru': { $regex: searchRegex } });
            searchCriteria.push({ 'content.en': { $regex: searchRegex } });
            searchCriteria.push({ 'content.sp': { $regex: searchRegex } });
            searchCriteria.push({ 'content.fr': { $regex: searchRegex } });
            searchCriteria.push({ 'content.de': { $regex: searchRegex } });
            searchCriteria.push({ 'content.ru': { $regex: searchRegex } });
            searchCriteria.push({ 'location.name': { $regex: searchRegex } });
            searchCriteria.push({ 'creator.name': { $regex: searchRegex } });
            criteria.push({ $or: searchCriteria });
        }

        let id = filter.getAsNullableString('id');
        if (id != null)
            criteria.push({ _id: id });

        let category = filter.getAsNullableString('category');
        if (category != null)
            criteria.push({ category: category });

        let app = filter.getAsNullableString('app');
        if (app != null)
            criteria.push({ app: app });

        let status = filter.getAsNullableString('status');
        if (status != null)
            criteria.push({ status: status });

        // Search by tags
        let tags = filter.getAsObject('tags');
        if (tags) {
            let searchTags = TagsProcessor.compressTags([tags]);
            criteria.push({ all_tags: { $in: searchTags } });
        }

        let fromCreateTime = filter.getAsNullableDateTime('from_create_time');
        if (fromCreateTime != null)
            criteria.push({ create_time: { $gte: fromCreateTime } });

        let toCreateTime = filter.getAsNullableDateTime('to_create_time');
        if (toCreateTime != null)
            criteria.push({ create_time: { $lt: toCreateTime } });

        return criteria.length > 0 ? { $and: criteria } : {};
    }

    public getPageByFilter(correlationId: string, filter: FilterParams, paging: PagingParams, callback: any) {
        super.getPageByFilter(correlationId, this.composeFilter(filter), paging, '-create_time', null, callback);
    }

    public getOneRandom(correlationId: string, filter: FilterParams,
        callback: (err: any, item: AnnouncementV1) => void): void {
        super.getOneRandom(correlationId, this.composeFilter(filter), callback);
    }

}


private composeFilter(filter: FilterParams): any {
        filter = filter || new FilterParams();

        let criteria = [];

        let search = filter.getAsNullableString('search');
        if (search != null) {
            let searchRegex = new RegExp(search, "i");
            let searchCriteria = [];
            searchCriteria.push({ 'title.en': { $regex: searchRegex } });
            searchCriteria.push({ 'title.sp': { $regex: searchRegex } });
            searchCriteria.push({ 'title.fr': { $regex: searchRegex } });
            searchCriteria.push({ 'title.de': { $regex: searchRegex } });
            searchCriteria.push({ 'title.ru': { $regex: searchRegex } });
            searchCriteria.push({ 'content.en': { $regex: searchRegex } });
            searchCriteria.push({ 'content.sp': { $regex: searchRegex } });
            searchCriteria.push({ 'content.fr': { $regex: searchRegex } });
            searchCriteria.push({ 'content.de': { $regex: searchRegex } });
            searchCriteria.push({ 'content.ru': { $regex: searchRegex } });
            searchCriteria.push({ 'location.name': { $regex: searchRegex } });
            searchCriteria.push({ 'creator.name': { $regex: searchRegex } });
            criteria.push({ $or: searchCriteria });
        }

        let id = filter.getAsNullableString('id');
        if (id != null)
            criteria.push({ _id: id });

        let category = filter.getAsNullableString('category');
        if (category != null)
            criteria.push({ category: category });

        let app = filter.getAsNullableString('app');
        if (app != null)
            criteria.push({ app: app });

        let status = filter.getAsNullableString('status');
        if (status != null)
            criteria.push({ status: status });

        // Search by tags
        let tags = filter.getAsObject('tags');
        if (tags) {
            let searchTags = TagsProcessor.compressTags([tags]);
            criteria.push({ all_tags: { $in: searchTags } });
        }

        let fromCreateTime = filter.getAsNullableDateTime('from_create_time');
        if (fromCreateTime != null)
            criteria.push({ create_time: { $gte: fromCreateTime } });

        let toCreateTime = filter.getAsNullableDateTime('to_create_time');
        if (toCreateTime != null)
            criteria.push({ create_time: { $lt: toCreateTime } });

        return criteria.length > 0 ? { $and: criteria } : {};
    }


public getPageByFilter(correlationId: string, filter: FilterParams, paging: PagingParams, callback: any) {
        super.getPageByFilter(correlationId, this.composeFilter(filter), paging, '-create_time', null, callback);
    }


public getOneRandom(correlationId: string, filter: FilterParams,
        callback: (err: any, item: AnnouncementV1) => void): void {
        super.getOneRandom(correlationId, this.composeFilter(filter), callback);
    }


@Component({
  template: `<div
                    style.color="a{{one}}b"
                    style.border="a{{one}}b"
                    [class.apple]="yesToApple"
                    [style.transition]="transition"
                    [class.orange]="yesToOrange"
                    [style.width]="width"
                    style.height="a{{one}}b"
                    style.top="a{{one}}b"></div>`
})
export class MyComponent {
  one = '';
  transition = 'all 1337ms ease';
  width = '42px';
  yesToApple = true;
  yesToOrange = true;
}


export default class Shell extends Component<ShellProps, any> {
    static Branding: ComponentType<ShellCommonProps>;
    static Action: ComponentType<ShellCommonProps>;
    static MultiTask: ComponentType<ShellCommonProps>;
    static AppBar: ComponentType<ShellCommonProps>;
    static Content: ComponentType<ShellCommonProps>;
    static Footer: ComponentType<ShellCommonProps>;
    static ToolDockItem: ComponentType<ShellCommonProps>;

    static Navigation: ComponentType<ShellNavigationProps>;
    static LocalNavigation: ComponentType<ShellLocalNavigationProps>;
    static Ancillary: ComponentType<ShellAncillaryProps>;
    static ToolDock: ComponentType<ShellToolDockProps>;
}


export interface ShellProps extends HTMLAttributes<HTMLElement>, CommonProps {
    /**
     * 设备类型，针对不同的设备类型组件做出对应的响应式变化
     */
    device?: 'tablet' | 'desktop' | 'phone';
    type?: 'light' | 'dark' | 'brand';
    fixedHeader?: boolean;
}


export interface ShellCommonProps extends HTMLAttributes<HTMLElement>, CommonProps {

}


export interface ShellNavigationProps extends ShellCommonProps {
    collapse?: boolean;
    direction?: 'hoz' | 'ver';
    align?: 'left' | 'right' | 'center';
    fixed?: boolean;
    onCollapseChange?: (collapse?: boolean) => {};
}


export interface ShellLocalNavigationProps extends ShellCommonProps {
    collapse?: boolean;
    onCollapseChange?: (collapse?: boolean) => {};
}


export interface ShellToolDockProps extends ShellCommonProps {
    collapse?: boolean;
    fixed?: boolean;
    onCollapseChange?: (collapse?: boolean) => {};
}


export interface ShellAncillaryProps extends ShellCommonProps {
    collapse?: boolean;
    onCollapseChange?: (collapse?: boolean) => {};
}


(filename: string) =>
    sqlBase.__dangerous__rawValue(readFileSync(filename, 'utf8'))


export interface SQL extends SQLBase {
  file(filename: string): SQLQuery;
}


/**
 * Acquires an item for the specified type and ignites it
 */
export default class AcquireItemAndIgnite extends Objective {

    constructor(private readonly itemType: ItemType) {
        super();
    }

    public getIdentifier(): string {
        return `AcquireItemAndIgnite:${ItemType[this.itemType]}`;
    }

    public getStatus(): string | undefined {
        return `Acquiring ${Translation.nameOf(Dictionary.Item, this.itemType).getString()} and igniting it`;
    }

    public override canIncludeContextHashCode(): boolean {
        return true;
    }

    public override shouldIncludeContextHashCode(context: Context): boolean {
        return context.isReservedItemType(this.itemType);
    }

    public async execute(context: Context): Promise<ObjectiveExecutionResult> {
        const objectives: IObjective[] = [];

        const itemToIgnite = itemUtilities.getItemInInventory(context, this.itemType);
        if (itemToIgnite === undefined) {
            objectives.push(new AcquireItem(this.itemType).setContextDataKey(this.getHashCode()));
        }

        objectives.push(new IgniteItem(itemToIgnite));

        return objectives;
    }

}


public getIdentifier(): string {
        return `AcquireItemAndIgnite:${ItemType[this.itemType]}`;
    }


public getStatus(): string | undefined {
        return `Acquiring ${Translation.nameOf(Dictionary.Item, this.itemType).getString()} and igniting it`;
    }


public override canIncludeContextHashCode(): boolean {
        return true;
    }


public override shouldIncludeContextHashCode(context: Context): boolean {
        return context.isReservedItemType(this.itemType);
    }


public async execute(context: Context): Promise<ObjectiveExecutionResult> {
        const objectives: IObjective[] = [];

        const itemToIgnite = itemUtilities.getItemInInventory(context, this.itemType);
        if (itemToIgnite === undefined) {
            objectives.push(new AcquireItem(this.itemType).setContextDataKey(this.getHashCode()));
        }

        objectives.push(new IgniteItem(itemToIgnite));

        return objectives;
    }


export interface IScatterPlotProps {
  index: number;
  data: ILine[];
  axesScaleType?: IAxesScaleState;
  chartTitle?: IChartTitle;
  displayOutliers?: boolean;
  highlightMode?: HighlightEnum;
  zoom?: IChartZoom;
  onZoomChange?: (zoom: Partial<IChartZoom>) => void;
  syncHoverState: (args: ISyncHoverStateArgs) => void;
}


public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `CREATE TABLE "notification" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "userId" integer NOT NULL, "isRead" boolean, "data" jsonb NOT NULL, CONSTRAINT "PK_705b6c7cdf9b2c2ff7ac7872cb7" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "token" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "lastActiveAt" TIMESTAMP WITH TIME ZONE NOT NULL, "type" character varying NOT NULL, "value" character varying NOT NULL, "maxAge" character varying NOT NULL, "userId" integer NOT NULL, CONSTRAINT "UQ_1096f931c2f2d9bf9c3c858d630" UNIQUE ("value"), CONSTRAINT "PK_82fae97f905930df5d62a702fc9" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "node" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "slug" character varying NOT NULL, "name" character varying NOT NULL, "description" character varying NOT NULL, "image" character varying, CONSTRAINT "UQ_e9c89f1e059861b0c4f897008d5" UNIQUE ("slug"), CONSTRAINT "PK_8c8caf5f29d25264abe9eaf94dd" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "topic" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "title" character varying NOT NULL, "content" character varying NOT NULL, "authorId" integer NOT NULL, "nodeId" integer NOT NULL, CONSTRAINT "PK_33aa4ecb4e4f20aa0157ea7ef61" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "user_topic_like" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "userId" integer NOT NULL, "topicId" integer NOT NULL, CONSTRAINT "PK_0151dd46f30684c6fe1d0d01061" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "user" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "username" character varying NOT NULL, "email" character varying, "avatar" character varying, "bio" character varying, "github" character varying, "twitter" character varying, "website" character varying, "githubUserId" character varying, "googleUserId" character varying, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "UQ_c445acb0ecd41969b8a0955e13a" UNIQUE ("githubUserId"), CONSTRAINT "UQ_3a6d6e65d5678fd41783302bbb2" UNIQUE ("googleUserId"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `CREATE TABLE "comment" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "content" character varying NOT NULL, "topicId" integer NOT NULL, "authorId" integer NOT NULL, "parentId" integer, CONSTRAINT "PK_0b0e4bbc8415ec426f87f3a88e2" PRIMARY KEY ("id"))`,
    )
    await queryRunner.query(
      `ALTER TABLE "notification" ADD CONSTRAINT "FK_1ced25315eb974b73391fb1c81b" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "token" ADD CONSTRAINT "FK_94f168faad896c0786646fa3d4a" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "topic" ADD CONSTRAINT "FK_5bc4974a5ec06dd10c348bdb5ec" FOREIGN KEY ("authorId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "topic" ADD CONSTRAINT "FK_b6f2a8821db533df60c26491470" FOREIGN KEY ("nodeId") REFERENCES "node"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "user_topic_like" ADD CONSTRAINT "FK_d4a2527fbbba34e21b1079de424" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "user_topic_like" ADD CONSTRAINT "FK_bee938ba73f54fe875fa83573d2" FOREIGN KEY ("topicId") REFERENCES "topic"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "comment" ADD CONSTRAINT "FK_b57a5333a16e092c662bd8ff5fe" FOREIGN KEY ("topicId") REFERENCES "topic"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "comment" ADD CONSTRAINT "FK_276779da446413a0d79598d4fbd" FOREIGN KEY ("authorId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
    await queryRunner.query(
      `ALTER TABLE "comment" ADD CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
    )
  }


public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      `ALTER TABLE "comment" DROP CONSTRAINT "FK_e3aebe2bd1c53467a07109be596"`,
    )
    await queryRunner.query(
      `ALTER TABLE "comment" DROP CONSTRAINT "FK_276779da446413a0d79598d4fbd"`,
    )
    await queryRunner.query(
      `ALTER TABLE "comment" DROP CONSTRAINT "FK_b57a5333a16e092c662bd8ff5fe"`,
    )
    await queryRunner.query(
      `ALTER TABLE "user_topic_like" DROP CONSTRAINT "FK_bee938ba73f54fe875fa83573d2"`,
    )
    await queryRunner.query(
      `ALTER TABLE "user_topic_like" DROP CONSTRAINT "FK_d4a2527fbbba34e21b1079de424"`,
    )
    await queryRunner.query(
      `ALTER TABLE "topic" DROP CONSTRAINT "FK_b6f2a8821db533df60c26491470"`,
    )
    await queryRunner.query(
      `ALTER TABLE "topic" DROP CONSTRAINT "FK_5bc4974a5ec06dd10c348bdb5ec"`,
    )
    await queryRunner.query(
      `ALTER TABLE "token" DROP CONSTRAINT "FK_94f168faad896c0786646fa3d4a"`,
    )
    await queryRunner.query(
      `ALTER TABLE "notification" DROP CONSTRAINT "FK_1ced25315eb974b73391fb1c81b"`,
    )
    await queryRunner.query(`DROP TABLE "comment"`)
    await queryRunner.query(`DROP TABLE "user"`)
    await queryRunner.query(`DROP TABLE "user_topic_like"`)
    await queryRunner.query(`DROP TABLE "topic"`)
    await queryRunner.query(`DROP TABLE "node"`)
    await queryRunner.query(`DROP TABLE "token"`)
    await queryRunner.query(`DROP TABLE "notification"`)
  }


() => {
      this.inputEventWasTriggered = true;
    }


export class ContentEditableTestSetup implements AdapterTestSetup {
  name = 'ContentEditableAdapter';
  inputFormat = 'HTML';
  editorElement = `<div id="editorId" style="height: ${EDITOR_HEIGHT}px; overflow-x: scroll; position: relative; font-size: 10px">initial text</div>`;
  inputEventWasTriggered?: boolean;

  init() {
    return Promise.resolve(new ContentEditableAdapter({editorId: 'editorId'}));
  }

  setEditorContent(html: string, done: DoneCallback) {
    $('#editorId').html(html).on('input', () => {
      this.inputEventWasTriggered = true;
    });
    done();
  }

  remove() {
    $('#editorId').remove();
  }

  getSelectedText(): string {
    return window.getSelection()!.toString();
  }
}


init() {
    return Promise.resolve(new ContentEditableAdapter({editorId: 'editorId'}));
  }


setEditorContent(html: string, done: DoneCallback) {
    $('#editorId').html(html).on('input', () => {
      this.inputEventWasTriggered = true;
    });
    done();
  }


remove() {
    $('#editorId').remove();
  }


getSelectedText(): string {
    return window.getSelection()!.toString();
  }


/**
 * This turns a node path into a valid state machine name, to try and improve
 * the StepFunction's AWS console experience while minimizing the risk for
 * collisons.
 */
function stateMachineNameFrom(nodePath: string): string {
  // Poor man's replace all...
  return nodePath.split(/[^a-z0-9+!@.()=_'-]+/i).join('.');
}


/**
 * A StepFunctions State Machine to reprocess every currently indexed package
 * through the ingestion function. This should not be frequently required, but
 * can come in handy at times.
 *
 * For more information, refer to the runbook at
 * https://github.com/cdklabs/construct-hub/blob/main/docs/operator-runbook.md
 */
class ReprocessIngestionWorkflow extends Construct {
  public readonly stateMachine: StateMachine;

  public constructor(scope: Construct, id: string, props: ReprocessIngestionWorkflowProps) {
    super(scope, id);

    const lambdaFunction = new ReIngest(this, 'Function', {
      architecture: gravitonLambdaIfAvailable(this),
      description: '[ConstructHub/Ingestion/ReIngest] The function used to reprocess packages through ingestion',
      environment: { BUCKET_NAME: props.bucket.bucketName, QUEUE_URL: props.queue.queueUrl },
      memorySize: 10_240,
      tracing: Tracing.ACTIVE,
      timeout: Duration.minutes(3),
    });

    props.queue.grantSendMessages(lambdaFunction);
    props.bucket.grantRead(lambdaFunction, `${STORAGE_KEY_PREFIX}*${METADATA_KEY_SUFFIX}`);
    props.bucket.grantRead(lambdaFunction, `${STORAGE_KEY_PREFIX}*${PACKAGE_KEY_SUFFIX}`);

    // Need to physical-name the state machine so it can self-invoke.
    const stateMachineName = stateMachineNameFrom(this.node.path);

    const listBucket = new Choice(this, 'Has a ContinuationToken?')
      .when(Condition.isPresent('$.ContinuationToken'),
        new CallAwsService(this, 'S3.ListObjectsV2(NextPage)', {
          service: 's3',
          action: 'listObjectsV2',
          iamAction: 's3:ListBucket',
          iamResources: [props.bucket.bucketArn],
          parameters: {
            Bucket: props.bucket.bucketName,
            ContinuationToken: JsonPath.stringAt('$.ContinuationToken'),
            Prefix: STORAGE_KEY_PREFIX,
          },
          resultPath: '$.response',
        }).addRetry({ errors: ['S3.SdkClientException'] }))
      .otherwise(new CallAwsService(this, 'S3.ListObjectsV2(FirstPage)', {
        service: 's3',
        action: 'listObjectsV2',
        iamAction: 's3:ListBucket',
        iamResources: [props.bucket.bucketArn],
        parameters: {
          Bucket: props.bucket.bucketName,
          Prefix: STORAGE_KEY_PREFIX,
        },
        resultPath: '$.response',
      }).addRetry({ errors: ['S3.SdkClientException'] })).afterwards();

    const process = new Map(this, 'Process Result', {
      itemsPath: '$.response.Contents',
      resultPath: JsonPath.DISCARD,
    }).iterator(
      new Choice(this, 'Is metadata object?')
        .when(
          Condition.stringMatches('$.Key', `*${METADATA_KEY_SUFFIX}`),
          new LambdaInvoke(this, 'Send for reprocessing', { lambdaFunction })
            // Ample retries here... We should never fail because of throttling....
            .addRetry({ errors: ['Lambda.TooManyRequestsException'], backoffRate: 1.1, interval: Duration.minutes(1), maxAttempts: 30 }),
        )
        .otherwise(new Succeed(this, 'Nothing to do')),
    );

    listBucket.next(
      new Choice(this, 'Is there more?')
        .when(
          Condition.isPresent('$.response.NextContinuationToken'),
          new StepFunctionsStartExecution(this, 'Continue as new', {
            associateWithParent: true,
            stateMachine: StateMachine.fromStateMachineArn(this, 'ThisStateMachine', Stack.of(this).formatArn({
              arnFormat: ArnFormat.COLON_RESOURCE_NAME,
              service: 'states',
              resource: 'stateMachine',
              resourceName: stateMachineName,
            })),
            input: TaskInput.fromObject({ ContinuationToken: JsonPath.stringAt('$.response.NextContinuationToken') }),
            integrationPattern: IntegrationPattern.REQUEST_RESPONSE,
            resultPath: JsonPath.DISCARD,
          }).addRetry({ errors: ['StepFunctions.ExecutionLimitExceeded'] }),
        ).afterwards({ includeOtherwise: true })
        .next(process),
    );

    this.stateMachine = new StateMachine(this, 'StateMachine', {
      definition: listBucket,
      stateMachineName,
      timeout: Duration.hours(1),
    });

    props.bucket.grantRead(this.stateMachine);
    props.queue.grantSendMessages(this.stateMachine);
  }
}


export interface IngestionProps {
  /**
   * The bucket in which ingested objects are due to be inserted.
   */
  readonly bucket: IBucket;

  /**
   * The CodeArtifact repository to which packages should be published. This is
   * the ConstructHub internal CodeArtifact repository, if one exists.
   */
  readonly codeArtifact?: Repository;

  /**
   * The monitoring handler to register alarms with.
   */
  readonly monitoring: Monitoring;

  /**
   * The backend orchestration to invoke once the package metadata has been
   * successfully registered.
   */
  readonly orchestration: Orchestration;

  /**
   * How long to retain the CloudWatch logs.
   *
   * @default RetentionDays.TEN_YEARS
   */
  readonly logRetention?: RetentionDays;

  /**
   * Configuration for custom package page links.
   */
  readonly packageLinks?: PackageLinkConfig[];

  /**
   * Serialized configuration for custom package tags.
   */
  readonly packageTags?: PackageTagConfig[];

  /**
   * How frequently all packages should get fully reprocessed.
   *
   * See the operator runbook for more information about reprocessing.
   * @see https://github.com/cdklabs/construct-hub/blob/main/docs/operator-runbook.md
   *
   * @default - never
   */
  readonly reprocessFrequency?: Duration;
}


interface ReprocessIngestionWorkflowProps {
  readonly bucket: IBucket;
  readonly queue: IQueue;
}


public metricFoundLicenseFile(opts?: MetricOptions): Metric {
    return new Metric({
      period: Duration.minutes(5),
      statistic: Statistic.SUM,
      ...opts,
      metricName: MetricName.FOUND_LICENSE_FILE,
      namespace: METRICS_NAMESPACE,
    });
  }


public metricIneligibleLicense(opts?: MetricOptions): Metric {
    return new Metric({
      period: Duration.minutes(5),
      statistic: Statistic.SUM,
      ...opts,
      metricName: MetricName.INELIGIBLE_LICENSE,
      namespace: METRICS_NAMESPACE,
    });
  }


public metricInvalidAssembly(opts?: MetricOptions): Metric {
    return new Metric({
      period: Duration.minutes(5),
      statistic: Statistic.SUM,
      ...opts,
      metricName: MetricName.INVALID_ASSEMBLY,
      namespace: METRICS_NAMESPACE,
    });
  }


public metricInvalidTarball(opts?: MetricOptions): Metric {
    return new Metric({
      period: Duration.minutes(5),
      statistic: Statistic.SUM,
      ...opts,
      metricName: MetricName.INVALID_TARBALL,
      namespace: METRICS_NAMESPACE,
    });
  }


/**
   * This metrics is the total count of packages that were rejected due to
   * mismatched identity (name, version, license) between the `package.json`
   * file and te `.jsii` attribute.
   */
public metricMismatchedIdentityRejections(opts?: MetricOptions): Metric {
    return new Metric({
      period: Duration.minutes(5),
      statistic: Statistic.SUM,
      ...opts,
      metricName: MetricName.MISMATCHED_IDENTITY_REJECTIONS,
      namespace: METRICS_NAMESPACE,
    });
  }


() => {
  test('click on closed', () => {
    const mockToggle = jest.fn();
    const view = mount(
      <SelectToggle id="Select Toggle" onToggle={mockToggle} parentRef={{ current: document.createElement('div') }}>
        Select
      </SelectToggle>
    );

    view
      .find('button')
      .first()
      .simulate('click');
    expect(mockToggle.mock.calls[0][0]).toBe(true);
  }


() => {
    const mockToggle = jest.fn();
    const view = mount(
      <SelectToggle id="Select Toggle" onToggle={mockToggle} parentRef={{ current: document.createElement('div') }}


() => {
    const mockToggle = jest.fn();
    const view = mount(
      <SelectToggle
        id="Select Toggle"
        onToggle={mockToggle}
        isOpen
        parentRef={{ current: document.createElement('div') }}


() => {
    const map = {} as any;
    document.addEventListener = jest.fn((event, cb) => {
      map[event] = cb;
    });
    const mockToggle = jest.fn();
    mount(
      <SelectToggle
        id="Select Toggle"
        onToggle={mockToggle}
        isOpen
        parentRef={{ current: document.createElement('div') }}


(event, cb) => {
      map[event] = cb;
    }


() => {
    const map = {} as any;
    document.addEventListener = jest.fn((event, cb) => {
      map[event] = cb;
    });
    document.removeEventListener = jest.fn((event, cb) => {
      if (map[event] === cb) {
        map[event] = () => {};
      }
    });
    const mockToggle = jest.fn();
    const view = mount(
      <SelectToggle
        id="Select Toggle"
        onToggle={mockToggle}
        isOpen
        parentRef={{ current: document.createElement('div') }}


(event, cb) => {
      if (map[event] === cb) {
        map[event] = () => {};
      }
    }


() => {
  test('active', () => {
    const view = mount(
      <SelectToggle id="Select Toggle" isActive parentRef={{ current: document.createElement('div') }}>
        Select
      </SelectToggle>
    );
    expect(view).toMatchSnapshot();
  }


() => {
    const view = mount(
      <SelectToggle id="Select Toggle" isActive parentRef={{ current: document.createElement('div') }}


export type CacheValue = number | Record<string, any>;


type CacheStore = {
  get(key: string): Promise<CacheValue | null>;

  all(): Promise<CacheValue[]>;

  put(key: string, value: CacheValue, minutes: number): Promise<void>;

  forget(key: string): Promise<void>;

  flush(): Promise<void>;

  getPrefix(): string;
};


@Controller('/api/v1')
export class ApiV1PaymentController {
  constructor (
    private readonly accountsService: AccountsService
  ) {}

  @UseGuards(UserRequiredAuthGuard)
  @Post('add-payment-token')
  async handleAddPaymentToken (@Request() req, @Res() res: Response): Promise<any> {
    const account = await this.accountsService.findByOwnerEmail(req.user.email)

    if (account == null) {
      return res.json({
        statusCode: 400,
        error: 'Account not found'
      })
    }

    const methods = await this.accountsService.addPaymentsMethods(account.id, req.body)

    return res.json({
      statusCode: 200,
      message: methods
    })
  }
}


@UseGuards(UserRequiredAuthGuard)
  @Post('add-payment-token')
  async handleAddPaymentToken (@Request() req, @Res() res: Response): Promise<any> {
    const account = await this.accountsService.findByOwnerEmail(req.user.email)

    if (account == null) {
      return res.json({
        statusCode: 400,
        error: 'Account not found'
      })
    }

    const methods = await this.accountsService.addPaymentsMethods(account.id, req.body)

    return res.json({
      statusCode: 200,
      message: methods
    })
  }


() => {
  it('should render text when not wrapped with provider', () => {
    let App = () => (
      <>
        <Text>Foobar 3000</Text>
      </>
    );
    let { getByText } = render(<App />);
    expect(getByText('Foobar 3000')).toBeTruthy();
  }


() => {
    let App = () => (
      <>
        <Text>Foobar 3000</Text>
      </>


() => (
      <>
        <Text>Foobar


() => {
    let App = () => (
      <Provider skipFontsLoading>
        <Text>Foobar 3000</Text>
      </Provider>


() => (
      <Provider skipFontsLoading>
        <Text>Foobar


(err: Error, raw: Buffer) => {
      if (err) return cb(err)
      var account = new Account(raw)
      cb(null, account)
    }


(err: Error, account: Account) => {
        if (err) return cb(err)
        this._update(key, account, false, false)
        cb(null, account)
      }


val => {
      if (val) accountArr.push(val)
    }


(addressHex: string, done: any) => {
        var address = Buffer.from(addressHex, 'hex')
        this._lookupAccount(address, (err: Error, account: Account) => {
          if (err) return done(err)
          this._update(address, account, false, false)
          done()
        })
      }


(err: Error, account: Account) => {
          if (err) return done(err)
          this._update(address, account, false, false)
          done()
        }


() => next


(done: any) => {
        if (it.value && it.value.modified) {
          it.value.modified = false
          it.value.val = it.value.val.serialize()
          this._trie.put(Buffer.from(it.key, 'hex'), it.value.val, (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else if (it.value && it.value.deleted) {
          it.value.modified = false
          it.value.deleted = false
          it.value.val = new Account().serialize()
          this._trie.del(Buffer.from(it.key, 'hex'), (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else {
          next = it.hasNext
          it.next()
          asyncLib.nextTick(done)
        }
      }


(err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          }


/**
 * @ignore
 */
export default class Cache {
  _cache: any
  _checkpoints: any[]
  _trie: any

  constructor(trie: any) {
    this._cache = Tree()
    this._checkpoints = []
    this._trie = trie
  }

  /**
   * Puts account to cache under its address.
   * @param key - Address of account
   * @param val - Account
   */
  put(key: Buffer, val: Account, fromTrie: boolean = false): void {
    const modified = !fromTrie
    this._update(key, val, modified, false)
  }

  /**
   * Returns the queried account or an empty account.
   * @param key - Address of account
   */
  get(key: Buffer): Account {
    let account = this.lookup(key)
    if (!account) {
      account = new Account()
    }
    return account
  }

  /**
   * Returns the queried account or undefined.
   * @param key - Address of account
   */
  lookup(key: Buffer): Account | undefined {
    const keyStr = key.toString('hex')

    const it = this._cache.find(keyStr)
    if (it.node) {
      const account = new Account(it.value.val)
      return account
    }
  }

  /**
   * Looks up address in underlying trie.
   * @param address - Address of account
   * @param cb - Callback with params (err, account)
   */
  _lookupAccount(address: Buffer, cb: any): void {
    this._trie.get(address, (err: Error, raw: Buffer) => {
      if (err) return cb(err)
      var account = new Account(raw)
      cb(null, account)
    })
  }

  /**
   * Looks up address in cache, if not found, looks it up
   * in the underlying trie.
   * @param key - Address of account
   * @param cb - Callback with params (err, account)
   */
  getOrLoad(key: Buffer, cb: any): void {
    const account = this.lookup(key)
    if (account) {
      asyncLib.nextTick(cb, null, account)
    } else {
      this._lookupAccount(key, (err: Error, account: Account) => {
        if (err) return cb(err)
        this._update(key, account, false, false)
        cb(null, account)
      })
    }
  }

  /**
   * Warms cache by loading their respective account from trie
   * and putting them in cache.
   * @param addresses - Array of addresses
   * @param cb - Callback
   */
  warm(addresses: string[], cb: any): void {
    // shim till async supports iterators
    const accountArr: string[] = []
    addresses.forEach(val => {
      if (val) accountArr.push(val)
    })

    asyncLib.eachSeries(
      accountArr,
      (addressHex: string, done: any) => {
        var address = Buffer.from(addressHex, 'hex')
        this._lookupAccount(address, (err: Error, account: Account) => {
          if (err) return done(err)
          this._update(address, account, false, false)
          done()
        })
      },
      cb,
    )
  }

  /**
   * Flushes cache by updating accounts that have been modified
   * and removing accounts that have been deleted.
   * @param cb - Callback
   */
  flush(cb: any): void {
    const it = this._cache.begin
    let next = true
    asyncLib.whilst(
      () => next,
      (done: any) => {
        if (it.value && it.value.modified) {
          it.value.modified = false
          it.value.val = it.value.val.serialize()
          this._trie.put(Buffer.from(it.key, 'hex'), it.value.val, (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else if (it.value && it.value.deleted) {
          it.value.modified = false
          it.value.deleted = false
          it.value.val = new Account().serialize()
          this._trie.del(Buffer.from(it.key, 'hex'), (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else {
          next = it.hasNext
          it.next()
          asyncLib.nextTick(done)
        }
      },
      cb,
    )
  }

  /**
   * Marks current state of cache as checkpoint, which can
   * later on be reverted or commited.
   */
  checkpoint(): void {
    this._checkpoints.push(this._cache)
  }

  /**
   * Revert changes to cache last checkpoint (no effect on trie).
   */
  revert(): void {
    this._cache = this._checkpoints.pop()
  }

  /**
   * Commits to current state of cache (no effect on trie).
   */
  commit(): void {
    this._checkpoints.pop()
  }

  /**
   * Clears cache.
   */
  clear(): void {
    this._cache = Tree()
  }

  /**
   * Marks address as deleted in cache.
   * @param key - Address
   */
  del(key: Buffer): void {
    this._update(key, new Account(), false, true)
  }

  _update(key: Buffer, val: Account, modified: boolean, deleted: boolean): void {
    const keyHex = key.toString('hex')
    const it = this._cache.find(keyHex)
    if (it.node) {
      this._cache = it.update({
        val: val,
        modified: modified,
        deleted: deleted,
      })
    } else {
      this._cache = this._cache.insert(keyHex, {
        val: val,
        modified: modified,
        deleted: deleted,
      })
    }
  }
}


/**
   * Puts account to cache under its address.
   * @param key - Address of account
   * @param val - Account
   */
put(key: Buffer, val: Account, fromTrie: boolean = false): void {
    const modified = !fromTrie
    this._update(key, val, modified, false)
  }


/**
   * Returns the queried account or an empty account.
   * @param key - Address of account
   */
get(key: Buffer): Account {
    let account = this.lookup(key)
    if (!account) {
      account = new Account()
    }
    return account
  }


/**
   * Returns the queried account or undefined.
   * @param key - Address of account
   */
lookup(key: Buffer): Account | undefined {
    const keyStr = key.toString('hex')

    const it = this._cache.find(keyStr)
    if (it.node) {
      const account = new Account(it.value.val)
      return account
    }
  }


/**
   * Looks up address in underlying trie.
   * @param address - Address of account
   * @param cb - Callback with params (err, account)
   */
_lookupAccount(address: Buffer, cb: any): void {
    this._trie.get(address, (err: Error, raw: Buffer) => {
      if (err) return cb(err)
      var account = new Account(raw)
      cb(null, account)
    })
  }


/**
   * Looks up address in cache, if not found, looks it up
   * in the underlying trie.
   * @param key - Address of account
   * @param cb - Callback with params (err, account)
   */
getOrLoad(key: Buffer, cb: any): void {
    const account = this.lookup(key)
    if (account) {
      asyncLib.nextTick(cb, null, account)
    } else {
      this._lookupAccount(key, (err: Error, account: Account) => {
        if (err) return cb(err)
        this._update(key, account, false, false)
        cb(null, account)
      })
    }
  }


/**
   * Warms cache by loading their respective account from trie
   * and putting them in cache.
   * @param addresses - Array of addresses
   * @param cb - Callback
   */
warm(addresses: string[], cb: any): void {
    // shim till async supports iterators
    const accountArr: string[] = []
    addresses.forEach(val => {
      if (val) accountArr.push(val)
    })

    asyncLib.eachSeries(
      accountArr,
      (addressHex: string, done: any) => {
        var address = Buffer.from(addressHex, 'hex')
        this._lookupAccount(address, (err: Error, account: Account) => {
          if (err) return done(err)
          this._update(address, account, false, false)
          done()
        })
      },
      cb,
    )
  }


/**
   * Flushes cache by updating accounts that have been modified
   * and removing accounts that have been deleted.
   * @param cb - Callback
   */
flush(cb: any): void {
    const it = this._cache.begin
    let next = true
    asyncLib.whilst(
      () => next,
      (done: any) => {
        if (it.value && it.value.modified) {
          it.value.modified = false
          it.value.val = it.value.val.serialize()
          this._trie.put(Buffer.from(it.key, 'hex'), it.value.val, (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else if (it.value && it.value.deleted) {
          it.value.modified = false
          it.value.deleted = false
          it.value.val = new Account().serialize()
          this._trie.del(Buffer.from(it.key, 'hex'), (err: Error) => {
            if (err) return done(err)
            next = it.hasNext
            it.next()
            done()
          })
        } else {
          next = it.hasNext
          it.next()
          asyncLib.nextTick(done)
        }
      },
      cb,
    )
  }


/**
   * Marks current state of cache as checkpoint, which can
   * later on be reverted or commited.
   */
checkpoint(): void {
    this._checkpoints.push(this._cache)
  }


/**
   * Revert changes to cache last checkpoint (no effect on trie).
   */
revert(): void {
    this._cache = this._checkpoints.pop()
  }


/**
   * Commits to current state of cache (no effect on trie).
   */
commit(): void {
    this._checkpoints.pop()
  }


/**
   * Clears cache.
   */
clear(): void {
    this._cache = Tree()
  }


/**
   * Marks address as deleted in cache.
   * @param key - Address
   */
del(key: Buffer): void {
    this._update(key, new Account(), false, true)
  }


_update(key: Buffer, val: Account, modified: boolean, deleted: boolean): void {
    const keyHex = key.toString('hex')
    const it = this._cache.find(keyHex)
    if (it.node) {
      this._cache = it.update({
        val: val,
        modified: modified,
        deleted: deleted,
      })
    } else {
      this._cache = this._cache.insert(keyHex, {
        val: val,
        modified: modified,
        deleted: deleted,
      })
    }
  }


/*
 * Copyright 2020 The Backstage Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
export interface Config {
  /** Configuration options for the auth plugin */
  auth?: {
    /**
     * The 'environment' attribute
     * @visibility frontend
     */
    environment?: string;

    session?: {
      /**
       * The secret attribute of session object.
       * @visibility secret
       */
      secret?: string;
    };

    /** To control how to store JWK data in auth-backend */
    keyStore?: {
      provider?: 'database' | 'memory' | 'firestore';
      firestore?: {
        /** The host to connect to */
        host?: string;
        /** The port to connect to */
        port?: number;
        /** Whether to use SSL when connecting. */
        ssl?: boolean;
        /** The Google Cloud Project ID */
        projectId?: string;
        /**
         * Local file containing the Service Account credentials.
         * You can omit this value to automatically read from
         * GOOGLE_APPLICATION_CREDENTIALS env which is useful for local
         * development.
         */
        keyFilename?: string;
        /** The path to use for the collection. Defaults to 'sessions' */
        path?: string;
        /** Timeout used for database operations. Defaults to 10000ms */
        timeout?: number;
      };
    };

    /**
     * The available auth-provider options and attributes
     */
    providers?: {
      google?: {
        [authEnv: string]: { [key: string]: string };
      };
      github?: {
        [authEnv: string]: { [key: string]: string };
      };
      gitlab?: {
        [authEnv: string]: { [key: string]: string };
      };
      saml?: {
        entryPoint: string;
        logoutUrl?: string;
        issuer: string;
        cert: string;
        audience?: string;
        privateKey?: string;
        authnContext?: string[];
        identifierFormat?: string;
        decryptionPvk?: string;
        signatureAlgorithm?: 'sha256' | 'sha512';
        digestAlgorithm?: string;
        acceptedClockSkewMs?: number;
      };
      okta?: {
        [authEnv: string]: { [key: string]: string };
      };
      oauth2?: {
        [authEnv: string]: {
          clientId: string;
          clientSecret: string;
          authorizationUrl: string;
          tokenUrl: string;
          scope?: string;
          disableRefresh?: boolean;
        };
      };
      oidc?: {
        [authEnv: string]: { [key: string]: string };
      };
      auth0?: {
        [authEnv: string]: { [key: string]: string };
      };
      microsoft?: {
        [authEnv: string]: { [key: string]: string };
      };
      onelogin?: {
        [authEnv: string]: { [key: string]: string };
      };
      awsalb?: {
        issuer?: string;
        region: string;
      };
    };
  };
}


resolve =>
        {
            let resolver: IResolver = {
                handler: (this.writing_++ === 0 && this.reading_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.WRITE,
                lockType: LockType.HOLD
            };
            this.queue_.push_back(resolver);

            if (resolver.handler === null)
                resolve();
        }


resolve =>
        {
            // CONSTRUCT RESOLVER WITH PREDICATION
            let resolver: IResolver = {
                handler: (this.writing_++ === 0 && this.reading_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.WRITE,
                lockType: LockType.KNOCK
            };
            let it: List.Iterator<IResolver> = this.queue_.insert(this.queue_.end(), resolver);

            if (resolver.handler === null)
                resolve(true); // SUCCESS
            else
            {
                // AUTOMATIC UNLOCK AFTER TIMEOUT
                sleep_for(ms).then(() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.writing_;
                        this._Cancel(it);
                    }
                });
            }
        }


() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.writing_;
                        this._Cancel(it);
                    }
                }


resolve =>
        {
            let resolver: IResolver = {
                handler: (this.writing_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.READ,
                lockType: LockType.HOLD
            }
            this.queue_.push_back(resolver);

            ++this.reading_;
            if (resolver.handler === null)
                resolve();
        }


resolve =>
        {
            // CONSTRUCT RESOLVER WITH PREDICATION
            let resolver: IResolver = {
                handler: (this.writing_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.READ,
                lockType: LockType.KNOCK
            };

            ++this.reading_;
            let it: List.Iterator<IResolver> = this.queue_.insert(this.queue_.end(), resolver);

            if (resolver.handler === null)
                resolve(true);
            else
            {
                // AUTOMATIC UNLOCK AFTER TIMEOUT
                sleep_for(ms).then(() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.reading_;
                        this._Cancel(it);
                    }
                });
            }
        }


() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.reading_;
                        this._Cancel(it);
                    }
                }


/**
 * @hidden
 */
interface IResolver
{
    handler: Function | null;
    accessType: AccessType; // read or write
    lockType: LockType; // void or boolean
}


export type shared_timed_mutex = SharedTimedMutex;


/**
     * @hidden
     */
private _Current_access_type(): AccessType | null
    {
        return this.queue_.empty()
            ? null
            : this.queue_.front().accessType;
    }


/* ---------------------------------------------------------
        WRITE LOCK
    --------------------------------------------------------- */
/**
     * @inheritDoc
     */
public async lock(): Promise<void>
    {
        return new Promise<void>(resolve =>
        {
            let resolver: IResolver = {
                handler: (this.writing_++ === 0 && this.reading_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.WRITE,
                lockType: LockType.HOLD
            };
            this.queue_.push_back(resolver);

            if (resolver.handler === null)
                resolve();
        });
    }


/**
     * @inheritDoc
     */
public async try_lock(): Promise<boolean>
    {
        if (this.writing_ !== 0 || this.reading_ !== 0)
            return false;

        ++this.writing_;
        this.queue_.push_back({
            handler: null,
            accessType: AccessType.WRITE,
            lockType: LockType.KNOCK
        });
        return true;
    }


/**
     * @inheritDoc
     */
public try_lock_for(ms: number): Promise<boolean>
    {
        return new Promise<boolean>(resolve =>
        {
            // CONSTRUCT RESOLVER WITH PREDICATION
            let resolver: IResolver = {
                handler: (this.writing_++ === 0 && this.reading_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.WRITE,
                lockType: LockType.KNOCK
            };
            let it: List.Iterator<IResolver> = this.queue_.insert(this.queue_.end(), resolver);

            if (resolver.handler === null)
                resolve(true); // SUCCESS
            else
            {
                // AUTOMATIC UNLOCK AFTER TIMEOUT
                sleep_for(ms).then(() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.writing_;
                        this._Cancel(it);
                    }
                });
            }
        });
    }


/**
     * @inheritDoc
     */
public try_lock_until(at: Date): Promise<boolean>
    {
        // COMPUTE MILLISECONDS TO WAIT
        let now: Date = new Date();
        let ms: number = at.getTime() - now.getTime();

        return this.try_lock_for(ms);
    }


/**
     * @inheritDoc
     */
public async unlock(): Promise<void>
    {
        if (this._Current_access_type() !== AccessType.WRITE)
            throw new InvalidArgument(`Error on std.${this.source_.constructor.name}.unlock(): this mutex is free on the unique lock.`);

        --this.writing_;
        this.queue_.pop_front();

        this._Release();
    }


/* ---------------------------------------------------------
        READ LOCK
    --------------------------------------------------------- */
/**
     * @inheritDoc
     */
public async lock_shared(): Promise<void>
    {
        return new Promise<void>(resolve =>
        {
            let resolver: IResolver = {
                handler: (this.writing_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.READ,
                lockType: LockType.HOLD
            }
            this.queue_.push_back(resolver);

            ++this.reading_;
            if (resolver.handler === null)
                resolve();
        });
    }


/**
     * @inheritDoc
     */
public async try_lock_shared(): Promise<boolean>
    {
        if (this.writing_ !== 0)
            return false;

        ++this.reading_;
        this.queue_.push_back({
            handler: null,
            accessType: AccessType.READ,
            lockType: LockType.KNOCK
        });
        return true;
    }


/**
     * @inheritDoc
     */
public try_lock_shared_for(ms: number): Promise<boolean>
    {
        return new Promise<boolean>(resolve =>
        {
            // CONSTRUCT RESOLVER WITH PREDICATION
            let resolver: IResolver = {
                handler: (this.writing_ === 0)
                    ? null
                    : resolve,
                accessType: AccessType.READ,
                lockType: LockType.KNOCK
            };

            ++this.reading_;
            let it: List.Iterator<IResolver> = this.queue_.insert(this.queue_.end(), resolver);

            if (resolver.handler === null)
                resolve(true);
            else
            {
                // AUTOMATIC UNLOCK AFTER TIMEOUT
                sleep_for(ms).then(() =>
                {
                    // NOT YET, THEN DO UNLOCK
                    if (it.value.handler !== null)
                    {
                        --this.reading_;
                        this._Cancel(it);
                    }
                });
            }
        });
    }


/**
     * @inheritDoc
     */
public try_lock_shared_until(at: Date): Promise<boolean>
    {
        // COMPUTE MILLISECONDS TO WAIT
        let now: Date = new Date();
        let ms: number = at.getTime() - now.getTime();

        return this.try_lock_shared_for(ms);
    }


/**
     * @inheritDoc
     */
public async unlock_shared(): Promise<void>
    {
        if (this._Current_access_type() !== AccessType.READ)
            throw new InvalidArgument(`Error on std.${this.source_.constructor.name}.unlock_shared(): this mutex is free on the shared lock.`);

        --this.reading_;
        this.queue_.pop_front();

        this._Release();
    }


/* ---------------------------------------------------------
        RELEASE
    --------------------------------------------------------- */
/**
     * @hidden
     */
private _Release(): void
    {
        // STEP TO THE NEXT LOCKS
        let current: AccessType = this._Current_access_type()!;

        for (let resolver of this.queue_)
        {
            // DIFFERENT ACCESS TYPE COMES?
            if (resolver.accessType !== current)
                break;

            // NOT RESOLVED YET?
            if (resolver.handler !== null)
            {
                // CLEAR FIRST
                let handler: Function | null = resolver.handler;
                resolver.handler = null;

                // CALL LATER
                if (resolver.lockType === LockType.HOLD)
                    handler();
                else
                    handler(true);
            }

            // STOP AFTER WRITE LOCK
            if (resolver.accessType === AccessType.WRITE)
                break;
        }
    }


/**
     * @hidden
     */
private _Cancel(it: List.Iterator<IResolver>): void
    {
        //----
        // POP THE RELEASE
        //----
        // DO RASE
        this.queue_.erase(it);

        // EXTRACT HANDLER TO AVOID THE `this._Release()`
        let handler: Function = it.value.handler!;
        it.value.handler = null;

        //----
        // POST-PROCESS
        //----
        // CHECK THE PREVIOUS RESOLVER
        let prev: List.Iterator<IResolver> = it.prev();

        // RELEASE IF IT IS THE LASTEST RESOLVER
        if (prev.equals(this.queue_.end()) === false && prev.value.handler === null)
            this._Release();

        // (LAZY) RETURNS FAILURE
        handler(false);
    }


function DrawerView(props: Props) {
  const [lock, setLock] = useState(false)
  const [visibleBgColor, setVisibleBgColor] = useState(false)

  // 延迟显示防止启动时闪烁
  useEffect(() => {
    setTimeout(() => setVisibleBgColor(true), 700)
  }, [])

  drawerController = {
    setLock: (lock = true) => setLock(lock)
  }

  return (
    <Drawer.Navigator
      initialRouteName="main"
      edgeWidth={50}
      drawerStyle={{
        width: Dimensions.get('window').width * 0.6,
        elevation: 10,
        backgroundColor: visibleBgColor ? 'white' : 'transparent',
        zIndex: 1000
      }}


() => {
    setTimeout(() => setVisibleBgColor(true), 700)
  }


() => setVisibleBgColor(true)


(lock = true) => setLock(lock)


export interface Props {
  children(): JSX.Element
}


export interface DrawerController {
  setLock(lock?: boolean): void
}


() => {
    it('should display messgae', inject([], () => {
        const queue = new Subject<string>();

        queue.first(s => s == 'hello').subscribe(
            console.log,
            console.log);
        queue.next('a');
        queue.next('hello');
        queue.error('oops');
        queue.next('hello');
    }));
}


() => {
        const queue = new Subject<string>();

        queue.first(s => s == 'hello').subscribe(
            console.log,
            console.log);
        queue.next('a');
        queue.next('hello');
        queue.error('oops');
        queue.next('hello');
    }


s => s == 'hello'


export enum Floor {
	Normal,
	Pit
}


function insertIntoSetTracker(
  tier: number,
  statMix: string,
  armorSet: IntermediateProcessArmorSet,
  setTracker: SetTracker
): void {
  if (setTracker.length === 0) {
    setTracker.push({ tier, statMixes: [{ statMix, armorSets: [armorSet] }] });
    return;
  }

  for (let tierIndex = 0; tierIndex < setTracker.length; tierIndex++) {
    const currentTier = setTracker[tierIndex];

    if (tier > currentTier.tier) {
      setTracker.splice(tierIndex, 0, { tier, statMixes: [{ statMix, armorSets: [armorSet] }] });
      return;
    }

    if (tier === currentTier.tier) {
      const currentStatMixes = currentTier.statMixes;

      for (let statMixIndex = 0; statMixIndex < currentStatMixes.length; statMixIndex++) {
        const currentStatMix = currentStatMixes[statMixIndex];

        if (statMix > currentStatMix.statMix) {
          currentStatMixes.splice(statMixIndex, 0, { statMix, armorSets: [armorSet] });
          return;
        }

        if (currentStatMix.statMix === statMix) {
          for (
            let armorSetIndex = 0;
            armorSetIndex < currentStatMix.armorSets.length;
            armorSetIndex++
          ) {
            if (
              getPower(armorSet.armor) > getPower(currentStatMix.armorSets[armorSetIndex].armor)
            ) {
              currentStatMix.armorSets.splice(armorSetIndex, 0, armorSet);
            } else {
              currentStatMix.armorSets.push(armorSet);
            }
            return;
          }
        }

        if (statMixIndex === currentStatMixes.length - 1) {
          currentStatMixes.push({ statMix, armorSets: [armorSet] });
          return;
        }
      }
    }

    if (tierIndex === setTracker.length - 1) {
      setTracker.push({ tier, statMixes: [{ statMix, armorSets: [armorSet] }] });
      return;
    }
  }
}


/**
 * Gets the stat values of an item with masterwork.
 */
function getStatValuesWithMWProcess(
  item: ProcessItem,
  assumeMasterwork: boolean | null,
  orderedStatValues: number[]
) {
  const baseStats = { ...item.baseStats };

  // Checking energy tells us if it is Armour 2.0 (it can have value 0)
  if (item.sockets && item.energy) {
    let masterworkSocketHashes: number[] = [];
    // only get masterwork sockets if we aren't manually adding the values
    if (!assumeMasterwork) {
      const masterworkSocketCategory = item.sockets.categories.find(
        (category) => category.categoryStyle === DestinySocketCategoryStyle.EnergyMeter
      );

      if (masterworkSocketCategory) {
        masterworkSocketHashes = masterworkSocketCategory.sockets
          .map((socket) => socket.plug?.plugItemHash ?? NaN)
          .filter((val) => !isNaN(val));
      }
    }

    if (masterworkSocketHashes.length) {
      for (const socket of item.sockets.sockets) {
        const plugHash = socket.plug?.plugItemHash ?? NaN;

        if (socket.plug?.stats && masterworkSocketHashes.includes(plugHash)) {
          for (const statHash of orderedStatValues) {
            if (socket.plug.stats[statHash]) {
              baseStats[statHash] += socket.plug.stats[statHash];
            }
          }
        }
      }
    }

    if (assumeMasterwork) {
      for (const statHash of orderedStatValues) {
        baseStats[statHash] += 2;
      }
    }
  }
  // mapping out from stat values to ensure ordering and that values don't fall below 0 from locked mods
  return orderedStatValues.map((statHash) => Math.max(baseStats[statHash], 0));
}


function flattenSets(sets: IntermediateProcessArmorSet[]): ProcessArmorSet[] {
  return sets.map((set) => ({
    ...set,
    armor: set.armor.map((item) => item.id),
  }));
}


(statType) => statHashes[statType]


(statType) => !statFilters[statType].ignored


(i) => -i.baseStats[TOTAL_STAT_HASH]


(l) => l[l.length - 1].baseStats[TOTAL_STAT_HASH]


(item) => (item.equippingLabel ? 1 : 0)


(set) => set.statMixes.map((mix) => mix.armorSets)


(mix) => mix.armorSets


(category) => category.categoryStyle === DestinySocketCategoryStyle.EnergyMeter


(socket) => socket.plug?.plugItemHash ?? NaN


(statHash) => Math.max(baseStats[statHash], 0)


(set) => ({
    ...set,
    armor: set.armor.map((item) => item.id),
  })


type SetTracker = {
  tier: number;
  statMixes: { statMix: string; armorSets: IntermediateProcessArmorSet[] }[];
}[];


dropDown => dropDown.label === label


dropDown => dropDown.labelKey === labelKey


export class DropDowns {
    list: DropDown[];

    constructor() {
        this.list = [];
    }

    add(label: string) {
        const dropDown = new DropDown(label);
        this.list.push(dropDown);

        return dropDown;
    }

    isEmpty() {
        return this.list.length === 0;
    }

    findDropDownByLabel(label: string) {
        return this.list.find(dropDown => dropDown.label === label);
    }

    findDropDownByLabelKey(labelKey: string) {
        return this.list.find(dropDown => dropDown.labelKey === labelKey);
    }
}


add(label: string) {
        const dropDown = new DropDown(label);
        this.list.push(dropDown);

        return dropDown;
    }


isEmpty() {
        return this.list.length === 0;
    }


findDropDownByLabel(label: string) {
        return this.list.find(dropDown => dropDown.label === label);
    }


findDropDownByLabelKey(labelKey: string) {
        return this.list.find(dropDown => dropDown.labelKey === labelKey);
    }


(image) => ({
      path: image.filename,
    })


(image) => image.path


async index(_req: Request, res: Response) {
    const productsRepository = getRepository(Products);
    const products = await productsRepository.find({
      relations: ["images", "category"],
    });

    return res.json(productView.renderMany(products));
  }


async show(req: Request, res: Response) {
    const { id } = req.params;

    const productsRepository = getRepository(Products);
    const product = await productsRepository.findOneOrFail(id, {
      relations: ["images", "category"],
    });

    return res.json(productView.render(product));
  }


async create(req: Request, res: Response) {
    const {
      name,
      description,
      price,
      quantity,
      category: category_id,
    } = req.body;

    const productsRepository = getRepository(Products);

    const requestImages = req.files as Express.Multer.File[];
    const images = requestImages.map((image) => ({
      path: image.filename,
    }));

    const categoryRepository = getRepository(Category);
    const category = await categoryRepository.findOneOrFail(category_id);

    const data = {
      name,
      description,
      price,
      quantity,
      category,
      images,
    };

    const schema = Yup.object().shape({
      name: Yup.string().required(),
      description: Yup.string().required(),
      price: Yup.number().required(),
      quantity: Yup.number().required(),
      images: Yup.array(
        Yup.object().shape({
          path: Yup.string().required(),
        })
      ),
      category: Yup.object()
        .shape({
          name: Yup.string().required(),
          id: Yup.number().required(),
        })
        .required(),
    });

    await schema.validate(data, {
      abortEarly: false,
    });

    const product = productsRepository.create(data);

    await productsRepository.save(product);

    return res.status(201).json(productView.render(product));
  }


async update(req: Request, res: Response) {
    const { id } = req.params;

    const {
      name,
      description,
      price,
      quantity,
      category: category_id,
    } = req.body;

    const productsRepository = getRepository(Products);
    const product = await productsRepository.findOneOrFail(id, {
      relations: ["images", "category"],
    });

    const categoryRepository = getRepository(Category);
    const category = await categoryRepository.findOneOrFail(category_id);

    const requestImages = req.files as Express.Multer.File[];
    const images = requestImages.map((image) => ({
      path: image.filename,
    }));

    const data = {
      name,
      description,
      price,
      quantity,
      category,
      images,
    };

    const schema = Yup.object().shape({
      name: Yup.string().required(),
      description: Yup.string().required(),
      price: Yup.number().required(),
      quantity: Yup.number().required(),
      images: Yup.array(
        Yup.object().shape({
          path: Yup.string().required(),
        })
      ),
      category: Yup.object()
        .shape({
          name: Yup.string().required(),
          id: Yup.number().required(),
        })
        .required(),
    });

    await schema.validate(data, {
      abortEarly: false,
    });

    const imagesRepository = getRepository(Images);

    const imagesNames = product.images.map((image) => image.path);

    deleteImages(imagesNames);

    await imagesRepository.remove(product.images);
    const imagesFromDB = imagesRepository.create(images);

    product.name = name;
    product.description = description;
    product.price = price;
    product.quantity = quantity;
    product.images = imagesFromDB;
    product.category = category;

    await productsRepository.save(product);

    return res.status(200).json(productView.render(product));
  }


async delete(req: Request, res: Response) {
    const { id } = req.params;

    const productsRepository = getRepository(Products);
    const product = await productsRepository.findOneOrFail(id, {
      relations: ["images"],
    });

    const imagesNames = product.images.map((image) => image.path);

    deleteImages(imagesNames);

    await productsRepository.remove(product);

    return res.status(204).json();
  }


(data: any[])=> {
        return {
          committees: data[1],
          tags: data[0]
        }
      }


@Injectable()
export class CommitteeService {

  constructor(private http: HttpClient) { }

  getCommittees(): Observable<{committees: Committee[], tags: string[]}> {
    return forkJoin([
      this.http.get("assets/all_tags.json"),
      this.http.get("assets/tags_by_comm.json")
    ])
      .map((data: any[])=> {
        return {
          committees: data[1],
          tags: data[0]
        }
      });
  }

}


getCommittees(): Observable<{committees: Committee[], tags: string[]}> {
    return forkJoin([
      this.http.get("assets/all_tags.json"),
      this.http.get("assets/tags_by_comm.json")
    ])
      .map((data: any[])=> {
        return {
          committees: data[1],
          tags: data[0]
        }
      });
  }


() => {
  const dispatch = useDispatch()
  // @ts-ignore
  const { project_id } = useParams()

  const project = useSelector<RootState, Project>(
    // eslint-disable-next-line eqeqeq
    (state) => state?.project?.data?.find((pro) => pro.id == project_id)!
  )
  const dataSource = useSelector<RootState, SourceMapModelState['data']>(
    (state) => state.sourceMap?.data
  )
  const loading = useSelector<RootState, boolean>(
    (state) => state.loading.effects['sourceMap/get']!
  )

  useMount(() => {
    dispatch({
      type: 'sourceMap/get',
      payload: { project },
    })
  })

  return (
    <section className={styles.root}>
      <Zone title="SourceMap">
        <Table<SourceMap>
          dataSource={dataSource}
          loading={loading}
          rowKey={(record)


// eslint-disable-next-line eqeqeq
(state) => state?.project?.data?.find((pro) => pro.id == project_id)!


(pro) => pro.id == project_id


(state) => state.sourceMap?.data


(state) => state.loading.effects['sourceMap/get']!


() => {
    dispatch({
      type: 'sourceMap/get',
      payload: { project },
    })
  }


dayjs(item?.createdAt)


onOk() {
                        dispatch({
                          type: 'sourceMap/delete',
                          payload: {
                            sourceMap_id: item?.id,
                            project,
                          },
                        })
                      }


export function test_MultiParserTemplate() {
    const xml = global.loadModule("xml-parser-tests/itemTemplates.xml")

    const view: any = builder.parse(xml);
    TKUnit.assertNotNull(view.items)
    TKUnit.assertEqual(view.items.length, 1);
}