Closed metamono closed 5 years ago
Cross-posting my recent answer from StackOverflow (https://stackoverflow.com/a/53655494/69868).
This looks like a limitation of the current implementation in loopback-datasource-juggler and/or the way how LoopBack 4 translates LB4 model definitions to Juggler models.
The error is triggered by this code:
// Assume the type constructor handles Constructor() call
// If not, we should call new DataType(value).valueOf();
this.__data[propertyName] = (value instanceof DataType) ? value : DataType(value);
Juggler assumes that types (models) are defined as ES5 functions which can be called either with or without new
. However, LB4 models are implemented as ES6 classes, which must be always constructed using new
keyword.
I think there are two options, they are not mutually exclusive:
DataType
functions that are ES6 class constructors. UPDATE: See https://github.com/strongloop/loopback-datasource-juggler/pull/1670 for a work that's already in progress.Possibly related: https://stackoverflow.com/q/52939388/69868
Cross-posting the relevant bits here:
@property.array(PhoneNumber)
phoneNumbers: PhoneNumber[];
In the above example, I get full schema validation, but if I try to save an instance of Contact using a generated Repository that extends DefaultCrudRespository, it just drops whatever was provided in the phoneNumbers field and saves an empty column in the db.
If I change the property annotation to:
@property.array(Object)
phoneNumbers: PhoneNumber[];
It will save the field properly, serialized as json, but it won't attempt to validate the field, and also won't specify the type as an array PhoneNumber in the generated openapi.json spec
any update on this? I want to have similar setup but it fails with a different error.
my setup is like the following
// .../models/user.model.ts
@model()
class Address {
@property()
country: string;
@property()
city: string;
}
@model()
export class User extends Entity{
// ...
@property()
address: Address
// ...
}
I get the following error when I execute any find/findOne/findById
methods:
TypeError: Cannot read property 'properties' of undefined
at MongoDB.fromDatabase (.../loopback-connector-mongodb/lib/mongodb.js:371:25)
at MongoDB.fromDatabase (.../loopback-connector-mongodb/lib/mongodb.js:396:22)
any update on this? I want to have similar setup but it fails with a different error.
my setup is like the following
// .../models/user.model.ts @model() class Address { @property() country: string; @property() city: string; } @model() export class User extends Entity{ // ... @property() address: Address // ... }
I get the following error when I execute any
find/findOne/findById
methods:TypeError: Cannot read property 'properties' of undefined at MongoDB.fromDatabase (.../loopback-connector-mongodb/lib/mongodb.js:371:25) at MongoDB.fromDatabase (.../loopback-connector-mongodb/lib/mongodb.js:396:22)
have you find any update for this issue
@bajtos @aetheric8 @tamer-mohamed @fabien @rmg need help
hello @techaks, we are also waiting on a solution. Temporarily we use the loopback-3 approach
Now that juggler has been improved to support ES6 classes in nested properties (see https://github.com/strongloop/loopback-datasource-juggler/pull/1670), let's find out what's needed to make that feature work in LB4 too.
The following code snippet from an earlier comment looks reasonable to me - I don't see any obvious error there:
@model()
class Address {
@property()
country: string;
@property()
city: string;
}
@model()
export class User extends Entity{
// ...
@property()
address: Address
// ...
}
Based on the comments above, it looks like this setup does not work with the MongoDB connector. How about other connectors like memory
or mysql
? Can the issue be reproduced there too?
In general, it would be very helpful if somebody could create a small application reproducing the problem - see our bug reporting instructions.
Actually we already have a pull request opened to fix the problem - see https://github.com/strongloop/loopback-next/pull/2505
HI @bajtos i ran test of embedded models for nested properties but face to an error!
Post Model:
// ...
@model()
class Review extends Entity {
@property()
rate: Number;
@property()
gender: String;
}
// ...
@model()
export class Post extends Entity {
@property({
type: 'string',
id: true,
required: true,
generated: true,
})
id: string;
@property({
type: 'string',
})
title?: string;
@property()
review: Review;
constructor(data?: Partial<Post>) {
super(data);
}
}
// ...
as #2505 pull request this model must be okay and work,
but when i hit npm start
i getting the below error:
$ npm start
> test@1.0.0 prestart E:\Projects\_lb4\test
> npm run build
> test@1.0.0 build E:\Projects\_lb4\test
> lb-tsc
> test@1.0.0 start E:\Projects\_lb4\test
> node -r source-map-support/register .
Cannot start the application. RangeError: Maximum call stack size exceeded
at baseIteratee (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:3458:26)
at getIteratee (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:5926:33)
at Function.mapValues (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:13398:18)
at jsonToSchemaObject (E:\Projects\_lb4\test\node_modules\@loopback\openapi-v3\src\json-to-schema.ts:72:31)
at result.definitions._.mapValues.def (E:\Projects\_lb4\test\node_modules\@loopback\openapi-v3\src\json-to-schema.ts:67:11)
at E:\Projects\_lb4\test\node_modules\lodash\lodash.js:13401:38
at E:\Projects\_lb4\test\node_modules\lodash\lodash.js:4905:15
at baseForOwn (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:2990:24)
at Function.mapValues (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:13400:7)
at jsonToSchemaObject (E:\Projects\_lb4\test\node_modules\@loopback\openapi-v3\src\json-to-schema.ts:66:32)
at result.definitions._.mapValues.def (E:\Projects\_lb4\test\node_modules\@loopback\openapi-v3\src\json-to-schema.ts:67:11)
at E:\Projects\_lb4\test\node_modules\lodash\lodash.js:13401:38
at E:\Projects\_lb4\test\node_modules\lodash\lodash.js:4905:15
at baseForOwn (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:2990:24)
at Function.mapValues (E:\Projects\_lb4\test\node_modules\lodash\lodash.js:13400:7)
at jsonToSchemaObject (E:\Projects\_lb4\test\node_modules\@loopback\openapi-v3\src\json-to-schema.ts:66:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! test@1.0.0 start: `node -r source-map-support/register .`
npm ERR! Exit status 1
It's better to mention that I tested with mongodb
and memory
connectors and both of them had the same error result.
also, I tried to find out an error flow to fixed this issue but I didn't find any relevant flow to fix it.
Hi,
I'm experiencing the same error described above by @HMarzban . Any news on that?
Maybe it's related to https://github.com/strongloop/loopback-next/pull/3897
HI @raymondfeng, I fount out that this problem comes from openapi package!
// controller
@post('/posts')
async create(
@requestBody({
content: {
'application/json':
{
schema: getModelSchemaRef(Post, { title: "PostSchema" })
}
}
})
post: Omit<Post, 'id'>,
): Promise<Post> {
return this.postRepository.create(post);
}
all these error comes from this line schema: getModelSchemaRef(Post, { title: "PostSchema" })
with some digging found out that the title
makes a problem when we use embedded models for nested properties.
e.g.
// model
@model()
class Category{
@property({
type: 'string',
})
name?: string;
@property({
type: 'string',
})
desc?: string;
}
@model()
export class Post extends Entity {
@property({ type: 'number', id: true, required: true, generated: true, })
id: number;
@property({ type: 'string', })
title?: string;
@property({ type: 'string', })
content?: string;
@property()
category: Category;
constructor(data?: Partial<Post>) {
super(data);
}
}
// controller
export class PostController {
constructor(
@repository(PostRepository)
public postRepository: PostRepository,
) { }
@post('/posts')
async create(
@requestBody({
content: {
'application/json':
{
schema: getModelSchemaRef(Post, { title: "Postschema" })
}
}
})
post: Omit<Post, 'id'>,
): Promise<Post> {
return this.postRepository.create(post);
}
}
regularly when I don't use the embedded model the getJsonSchemaRef()
which located in @loopback\repository-json-schema\src\build-schema.ts
retrieve some things like this:
{
title: 'Postschema',
description: '(Schema options: { title: \'Postschema\' })',
properties:
{
id: { type: 'number' },
title: { type: 'string' },
content: { type: 'string' },
catagory: { type: 'string' }
},
required: ['id']
}
but wen embedded model comes to the road the function retrieve some things like this:
{
'$ref': '#/definitions/Postschema',
definitions:
{
Catagory:
{
title: 'Postschema',
description: '(Schema options: { title: \'Postschema\' })',
properties: [Object],
required: [Array],
definitions: [Object]
},
Postschema:
{
title: 'Postschema',
description: '(Schema options: { title: \'Postschema\' })',
properties: [Object],
required: [Array]
}
}
}
this new schema makes all problem and create infinity loop, in @loopback\openapi-v3\src\json-to-schema.ts
file and jsonToSchemaObject()
function.
I hope this digging make some help 😊
@HMarzban is the issue fixed now that #3897 has been landed? If not then please open a new GitHub issue.
Description / Steps to reproduce / Feature proposal
This issue was discussed at stackoverflow.
An error occurs on create if nested entities are defined.
Current Behavior
on create of an entity with a nested child (or more), an error occurs:
if the nested entity was included like this:
Expected Behavior
The objective of this was to get nested entities, which
Even more helpful would be to use jsonSchema for the datamodel and get the described features like autocomplete, typesafety if this is possible anyhow.