0

I'm having a little problem trying to create the database connection url. I am using the AWS Secrets Manager service and with the returned data I create my connection URL. The problem is that when I want to create the URL it gives me an error. If someone can help me I would really appreciate it

I created a module with functions to create the URL but, the return is undefined. What seems to happen is that the execution does not wait for the promise to resolve. because the Secrets if I am receiving them but later

import { Injectable } from '@nestjs/common'
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'

@Injectable({})
export class SecretsService{
    public final: string

    async getSecret() {
        const secret_name = 'Secret'
        let lastURL
        const client = new SecretsManagerClient({
            region: 'us-east-1',
        })

        client.send(
            new GetSecretValueCommand({
                SecretId: secret_name,
                VersionStage: 'AWSCURRENT'// VersionStage defaults to AWSCURRENT if unspecified
            })
        ).then((response)=>{
            const data = response.SecretString
            const secret=JSON.parse(data)
            lastURL= `${secret.engine}://${secret.username}:${secret.password}@${secret.host}:${secret.port}/dbname?schema=public`
            this.final=lastURL
            console.log(this.final)
        }).catch((error)=>{
            console.log(error)
        })

    }
}
import { Injectable } from '@nestjs/common'
import { PrismaClient } from '@prisma/client'
import { SecretsService } from 'src/secrets/secrets.service'

const asd = new SecretsService()

asd.getSecret()
const urlFinal=asd.final

@Injectable()
export class  PrismaService extends PrismaClient {
    
    constructor(){
        super({
            datasources: {
                db:{
                     url: asd.final
                }
            }
        })
    }

}
  • You have to await the call and only then continue, i.e. `await asd.getSecret()`. This won't work however, as you are trying to use the async result in a constructor which [doesn't work](https://stackoverflow.com/questions/43431550/async-await-class-constructor). You have to refactor the code to reflect the async nature of it. – Wiktor Zychla Nov 04 '22 at 15:26
  • You say something like this async()=>{await asd.getSecret()} – Walter Stamm Nov 04 '22 at 15:53

2 Answers2

0
import { Injectable } from '@nestjs/common'
import { PrismaClient } from '@prisma/client'
import { SecretsService } from 'src/secrets/secrets.service'   


@Injectable()
export class  PrismaService extends PrismaClient {
    
    constructor(
        private readonly asd: SecretsService
    ){
        super({
            datasources: {
                db:{
                     url: async () => {
                              await asd.getSecret();
                              return asd.final;
                          };
                }
            }
        })
    }

}

Can you try this way?

melihkizmaz
  • 31
  • 1
  • 2
  • Yes I tried , but i recive this errorEl tipo '() => Promise' no se puede asignar al tipo 'string'.ts(2322) index.d.ts(1086, 5): El tipo esperado procede de la propiedad "url", que se declara aquí en el tipo "Datasource" – Walter Stamm Nov 07 '22 at 02:41
0

Have you tried a plain async / await approach without touching the indesesof the promise? This is how AWS suggests sending commands in the AWS docs:

// the secrets manager
import { Injectable } from '@nestjs/common'
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'

@Injectable({})
export class SecretsService{

    async getSecret() {
        const secret_name = 'Secret'
        let lastURL
        const client = new SecretsManagerClient({
            region: 'us-east-1',
        })

        const response = await client.send(
            new GetSecretValueCommand({
                SecretId: secret_name,
                VersionStage: 'AWSCURRENT'// VersionStage defaults to AWSCURRENT if unspecified
            });
        const secret =   JSON.parse(rsponse.SecretString);
        return `${secret.engine}://${secret.username}:${secret.password}@${secret.host}:${secret.port}/dbname?schema=public`;
    }
}

And consume it like this:

const asd = new SecretsService()
const url = await asd.getSecret();
Konstantin A. Magg
  • 1,106
  • 9
  • 19