My journey with

What is loopback?

Main parts
JSON definition
CRUD REST endpoints
ACL
Datasource
Client lib
- each model has one JS file
- API endpoint
- model method
- operation hook
Custom logic
- auto-migrate
- drop all tables and recreate them
- => useless
- auto-migrate
- looks for changes in model definitions
- can't handle: rename fields, indices
- => useless
- no real support
Migrations
Transaction management
- manually handle opening, committing and rollbacking
- manually use the transaction when performing DB operations
- nested transactions?
...
MyModel.beginTransaction(tx => {
MyModel.findById(42, {}, {transaction: tx})
.then(modelInstance => {
return modelInstance.update(
{attribute: newValue},
{transaction: tx}
);
})
.then(result => {
return tx.commit().then(() => result);
})
.catch(err) => {
console.error(err.stack);
tx.rollback();
});
});function fancyFind(criteria, transaction = null) {
if (transaction) {
return FancyModel.find(criteria);
} else {
return FancyModel.find(criteria, {transaction});
}
}Consequence
Support for promises

The (in)famous Contex
- update a model in a transaction
- any model validations need to run in THE SAME transaction
...
return modelInstance.update(
{attribute: newValue},
{transaction: tx}
);
...MyModel.validate('new value is ok', () => {
AnotherModel.find(
{where: {aValue: this.attribute}},
{transaction: tx}
)
});- how does tx get from left to right?
- the CONTEXT (manually)

- what else uses the context?
- the loopback way of getting the current user
The datasource juggler
- allows you to connect the models to any datasource:
- MySQL
- Memory
- PostgreSQL
- MongoDB
- REST API
- ...
- however:
- various inconsistencies in storage providers make this very hard to achieve
- not all datasources use the same code (the juggler)
The API interface
MyModel.find({
"filter": {
"where": {
"id": {
"inq": [1, 2, 3]
},
"startDate": {
"gte": "2016-01-02"
}
},
"include": {
"child": {
"include": ["grandchild"]
}
}
}
});http://localhost:3010/api/action-plan-items?filter=%7B%22where%22%3A%7B%22id%22%3A%7B%22
inq%22%3A%5B1%2C2%2C3%5D%7D%2C%22startDate%22%3A%7B%22gte%22%3A%222016-01-02%22%7D%7D
%2C%22include%22%3A%7B%22child%22%3A%7B%22include%22%3A%5B%22grandchild%22%5D%7D%7D%7D
http://localhost:3010/api/action-plan-items?filter={"where":{"id":{"inq":[1,2,3]},
"startDate":{"gte":"2016-01-02"}},"include":{"child":{"include":["grandchild"]}}}- very flexible
- one API invocation to get everything you want
- no need to implement a custom API endpoint
-------------
- easy to go over the url length limit
- exposing a lot of internal structure (but that is REST; 1-1 mapping between Model - REST Resource)
- the correctness relies on using query params with empty string and empty array
- JS querystring library removes the empty array
Query params
http://localhost:3010/api/action-plan-items?filter={"where":{"id":{"inq":[]}}}http://localhost:3010/api/action-plan-itemsTake aways
- Very good for rapid prototyping
- Very good integration with Angular
- Decent community where you can find resources
- Multitude of github repos some actively maintained, some not so much
- Pretty nice to do unit tests
Take aways
- Doesn't encapsulate really well
- A lot of manual work when working with transactions
- Also, hard to test without a MySQL datasource
- in the long run, you will move away from the generic REST API
- No migration support
- Once you get past a certain level, you will get hit by bugs
- Could be better and more actively maintained
Q & A
Thanks!
Resources
- TODO
My journey with loopback
By Horia Radu
My journey with loopback
- 384