I can create a loopback model from an example json instance as shown here https://docs.strongloop.com/display/public/LB/Creating+models+from+unstructured+data. But from there is there an API to create the .json file in common/models?
#BoLaMN from Looback Gitter said this:
try app.registry.modelBuilder.introspect(json); that should give you a properties object. Then just add name, base to it and fs.writeSync JSON.stringify(obj).
I haven't tried yet, but it makes sense.
I've been using this:
var User = db.buildModelFromInstance('User', user, {idInjection: true});
var UserModel = (loopback.getModel(User));
var UserModelJSON = {}
UserModelJSON.name = 'User';
UserModelJSON.base = 'PersistedModel';
UserModelJSON.properties = UserModel.definition.rawProperties;
console.log(JSON.stringify(UserModelJSON));
fs.writeFile('User.json', 'UserModelJSON', function(err) {
if (err) throw err;
});
In your loopback /server directory at the root of your project, if you define the datasources.json file like so
{
"db": {
...
},
"restResourceName": {
"name": "restResourceName",
"baseURL": "http://restResourceUrl/",
"crud": true,
"connector": "rest"
}
}
And you define a boot script, like so
const fs = require('fs')
const path = require('path')
const writeInstance = (server, modelName, instance) => {
let Model = server.dataSources.restResourceName.buildModelFromInstance(modelName, instance)
let modelJson = Model.definition.toJSON()
delete modelJson.settings.base
fs.writeFile(path.join(__dirname, '..', 'models', modelName + '.json'),
JSON.stringify(modelJson, null, 2), (/*...*/) => {
/*...*/
})
}
module.exports = function (server) {
writeInstance(server, "Atom", {
atomicWeight: 6
})
}
You will generate a model file Atom.json
{
"name": "Atom",
"properties": {
"atomicWeight": {
"type": "Number"
},
"id": {
"type": "Number",
"id": 1,
"generated": true,
"updateOnly": true
}
},
"settings": {
"strict": false,
"forceId": "auto",
"replaceOnPUT": true
}
}
If you want to see the models in the loopback api explorer (swagger GUI), you must add the model to the model-config.json with a public: true property
{
"_meta": {
"sources": [
...
],
"mixins": [
...
]
},
"Atom": {
"public": true,
"dataSource": "restResourceName"
}
}
Related
Struggling to create my customised adapter & serializer to integrate Supabase, how I'm stuck why no data in Ember Data.
Trying out with a simple findAll() method. See below:
Service ⬇️:
export default class SupabaseService extends Service {
client;
constructor() {
super(...arguments);
const { url, key } = ENV.supabase;
const supabase = createClient(url, key);
this.client = supabase;
}
}
Model ⬇️:
export default class CourseModel extends Model {
#attr('string') name;
#attr('date') date_added;
}
Adapter ⬇️:
export default class ApplicationAdapter extends RESTAdapter {
#service supabase;
async findAll(store, type, neverSet, snapshotRecordArray) {
return new Promise(async (resolve, reject) => {
try {
const { data, error, status } = await this.supabase.client
.from(pluralize(type.modelName))
.select('*');
if (error) {
reject(error);
} else {
resolve(data);
}
} catch (error) {
reject(error);
}
});
}
}
Serializer ⬇️:
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
// parse the response data from the server and return it in the format that Ember Data expects
let newPayload = {
data: payload.map(item => {
let attributes = JSON.parse(JSON.stringify(item));
delete attributes.id;
return {
id: item.id,
type: primaryModelClass.modelName,
attributes: attributes
}
})
}
return super.normalizeResponse(store, primaryModelClass, newPayload, id, requestType);
}
✅ The service works fine. The adapter manage to get data and returns as follows:
[
{
"id": "259f46fd-3321-4cc9-ad5e-6d6ec880f7f1",
"date_added": "2022-12-31T00:03:14.618585+00:00",
"name": "Science"
},
{
"id": "62a6a085-604b-4600-8cc4-59a8c9af284a",
"date_added": "2022-12-31T00:03:30.010963+00:00",
"name": "Physics"
}
]
The serializer newPayload to follow JSON API schema, returns:
{
"data": [
{
"id": "259f46fd-3321-4cc9-ad5e-6d6ec880f7f1",
"type": "course",
"attributes": {
"name": "Science",
"date_added": "2022-12-31T00:03:14.618585+00:00"
}
},
{
"id": "62a6a085-604b-4600-8cc4-59a8c9af284a",
"type": "course",
"attributes": {
"name": "Physics",
"date_added": "2022-12-31T00:03:30.010963+00:00"
}
}
]
}
But the problem is no data in store. Logging model in template shows empty Proxy {}.
I have no idea why. Ember Inspector shows no model in Data.
Any suggestions?
I wanted to check from the response format if status=AVAILABLE then arrayElement should return with roomTypeId else roomTypeId should not return for other status.
[
{
"status": "SOLDOUT",
"propertyId": "dc00e77f",
"Fee": 0,
"isComp": false
},
{
"roomTypeId": "c5730b9e",
"status": "AVAILABLE",
"propertyId": "dc00e77f",
"price": {
"baseAveragePrice": 104.71,
"discountedAveragePrice": 86.33
},
"Fee": 37,
"isComp": false
},
]
[
{
"status": "SOLDOUT",
"propertyId": "773000cc-468a-4d86-a38f-7ae78ecfa6aa",
"resortFee": 0,
"isComp": false
},
{
"roomTypeId": "c5730b9e-78d1-4c1c-a429-06ae279e6d4d",
"status": "AVAILABLE",
"propertyId": "dc00e77f-d6bb-4dd7-a8ea-dc33ee9675ad",
"price": {
"baseAveragePrice": 104.71,
"discountedAveragePrice": 86.33
},
"resortFee": 37,
"isComp": false
},
]
I tried to check this from below;
pm.test("Verify if Status is SOLDOUT, roomTypeId and price information is not returned ", () => {
var jsonData = pm.response.json();
jsonData.forEach(function(arrayElement) {
if (arrayElement.status == "SOLDOUT")
{
pm.expect(arrayElement).to.not.include("roomTypeId");
}
else if (arrayElement.status == "AVAILABLE")
{
pm.expect(arrayElement).to.include("roomTypeId");
}
});
});
You need to check if the property exists or not.
With the have.property syntax you can do that.
You can read the Postman API reference docs and also Postman uses a fork of chai internally, so ChaiJS docs should also help you.
Updated script:
pm.test("Verify if Status is SOLDOUT, roomTypeId and price information is not returned ", () => {
var jsonData = pm.response.json();
jsonData.forEach(function(arrayElement) {
if (arrayElement.status === "SOLDOUT") {
pm.expect(arrayElement).to.not.have.property("roomTypeId");
} else if (arrayElement.status === "AVAILABLE") {
pm.expect(arrayElement).to.have.property("roomTypeId");
}
});
});
I have built an SPA Application, i need to deploy it on a loopback server, and i never used it, so i am lost with all of these json files you can configure to intercept the calls.
I simply need to intercept every calls (expect static files) and to return my index.html file for every cases.
Technically, it is just a middleware that is invocked after the "serve-static" middleware and say "ok if you are here, you are not an asset, render the index.html file".
My / path already return the index.html, how am i supposed to implement that rule properly with loopback?
I guess it is going to happens on the middleware.json file, so mine currently looks like this:
{
"initial:before": {
"loopback#favicon": {}
},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": true,
"credentials": true,
"maxAge": 86400
}
}
},
"session": {
},
"auth": {
},
"parse": {
},
"routes": {
"loopback#rest": {
"paths": ["${restApiRoot}"]
}
},
"files": {
"serve-static": {
"params": "$!../client"
}
},
"final": {
"loopback#urlNotFound": {}
},
"final:after": {
"loopback#errorHandler": {}
}
}
You can a middleware which will check if nodejs has already served a request, if not redirect to /.
//in middleware.json
"final:before": {
"./middleware/redirect.js": {},
}
//in server/middleware/redirect.js
module.exports = function() {
return function redirect(request, response, next) {
if (!response.headersSent) {
response.redirect('/');
} else {
next();
}
}
};
I have the following model in LoopBackJS:
{
"name": "member",
"base": "PersistedModel",
"properties": {
"firstName": {
"type": "string"
}
"public": {
"type": "boolean"
}
},
"relations": {
"spouse": {
"type": "hasOne",
"model": "spouse",
"foreignKey": "spouseId"
}
}
}
Now I need to modify the firstName field, so one can only see "public": true members first name and the others gets firstName: "*". The function for that I have already.
But how can I access the data on each data-access-request?
I tried it with the with the operation hook e.g. find, findOne,... but when I miss one of them some users could access the firstName.
With the remote hook it's the same.
Now I'm trying it with the connector hook:
connector.observe('after execute', function(ctx, next) {
if (ctx.model === 'familyMember') {
if (ctx.req.command === 'find') {
}
}
next();
});
For all find queries (mongodb) but there I can't access the data. Is there a way to access those data? Or is there a much better (build-in) solution for this problem?
You need to check result after each remote :
member.afterRemote('**', function(ctx, modelInstance, next) {
if (ctx.result) {
if (Array.isArray(modelInstance)) {
var answer = [];
ctx.result.forEach(function (result) {
if(result.public === false)
result.firstName = "*";
answer.push(result);
});
} else {
var answer =ctx.result;
if(answer.public === false)
answer.firstName = "*";
}
ctx.result = answer;
}
next();
});
My api basically returns something like this:
GET /api/projects/
{
"count": 26,
"next": "http://127.0.0.1:8000/api/projects/?page=2",
"previous": null,
"results": [
{
"id": 21,
"name": "Project A",
...
},
{
"id": 19,
"name": "Project B",
...
},
...
]
}
Using NgResource, I am able to query the api and get the data like this:
var PROJECT = $resource('/api/projects/:id/', {id:'#id'},{
query : {
method : 'GET',
isArray : false
}
});
factory.project_list = function(callback) {
PROJECT.query({},function(project_list){
factory.project_list = project_list.results;
callback();
});
};
My different projects are now available in factory.project_list. The issue here is that each item in factory.project_list are not ngResource items. So I can't call methods such as .$save(), .$update()...
I saw a transformResponse() function but I'm not able to get it working easily...
Do you have any idea what could be the best approach here ?
This is what worked for me:
app.config(['$resourceProvider', function($resourceProvider) {
$resourceProvider.defaults.stripTrailingSlashes = false;
}]);
services.factory('Project', ['$resource',
function($resource) {
return $resource('api/project/:id/', {}, {
query: {
method: 'GET',
url: 'api/projects/',
isArray: true,
transformResponse: function(data, headers) {
return angular.fromJson(data).results;
},
},
});
}
]);