Properties with dots in their name are treated as paths instead of as literals
VanTanev opened this issue · comments
Given the following code:
export const db = factory({
user: {
'employee.id': primaryKey(() => 'abc-123'),
}
})
db.user.create({ 'employee.id': 'some-id' })
We get this error:
Uncaught (in promise) OperationError: Failed to create a "user" entity: expected the primary key "employee.id" to have a value, but got: undefined
at new OperationError (OperationError.js:28)
at Object.create (factory.js:66)
This is because createModel uses lodash/set
, which converts dot strings to deep properties (eg, among others):
Lines 58 to 65 in c4a5208
The resulting model object is:
const user: {
employee: {
id: <primaryKey>
}
}
// instead of
const user: {
'employee.id': <primaryKey>
}
I think that lodash/set
is a poor fit, because properties with dots in them are completely valid. Is there any reason it was used other than convenience?
Hey, @VanTanev. Thanks for reporting this.
lodash.set
was used to support nested objects (#113). Internally, we keep a flat map of deep object keys and use set
to properly construct the end entities based on the model.
That's a valid concern that model properties that contained dots initially will be treated as nested properties by lodash. We need to account for such properties.
I suggest we preserve the original model properties by wrapping them in []
before passing to .set
.
set(target, '["a.b.c"]', value)
// { "a.b.c": value }
This change will affect the following functions:
Lines 59 to 63 in c4a5208
Line 80 in c4a5208
Line 85 in c4a5208
We need also be careful about definePropertyAtPath
:
data/src/utils/definePropertyAtPath.ts
Line 24 in c4a5208
@VanTanev, would you be interested in opening a pull request with the fix? Adding a simple integration test that fails at the moment would be a great start. Let me know if this interests you, I'd be happy to help you during the code review.
It's worth analyzing if nested objects are needed in createModel
to begin with. Perhaps we can use plain property assignment there and utilize deep objects when creating entities.
Hey @kettanaito, I have already implemented this in #152. Is there anything you need me to improve?
@VanTanev, thank you for your work on that! I've seen the pull request, will review it as soon as I've got a spare minute. Looking forward to having this issue resolved.