4

Using Loopback 4, I am trying to execute a simple get request after which I want to store some data in my database.

I would like to execute the following code from the command line:

import {WebshopApplication} from '../application';
import axios from 'axios';
import {CurrencyRepository} from '../repositories';

export async function importCurrencies(args: string[]) {

  const app = new WebshopApplication();
  await app.boot();


  const host = 'http://data.fixer.io/api';
  const accessToken = 'access_key=mykey';

  const currencyRepository = await app.getRepository(CurrencyRepository);
  const currencies = currencyRepository.find({});
  console.log(currencies);

  try {

    const resp = await axios.get(`${host}/latest?${accessToken}` );
    const currencies = resp.data;
    console.log(currencies);
  } catch (err) {
    console.log(err);
  }

  process.exit(0);
}

importCurrencies(process.argv).catch(err => {
  console.error('Cannot import currencies due to error', err);
  process.exit(1);
});

When i execute:

 ts-node src/commands/import-currency.command.ts

I get the following error:

Cannot import currencies due to error Error: The key 'repositories.CurrencyRepository' is not bound to any value in context WebshopApplication-f9b12a86-ec04-46b4-8e87-4031a4ab71f9

Why is this not working?

UPDATE 26-05-2020:

I have updated the above script to the following as per a suggestion in the commands.

import {WebshopApplication} from '../application';
import axios from 'axios';
import {CurrencyRepository} from '../repositories';
import {bind, BindingScope} from '@loopback/context';

@bind({scope: BindingScope.TRANSIENT})
export class ImportCurrencies {

  generate = async () => {
    const app = new WebshopApplication();
    await app.boot();

    const host = 'http://data.fixer.io/api';
    const accessToken ='mytoken';

    const currencyRepository = await app.getRepository(CurrencyRepository);
    const currencies = currencyRepository.find({});

    const resp = await axios.get(`${host}/latest?${accessToken}`);
    const currencies = resp.data;

    process.exit(0);
  }
}

const importCurrencies = new ImportCurrencies();

importCurrencies.generate().catch(err => {
  process.exit(1);
});

Unfortunately adding the binding at the top of the class did not work

xfscrypt
  • 16
  • 5
  • 28
  • 59

2 Answers2

2

is basically indicating that a binding key wasn't bound properly to the application context. Do you have 'repositories.CurrencyRepository' bound in SINGLETON scope? full explanation here https://github.com/strongloop/loopback-next/blob/master/docs/site/Dependency-injection.md#dependency-injection-for-bindings-with-different-scopes

it suggest to do this:

@bind({scope: BindingScope.TRANSIENT})
export class someDatasource extends juggler.DataSource {
}

Or

The issue seems to be coming from the @loopback/context. As a temp workaround, use "@loopback/context": "1.5.1" instead of the latest.

RaymondFeng told that it was a binding scope issue in Loopback 4 see : https://github.com/strongloop/loopback-next/pull/2513

Dependency injection for bindings with different scopes: Contexts can form a chain and bindings can be registered at different levels. The binding scope controls not only how bound values are cached, but also how its dependencies are resolved.

possible Troubleshooting:

import {CurrencyRepository} from '../repositories'; -->is the path correct? ../?

nikhil swami
  • 2,360
  • 5
  • 15
  • I have tried to add the bind decorator, but unfortunately that did not work either. The same error remains – xfscrypt May 26 '20 at 09:43
  • 1
    Also, downgrading to 1.5.1 seems to be quite far back from the current 3.8.1. That comment was made in feb 2019, more then a year ago from today. The path to the repository is correct. I have a src/commands folder and a src/repositories folder in my structure, – xfscrypt May 26 '20 at 09:46
2

LoopBack 4 has the concept of Booters to dynamically link certain assets (such as Repositories) during runtime. Booters look for built, JavaScript files in the /dist folder.

As such, the application must be built using npm run build and then the application must be run in its completely-built form:

    node dist/command/import-currency.command.js
Rifa Achrinza
  • 1,555
  • 9
  • 19
xfscrypt
  • 16
  • 5
  • 28
  • 59