pk: createDelimitedAttribute()

in source/packages/services/organization-manager/src/accounts/accounts.dao.ts [56:269]


                        pk: createDelimitedAttribute(
                            PkType.OrganizationalUnits,
                            organizationalUnit
                        ),
                        sk: createDelimitedAttribute(PkType.Region, ...[accountId, region]),
                        accountId: accountId,
                    },
                },
            };
        });
    }

    public async getAccountById(accountId: string): Promise<AccountsItem> {
        logger.debug(`accounts.dao getAccountById: in: accountId ${accountId}`);
        const getAccountResponse = await this._dc
            .query({
                TableName: this.accountsTable,
                IndexName: this.accountsTableGsi2,
                KeyConditionExpression: 'gsi2Key = :gsi2Key and  begins_with(sk,:sk)',
                ExpressionAttributeValues: {
                    ':gsi2Key': createDelimitedAttributePrefix(PkType.Accounts, accountId),
                    ':sk': PkType.OrganizationalUnits,
                },
            })
            .promise();

        if (getAccountResponse.Items.length === 0) {
            logger.debug('accounts.dao getAccount: exit: undefined');
            return undefined;
        }

        const item = AccountsDao.assembleAccount(getAccountResponse.Items[0]);
        logger.debug(`accounts.dao getAccount: exit: ${JSON.stringify(item)}`);
        return item;
    }

    public async getAccountByName(accountName: string): Promise<AccountsItem> {
        logger.debug(`accounts.dao getAccountByName: in: accountName ${accountName}`);
        const getAccountResponse = await this._dc
            .query({
                TableName: this.accountsTable,
                KeyConditionExpression: 'pk = :pk and  begins_with(sk,:sk)',
                ExpressionAttributeValues: {
                    ':pk': createDelimitedAttributePrefix(PkType.Accounts, accountName),
                    ':sk': PkType.OrganizationalUnits,
                },
            })
            .promise();

        if (getAccountResponse.Items.length === 0) {
            logger.debug('accounts.dao getAccount: exit: undefined');
            return undefined;
        }

        const item = AccountsDao.assembleAccount(getAccountResponse.Items[0]);
        logger.debug(`accounts.dao getAccountByName: exit: ${JSON.stringify(item)}`);
        return item;
    }

    private static assembleAccounts(result: AWS.DynamoDB.DocumentClient.ItemList): AccountsItem[] {
        logger.debug(`accounts.dao assembleAccounts: in: result: ${JSON.stringify(result)}`);

        const accountItems = [];

        for (const item of result) {
            const accountItem = this.assembleAccount(item);
            accountItems.push(accountItem);
        }

        logger.debug(`accounts.dao assembleAccount: exit: ${JSON.stringify(accountItems)}`);
        return accountItems;
    }

    private static assembleAccount(
        result: AWS.DynamoDB.DocumentClient.AttributeMap
    ): AccountsItem {
        logger.debug(`accounts.dao assembleAccount: in: result: ${JSON.stringify(result)}`);
        const { pk, sk, status, regions, gsi2Key, email, ssoEmail, ssoFirstName, ssoLastName } =
            result;
        let accountId;
        const pkElements = pk.split(':');
        const skElements = sk.split(':');
        if (gsi2Key !== undefined) {
            const gsi2Elements = gsi2Key.split(':');
            accountId = gsi2Elements[1];
        }

        const item: AccountsItem = {
            name: pkElements[1],
            organizationalUnitId: skElements[1],
            email,
            accountId,
            ssoEmail,
            ssoFirstName,
            ssoLastName,
            regions,
            status,
        };
        logger.debug(`accounts.dao assembleAccount: exit: ${JSON.stringify(item)}`);
        return item;
    }

    private static assembleComponentsDeploymentStatus(
        result: AWS.DynamoDB.DocumentClient.ItemList
    ): AccountComponentModel[] {
        logger.debug(
            `accounts.dao assembleComponentsDeploymentStatus: in: result: ${JSON.stringify(
                result
            )}`
        );
        const componentDeploymentStatus: AccountComponentModel[] = [];
        for (const item of result) {
            const { pk, sk, status } = item;
            const pkElements = pk.split(':');
            const skElements = sk.split(':');
            componentDeploymentStatus.push({
                status,
                accountId: pkElements[1],
                region: skElements[1],
                componentName: skElements[2],
            });
        }

        logger.debug(
            `accounts.dao assembleComponentsDeploymentStatus: exit: ${JSON.stringify(
                componentDeploymentStatus
            )}`
        );
        return componentDeploymentStatus;
    }

    public async listComponentsByAccount(accountId: string): Promise<AccountComponentModel[]> {
        logger.debug(`accounts.dao listComponentsByAccount: in accountId:${accountId}`);
        const queryResponse = await this._dc
            .query({
                TableName: this.accountsTable,
                IndexName: this.accountsTableGsi2,
                KeyConditionExpression: 'gsi2Key = :gsi2Key and begins_with(sk,:sk)',
                ExpressionAttributeValues: {
                    ':gsi2Key': createDelimitedAttributePrefix(PkType.Accounts, accountId),
                    ':sk': PkType.Components,
                },
            })
            .promise();

        if (queryResponse.Items === undefined || queryResponse.Items.length === 0) {
            return [];
        }
        const componentDeploymentStatusList = AccountsDao.assembleComponentsDeploymentStatus(
            queryResponse.Items
        );
        logger.debug(
            `accounts.dao listComponentsByAccount: exit componentDeploymentStatusList:${JSON.stringify(
                componentDeploymentStatusList
            )}`
        );
        return componentDeploymentStatusList;
    }

    public async updateComponentByAccount(request: AccountComponentModel): Promise<void> {
        logger.debug(
            `accounts.dao updateComponentByAccount: in request:${JSON.stringify(request)}`
        );

        const { region, accountId, componentName, status } = request;

        const account = await this.getAccountById(accountId);

        await this._dc
            .put({
                TableName: this.accountsTable,
                Item: {
                    pk: createDelimitedAttribute(PkType.Accounts, account.name),
                    sk: createDelimitedAttribute(PkType.Components, region, componentName),
                    gsi2Key: createDelimitedAttributePrefix(PkType.Accounts, accountId),
                    status,
                },
            })
            .promise();
        logger.debug(`accounts.dao updateComponentByAccount: exit`);
    }

    public async updateRegionsMappingForAccount(
        organizationalUnitId: string,
        accountId: string,
        regions: string[]
    ): Promise<void> {
        logger.debug(
            `accounts.dao deleteRegionsMappingForAccount: in organizationalUnitId:${organizationalUnitId} accountId:${accountId}`
        );
        const queryResponse = await this._dc
            .query({
                TableName: this.accountsTable,
                KeyConditionExpression: 'pk = :pk and begins_with(sk,:sk)',
                ExpressionAttributeValues: {
                    ':pk': createDelimitedAttributePrefix(
                        PkType.OrganizationalUnits,
                        organizationalUnitId
                    ),
                    ':sk': createDelimitedAttributePrefix(PkType.Region, accountId),
                },
            })
            .promise();

        if (queryResponse.Items.length > 0) {
            logger.debug(
                `accounts.dao deleteRegionsMappingForAccount: queryResponse: ${JSON.stringify(
                    queryResponse
                )}`
            );
            await this._dc
                .batchWrite({
                    RequestItems: {
                        [this.accountsTable]: queryResponse.Items.map((item) => {