-
-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: remove all internals from API model #67
Conversation
src/model/parseModelDeclaration.ts
Outdated
if (exactValue) { | ||
if (Array.isArray(exactValue)) { | ||
if (exactValue && relationDefinition) { | ||
const relationPrimarykey = findPrimaryKey( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can assume that primary key exists because we have already checked it when the factory is first created
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. I'd rather parse primaryKey
in parseModelDeclaration
and throw away findPrimaryKey
function. It's confusing why the model that's known is parsed only when an entity is created. Needless to say, that creating new entities doesn't change model declaration's properties or relations. Looks like a design overhaul to me, and I'd like to address it in the follow-up pull request.
fab4c81
to
0b7ec0c
Compare
0b7ec0c
to
5494d02
Compare
Hey, @marcosvega91. Thank you for shipping this! I've rebased the feature branch to include the latest |
This issue is more complicated than it appears. Since we've removed the internal properties from the entity, they are no longer present in the entity instance returned from the model API methods (create/update/etc.): const usa = db.country.create({ name: 'USA' }) This is intended, as we wish for the public entity not to contain internal things. However, this means that relational properties cannot validate what kind of data you pass into them. Consider this: const db = factory({
country: { id: primaryKey(String), name: String },
capital: { id: primaryKey(String), country: oneOf('country') }
})
const usa = db.country.create({ name: 'USA' })
const notCountry = {
id: 'abc-123',
name: 'Made up'
}
// This is OK, as we pass an entity as the reltional value.
db.capital.create({ country: usa })
// However, this is also OK because a non-entity object "notCountry"
// is compatible with its properties, although it's not the correct value to pass
// as it won't get resolved (doesn't have "__type", "__primaryKey", and "__nodeId")
// to look up the relational reference.
db.capital.create({ country: notCountry })
I think we may design the internal logic in a different way, as all the necessary info for the relational lookup is known at the model declaration time: {
country: {
capital: manyOf('capital')
}
} Knowing that the referenced model is "capital" ( @marcosvega91, what do you think about this? Was I successful in explaining the problem? |
3b0fa7e
to
e70fa32
Compare
ah yes, I didn't think about it. When we'll create a new entity we should verify the existence of all relational entities |
@marcosvega91, yeah. I'll separate the concerns and make the relational properties work based on the model definition, without us having to return the data like referenced entity |
e70fa32
to
0cc61dd
Compare
Hey @kettanaito I think I have dropped one of your commit here. The one that you have pushed with the refactor of I have rebase the branch with the current master |
@marcosvega91, no worries. I've applied that refactoring on top of your feature branch. |
…notate custom defined properties
Could you please tell me more about how you replace the entity references in relational properties? Previously, the definition of the relational property produces a short factory({
user: { country: oneOf('country') }
})
user.country // { kind: 'OneOf', modelName: 'country', unique: false } Then, in data/src/model/defineRelationalProperties.ts Lines 31 to 34 in 39c078b
For instance, db.user.create({
country: db.country.create()
// country: { __type: "country", __primaryKey: "id", ...initialValues }
}) With the removal of the internal entity properties like |
I have added the primary key in the |
Awesome! Got it now, thanks for the details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A great improvement. Thank you, @marcosvega91!
This can be useful also for the issue #56, we'll have a better access to all the things we need to generate rest apis using relations |
True! I'm glad this touched relations a little, it will indeed give us more control over them in the future, as all the necessary data to resolve a relation is succinctly available on the |
In this PR I have removed all the internals from API.
To do so I have removed remove coupling of api with itself and add the map transformation on different method returns.
I have also removed the map from the rest handlers because it is already done in the api.
I have created a new
Entity
type, the public one, and replaced the old one withInternalEntity
.GitHub
Changes
Entity
andInternalEntity
.__type
,__primaryKey
, etc.).db[model].create()
return payload).primaryKey
on theRelation
when it's defined by looking it up in the database for the referenced model.Relation
with no internal properties on the actual value (no longer needed, relation contains all the necessary info).