6

I am using loopback without the strongloop framework itself, meaning I have no access to any of the cli tools. I am able to succesfully create and launch a loopback server and define/load some models in this fashion:

var loopback = require('loopback');
var app = loopback();

var dataSource = app.dataSource
(
    'db',
    {
        adapter : 'memory'
    });
);

var UserModel = app.loopback.findModel('User');
UserModel.attachTo(dataSource);
app.model(UserModel);

/* ... other models loading / definitions */

// Expose API
app.use('/api', app.loopback.rest());

What I would like to achieve is to be able to detach a model from the loopback application at runtime, so it is not available from the rest API nor the loopback object anymore (without the need to restart the node script).

I know it is possible to remove a model definition made previously from the cli: Destroy a model in loopback.io, but this is not valid in my case since what it does is to remove the json objects that are loaded at strongloop boot, which is not applicable here.

I would appreciate very much any help regarding this, I have found nothing in the strongloop API documentation.

Community
  • 1
  • 1

2 Answers2

1

Disclaimer: I am a core developer of LoopBack.

I am afraid there is no easy way for deleting models at runtime, we are tracking this request in issue #1590.

so it is not available from the rest API nor the loopback object anymore

Let's take a look at the REST API first. In order to remove your model from the REST API, you need to remove it from the list of "shared classes" maintained by strong-remoting and then clean the cached handler middleware.

delete app.remotes()._classes[modelName];
delete app.remotes()._typeRegistry._types[modelName];
delete app._handlers.rest;

When the next request comes in, LoopBack will create a new REST handler middleware and rebuild the routing table.

In essence, you need to undo the work done by this code.

In order to remove the model from LoopBack JavaScript APIs, you need to remove it from the list of models maintained by application's registry:

delete app.models[modelName];
delete app.models[classify(modelName)];
delete app.models[camelize(modelName)];
app.models.models.splice(app.models.indexOf(ModelCtor), 1);

(This is undoing the work done by this code).

Next, you need to remove it from loopback-datasource-juggler registries:

delete app.registry.modelBuilder.models[modelName];

Caveats:

  • I haven't run/tested this code, it may not work out of the box.
  • It does not handle the case where the removed model has relations with other models.
  • It does not notify loopback-component-explorer about the change in the API
Miroslav Bajtoš
  • 9,924
  • 1
  • 36
  • 91
  • Thanks a lot Bajtos. Will try to achieve it as soon as I can, I have been avoiding it until now :) – Lucas Lopez Aug 09 '17 at 15:46
  • I'd like to add onto Bajtos's answer. You need to import [underscore.string](http://epeli.github.io/underscore.string/) in order for you to be able to use `classify` and `camelize`. Also, this line `app.models.models.splice(app.models.indexOf(ModelCtor), 1);` is pretty useless and will yield an error; deleting it won't affect your desired change. And most importantly, you need to delete all of the entries in your model before deleting because they don't get deleted from database entries, so add this line at the top of your deletion code: `app.models[modelName].destroyAll();` – Harry Adel Apr 02 '18 at 15:58
1

Update

There's now a function called deleteModelByName that does exactly that.

https://apidocs.strongloop.com/loopback/#app-deletemodelbyname

https://github.com/strongloop/loopback/pull/3858/commits/0cd380c590be7a89d155e5792365d04f23c55851

Harry Adel
  • 746
  • 6
  • 12