I have a Loopback API in which I have a container and I'm trying to add some relations to my models (using this) but when it comes to adding relations to container.js, it does not work anymore and I get this error :
/home/mowso/Documents/loopback-examples/test/node_modules/loopback-datasource-juggler/lib/datasource.js:434
modelClass[relation.type].call(modelClass, name, params);
^
TypeError: Cannot read property 'call' of undefined
at EventEmitter.<anonymous> (/home/mowso/Documents/loopback-examples/test/node_modules/loopback-datasource-juggler/lib/datasource.js:434:36)
at EventEmitter.g (events.js:260:16)
at emitOne (events.js:77:13)
at EventEmitter.emit (events.js:169:7)
at DataSource.setupDataAccess (/home/mowso/Documents/loopback-examples/test/node_modules/loopback-datasource-juggler/lib/datasource.js:540:14)
at DataSource.attach (/home/mowso/Documents/loopback-examples/test/node_modules/loopback-datasource-juggler/lib/datasource.js:752:8)
at Function.ModelClass.attachTo (/home/mowso/Documents/loopback-examples/test/node_modules/loopback-datasource-juggler/lib/model-builder.js:336:16)
at Registry.configureModel (/home/mowso/Documents/loopback-examples/test/node_modules/loopback/lib/registry.js:238:15)
at configureModel (/home/mowso/Documents/loopback-examples/test/node_modules/loopback/lib/application.js:441:16)
at EventEmitter.app.model (/home/mowso/Documents/loopback-examples/test/node_modules/loopback/lib/application.js:133:5)
I have three models like in the example I link above, they basically just have different names. Here is my container.json :
{
"name": "Container",
"base": "PersistedModel",
"properties": {
"name": {
"type": "string"
}
},
"validations": [],
"relations": {
"user": {
"type": "belongsTo",
"model": "user",
"foreignKey": "ownerId"
}
},
"acls": [],
"methods": {}
}
and my user.json :
{
"name": "user",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"containers": {
"type": "hasOne",
"model": "Container",
"foreignKey": "ownerId"
},
"companies": {
"type": "hasOne",
"model": "company",
"foreignKey": "ownerId"
}
},
"acls": [],
"methods": {}
}
Here is the model-config.json :
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false
},
"Role": {
"dataSource": "db",
"public": false
},
"Container": {
"dataSource": "myfile",
"public": true
},
"user": {
"dataSource": "db",
"public": false
},
"company": {
"dataSource": "db",
"public": false
}
}
and finally my datasource.json, notice that I have a storage folder at the root of my project :
{
"db": {
"name": "db",
"connector": "mongodb"
},
"myfile": {
"name": "myfile",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "storage"
}
}
Your foreign key is not correct, as per the documentation it should be,
Relation name: Camel case of the model name, for example, for the "supplier" model the relation is "supplier".
Foreign key: The relation name appended with ‘Id’, for example, for relation name "supplier" the default foreign key is "supplierId".
So in your case it should be
"foreignKey": "userId"
https://docs.strongloop.com/display/public/LB/HasOne+relations
And you should use the slc relations instead of editing the json files.
I believe Container should inherit Model, not PersistedModel. By default, a Container is a folder inside a filesystem, so there is no choice of persisting it or not.
{
"name": "Container",
"base": "Model",
Related
I am creating loopback applications with mysql . I set out the datasource will be mysql but when i run the applications i got following error in console windows .
ReferenceError: Cannot create data source "shop": Cannot initialize connector "mysql": time is not defined
Here is my datasource.json code .
{
"db": {
"name": "db",
"connector": "memory"
},
"shop": {
"host": "localhost",
"port": 8081,
"url": "",
"database": "shoppingdatabase",
"password": "",
"name": "shop",
"user": "root",
"connector": "mysql",
"connectTimeout":9000000
}
}
Here is the code for model.json
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
},
"carts": {
"dataSource": "shop",
"public": true
},
"products": {
"dataSource": "shop",
"public": true
},
"users": {
"dataSource": "shop",
"public": true
},
"vendors": {
"dataSource": "shop",
"public": true
}
}
Here is the screen shot when i run the server .
Change your datasource.json as :
{
"db": {
"host": "localhost",
"port": 3306,
"url": "",
"database": "shoppingdatabase",
"password": "",
"name": "db",
"user": "root",
"connector": "mysql",
"connectTimeout":9000000
}
}
and model.json as
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
},
"carts": {
"dataSource": "db",
"public": true
},
"products": {
"dataSource": "db",
"public": true
},
"users": {
"dataSource": "db",
"public": true
},
"vendors": {
"dataSource": "db",
"public": true
}
}
and before that create a database in MySQL manually with the name "shoppingdatabase" as loopback will need the database pre-created.
And keep it password protected too.
I created a task that talks to a REST API to retreive the values for 2 picklists.
Filling the first dropdown box works fine, when using just the jsonpath.
Based on the first picklist I'd like to retreive values of the second list.
I've tried some variations and I'm trying something like this:
The json which I receive in the first rest call is similar to:
{
"id": "45",
"href": "https://selfservice/api/configurations/45/",
"name": "Type",
"description": "",
"version": "0.0.4",
"attributes": [
{
"value": {
"sdk-object": {
"type": "ConfigurationElement",
"id": "56"
}
},
"type": "ConfigurationElement",
"name": "win"
},
{
"value": {
"sdk-object": {
"type": "ConfigurationElement",
"id": "57"
}
},
"type": "ConfigurationElement",
"name": "lin"
}
]
}
I try to show the attributes name in the list and need the id of the attribute in the second picklist.
I created the following datasourcebindings in the task.json. Of course, the targets exist in the task.
task.json:
{
"id": "GUID",
"name": "Spinup",
"friendlyName": "Create environment",
"description": "Starts Workflow to create an environment. ___ The following placeholders are created deplending on the template and can be used in the rest of the release:**XLDEnvironment** and **testAgentHostname**",
"category": "Deploy",
"author": "***",
"version": {
"Major": 0,
"Minor": 0,
"Patch": 33
},
"minimumAgentVersion": "1.95.3",
"inputs": [
{
"label": "Endpoint",
"name": "connectedServiceName",
"required": true,
"type": "connectedService:server",
"helpMarkDown": "endpoint to connect to."
},
{
"name": "stage",
"type": "string",
"label": "Stage",
"defaultValue": "$(Release.EnvironmentName)",
"required": true,
"helpMarkDown": "Stage of the release, default value is based on the pipeline."
},
{
"name": "releaseName",
"type": "string",
"label": "Environment name",
"defaultValue": "$(Release.ReleaseName)",
"required": true,
"helpMarkDown": "Name of the environment that will be created."
},
{
"name": "owner",
"type": "string",
"label": "Owner of the environment",
"defaultValue": "***",
"required": true,
"helpMarkDown": "It is common to use the initials of the product owner in this field. There has to be a valid AD user owner of each environment. This can also be set by using a variable through the pipeline."
},
{
"name": "group",
"type": "string",
"label": "Group of the owner",
"defaultValue": "",
"required": true,
"helpMarkDown": "group that owns the environment. groups can be requested by the infrastructure department. Example: ****"
},
{
"name": "platform",
"type": "pickList",
"label": "Platform (OS)",
"defaultValue": "",
"required": true,
"helpMarkDown": "Choose the type of the target platform."
},
{
"name": "size",
"type": "pickList",
"label": "Environment Template",
"defaultValue": "",
"required": true,
"helpMarkDown": "Size of the environment to create."
}
],
"dataSourceBindings": [
{
"dataSourceName": "GetCEPlatformType",
"endpointId": "$(connectedServiceName)",
"target": "platform",
"selector": "jsonpath:$.attributes[*].name",
"keySelector": "jsonpath:$.attributes[*].value.sdk-object.id"
},
{
"dataSourceName": "GetCEPlatformSize",
"endpointId": "$(connectedServiceName)",
"target": "size",
"parameters": {
"platformTypeId": "$(platform)"
}
}
],
"instanceNameFormat": "Spin up $(size) $(platform) environment",
"execution": {
"PowerShell3": {
"target": "$(currentDirectory)\\task.ps1",
"argumentFormat": "",
"workingDirectory": "$(currentDirectory)"
}
}
}
vss-extension.json:
{
"manifestVersion": 1,
"id": "*****",
"name": "Release Tasks",
"version": "1.0.1",
"publisher": "***",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"description": "Tools to contact ***. Includes a task to spin up a platform and a task to remove the platform.",
"categories": [
"Build and release"
],
"icons": {
"default": "images/extension-icon.png"
},
"files": [
{
"path": "RemoveEnvironment"
},
{
"path": "SpinUpEnvironment"
}
],
"contributions": [
{
"id": "******",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "RemoveEnvironment"
}
},
{
"id": "*********",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "SpinUpEnvironment"
}
},
{
"description": "Service Endpoint type for all connections",
"id": "endpoint-type",
"properties": {
"authenticationSchemes": [
{
"inputDescriptors": [
{
"description": "Username",
"id": "username",
"inputMode": "textbox",
"name": "Username",
"validation": {
"dataType": "string",
"isRequired": true
}
},
{
"description": "Password",
"id": "password",
"inputMode": "passwordbox",
"isConfidential": true,
"name": "Password",
"validation": {
"dataType": "string",
"isRequired": false
}
}
],
"type": "ms.vss-endpoint.endpoint-auth-scheme-basic"
}
],
"dataSources": [
{
"endpointUrl": "api/configurations/*****/",
"name": "GetCEPlatformType",
"resultSelector": "jsonpath:$.attributes[*].name"
},
{
"endpointUrl": "api/configurations/$(platformTypeId)/",
"name": "GetCEPlatformSize",
"resultSelector": "jsonpath:$.attributes[*].name"
}
],
"displayName": "*****",
"helpMarkDown": "Enter the url and credentials to connect to the endpoint.",
"name": "server",
"url": {
"displayName": "Server URL",
"helpText": "Url for the server to connect to."
}
},
"targets": [
"ms.vss-endpoint.endpoint-types"
],
"type": "ms.vss-endpoint.service-endpoint-type"
}
]
}
Sadly I can't get this to work. The datasources exist in the endpoint, but I'm not sure what to do with the resultSelector.
Does anyone have an idea on how to get this to work? The documentation on this isn't too good.
I'm not familiar with mustache, but in the mustache test tool this seems to work.
Thoughts are appreciated!
Try with this in the first data source:
{
"dataSourceName": "dsList1",
"endpointId": "$(connectedServiceName)",
"target": "list1",
"selector": "jsonpath:$.attributes[*].name",
"keySelector": "jsonpath:$.attributes[*].value.sdk-object.id"
}
Update:
You were trying to use "platformTypeId" in vss-extension.json file while it was defined in task.json, this cause the error message you mentioned in the comment.
By the way, I just noticed that you are using "dataSourceBindings", then you cannot use "selector" and "KeySelector" to parse the result since they are used for "sourceDefinitions".
To achieve the feature you want with "dataSourceBindings", you can definition the endpoint url in the task.json directly instead of defining datasource in endpoint contribution.
So you can move the datasources section in the vss-extension.json file first, and then in the task.json file, change to following:
"dataSourceBindings": [
{
"endpointId": "$(connectedServiceName)",
"endpointURL": "api/configurations/*****/",
"target": "platform",
"resultselector": "jsonpath:$.attributes[*]",
"resultTemplate": "{ \"Value\" : \"{{{value.id}}}\", \"DisplayValue\" : \"{{{name}}}\" }"
},
{
"endpointId": "$(connectedServiceName)",
"endpointURL": "api/configurations/$(platformTypeId)/",
"target": "size"
}
],
I'm just learn about Loopback from StrongLoop to create a simple API.
I got some trouble to make the API works.
Here is my config :
model.js
--------
'use strict';
module.exports = function(Account) {
};
This is my model.json:
{
"name": "Account",
"base": "PersistedModel",
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "string",
"required": true,
"defaultFn": "uuidv4",
"postgresql": {
"columnName": "id",
"dataType": "uuid"
}
},
"code": {
"type": "string",
"required": true,
"postgresql": {
"columnName": "code",
"dataType": "character varying",
"dataLength": "50"
}
},
"name": {
"type": "string",
"required": true,
"postgresql": {
"columnName": "name",
"dataType": "text"
}
},
"type": {
"type": "string",
"required": true,
"postgresql": {
"columnName": "type",
"dataType": "character varying",
"dataLength": "50"
}
},
"isActive": {
"type": "boolean",
"required": true,
"default": true
},
"isDelete": {
"type": "boolean",
"required": true,
"default": false
},
"createdBy": {
"type": "string",
"required": true,
"defaultFn": "uuidv4",
"postgresql": {
"columnName": "createdBy",
"dataType": "uuid"
}
},
"updatedBy": {
"type": "string",
"required": true,
"defaultFn": "uuidv4",
"postgresql": {
"columnName": "updatedBy",
"dataType": "uuid"
}
},
"createdAt": {
"type": "date",
"required": true,
"defaultFn": "now"
},
"updatedAt": {
"type": "date",
"required": true,
"defaultFn": "now"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
The following model have been migrated successfull, I'm using postgresql for my db.
The problem is when Loopback create the CRUD standard API, the POST API seem to not working when I try the POST method. below is my json string when i try to put on API explorer :
{
"id": "123e4567-e89b-12d3-a456-426655440000",
"code": "1000",
"name": "Cash and Bank",
"type": "Assets",
"isActive": true,
"isDelete": false,
"createdBy": "123e4567-e89b-12d3-a456-426655440000",
"updatedBy": "123e4567-e89b-12d3-a456-426655440000",
"createdAt": "2017-09-01T17:00:00.000Z",
"updatedAt": "2017-09-01T17:00:00.000Z"
}
But It throw an error, here is the response body :
{
"error": {
"statusCode": 500,
"name": "error",
"message": "syntax error at end of input",
"length": 92,
"severity": "ERROR",
"code": "42601",
"position": "230",
"file": "scan.l",
"line": "1078",
"routine": "scanner_yyerror",
"stack": "error: syntax error at end of input\n at Connection.parseE (/media/andylpjr/EA7C669F7C6665F3/Project/kpost/kpost-api/node_modules/pg/lib/connection.js:567:11)\n at Connection.parseMessage (/media/andylpjr/EA7C669F7C6665F3/Project/kpost/kpost-api/node_modules/pg/lib/connection.js:391:17)\n at Socket.<anonymous> (/media/andylpjr/EA7C669F7C6665F3/Project/kpost/kpost-api/node_modules/pg/lib/connection.js:129:22)\n at emitOne (events.js:96:13)\n at Socket.emit (events.js:191:7)\n at readableAddChunk (_stream_readable.js:178:18)\n at Socket.Readable.push (_stream_readable.js:136:10)\n at TCP.onread (net.js:561:20)"
}
}
For the note when I'm try from the pgadmin insert to table using SQL query it works. Something like "INSERT INTO Account VALUES (bla bla bla)". I know this maybe just a common mistake, please help. Sorry for bad english.
Well case closed, it appears I'm missing my model definition for primary key, what a shame.. Thanks guys.
I made a website with nodejs and strongloop. I used the mysql connector and tested the connection in Strongloop Arc. The connection is OK. I created the models with the arc tool (discover models). It was also OK.
But when I open the Strongloop API Explorer and do the test to get the data I Always get the error:
"ER_NO_DB_ERROR: No database selected".
Have you confirmed that your model was connected to dbAuction instead of db?
When using arc to add a model, the 'datasource' should be 'dbAuction'.
You can also check the model-config.json in 'server/' directory. A property named 'dataSource' belongs to the model name like
"modelname" : {
"dataSouce":"dbAuction"
...
},
...
This is the model-config.json
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false
},
"Role": {
"dataSource": "db",
"public": false
},
"newModel": {
"dataSource": "db",
"public": true
},
"Biedingen": {
"dataSource": "dbAuction",
"public": true
},
"Kavel": {
"dataSource": "dbAuction",
"public": true
},
"Gebruikers": {
"dataSource": "dbAuction",
"public": true
},
"Message": {
"dataSource": "dbAuction",
"public": true
},
"Veilingen": {
"dataSource": "dbAuction",
"public": true
},
"Sourcemessage": {
"dataSource": "dbAuction",
"public": true
},
"Veilingenkavels": {
"dataSource": "dbAuction",
"public": true
},
"Veilingsoorten": {
"dataSource": "dbAuction",
"public": true
}
and the datasources.json
{
"db": {
"name": "db",
"connector": "mysql"
},
"dbAuction": {
"host": "localhost",
"port": 3306,
"database": "auctions",
"password": "",
"name": "dbAuction",
"connector": "mysql",
"user": "root"
}
}
I can't add a comment since my reputation is too low..
I suggest you can change the 'mysql' in
"db": {
"name": "db",
"connector": "**mysql**"
into "memory" as it was initiated because the "db" is useful for some models while you changed wrongly so that 'db' cannot work well, which may lead to this problem.
I am very new to loopback. I am making my first app with it and I change my datasource to MySql. my person model look like this
person.json
{
"name": "Person",
"plural": "People",
"base":"User",
"properties": {
"firstName": {
"type": "string",
"required": true
},
"lastName": {
"type": "string",
"required": true
},
"username": {
"type": "string",
"required": true
},
"email": {
"type": "string",
"required": true
},
"password": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"accessType": "*"
}
],
"methods": []
}
and
datasource.json
{
"db": {
"name": "db",
"connector": "memory"
},
"mysql": {
"host": "localhost",
"port": 3306,
"database": "demo",
"username": "demouser",
"password": "****",
"name": "mysql",
"connector": "mysql"
}
}
and
model-config.json
{
"_meta": {
"sources": [
"../common/models",
"./models"
]
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false
},
"Role": {
"dataSource": "db",
"public": false
},
"Person": {
"dataSource": "mysql",
"public": true
}
}
After this when I want to create any person I cant create any person as I am unauthorized. I inserted an entry in mysql and tried to login but no luck.But when I remove User as base of person then all goes fine. But I lose all auth features inherit from User. How can I extend User using mysql as datasource properly so that I can use Person as my Users?
Thanks in Advance
Can you try to add the following ACL?
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"accessType": "*",
"property": "create"
}
],
You can debug the application using:
DEBUG=loopback:security:* node .