-
-
Notifications
You must be signed in to change notification settings - Fork 71
chore(core): streamline object helpers #685
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
Conversation
🦋 Changeset detectedLatest commit: 5518f9c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
|
I'm not sure I fully understand what's happening here? Also, what made you change that? I do think the cleanest object helper we currently have is the cli/packages/addons/eslint/index.ts Lines 110 to 120 in 7848d53
It handles nested object's perfectly fine, has helpers for converting bools, arrays and strings to the appropriate ast alternatives and so on. I do understand that the But as I said, im not fully understanding why this change is done, so let me know if I missed anything. |
|
its to avoid repeating code like this everywhere: const kitConfig = config.properties.find(
(p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'kit'
) as AstTypes.Property | undefined;
// ...
if (kitConfig) {
// override it
} else {
// set a default
}you should be able to use but then when you go beyond one level of nesting, the current if (kitConfig) {
const deepObj = kitConfig.properties.find(...);
if (deepObj) {
const deeperObj = deepObj.properties.find(...);
// ...
} else {
// ...
}
} else {
// ...
}it'd be cleaner to be able to: overrideProperty(config, {
path: ['kit', 'deepObj', 'deeperObj'],
value: whatever
});which entirely replaces the big block of if/else chains |
|
Yeah, that totally makes sense, but isn't that what |
Yes, but not in a nested way. now you have |
|
for example, you had to do this (pseudo code): const kit = object.property(obj, {
name: 'kit',
fallback: {}
});
const deepObj = object.property(kit, {
name: 'deepObj',
fallback: {}
});
const deepestObj = object.overrideProperty(deepObj, {
name: 'deepestObj',
value: 303
});to produce: {
kit: {
deepObj: {
deepestObj: 303
}
}
}but now you can: object.overrideProperty(obj, {
path: ['kit', 'deepObj', 'deepestObj'],
value: 303
}); |
|
Thank you, I did finally understand it. Now my last question is if we are able to and want to align it further with the const arrayOfFancyAstNodes = array.create();
const bla = object.create({
foo: {
bar: 'test',
baz: arrayOfFancyAstNodes
},
test: true
});Your last example would look like this: object.overrideProperty(obj, {
kit: {
deepObj: {
deepesteObj: 303
}
}
});IMO, this would make it even simpler and align with the create syntax even more. We could probably even share some code with |
|
so the difference would be that we pass an object as input? the implementation of basically: for (const prop of inputObj) {
if (isObject(inputObj[prop])) {
// recursively do this overall algo
} else {
overrideProperty(originalObj, {property: prop, value: inputObj[prop]});
}
}if i understood correctly, that makes sense to me 👍 |
|
When I have: const obj = {
hello: 'world',
kit: {}
}and then do object.overrideProperty(obj, {
kit: {
deepObj: {
deepesteObj: 303
}
}
});I'm a bit worried that In the end, I don't really mind, if you prefer the object you can do 👍, I just gave my 2 cents :D |
manuel3108
left a comment
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.
Ok, I have made the changes I suggested earlier. I think it turned out great, but let me know what you think.
Also i removed the export for object.overrideProperty as it had only a few usages and basically the same problem as discussed above.
| (property) => { | ||
| if ( | ||
| property.key.type !== 'Identifier' || | ||
| property.key.name !== 'adapter' || | ||
| adapter.package === '@sveltejs/adapter-auto' | ||
| ) | ||
| return property; | ||
|
|
||
| // reset the comment for non-auto adapters | ||
| property.leadingComments = []; | ||
| return property; | ||
| } |
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.
This is the only thing, I'm not super happy about. For one, I don't like that this is just a third argument as a function, should probably be an object.
Additionally this is now executed for every property along the path, that's why the additional checks are needed.
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.
using object.create like syntax is maybe not that bad.
// array style
[ { name: 'id', value: '007' } ]
// object.create syntax (nice & short)
{ id: '007' }
// alternative (shorter, I like, but maybe less readable)
[ ['id', '007'] ]third argument as a function, should probably be an object
As it's optional, and not used a lot I think that this is ok.
this is now executed for every property along the path
This is more problematic IMO. What about { a: { b: { a: true } } }, we will have 2 key.name of a.
I'm not sure I have a lot of proposal. Maybe we could have a transformProperty taking also the same api, but with a selector of where to do the transform?
if(adapter.package !== '@sveltejs/adapter-auto'){
object.transformProperty(
config,
{ kit: { adapter: true } }, // selector ?
(property) => {
property.leadingComments = [];
return property;
}
);
}Or the previous way ? Or the previous alternative way ?
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.
I do think that could work. But is it worth the effort?
We could also only run that function on leaf nodes, but then we would need to think about a better naming for this.
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.
I though about leaf nodes but:
{
b: { a: true },
c: { a: '1' }
} Both are leaf, and both are 'a'.
Not easy 😅
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.
okay, you got me
Any reason you decided against something like that in your last example? I think that would make it even more clear. I did not check if can convince typescript, but it should work just fine
if(adapter.package !== '@sveltejs/adapter-auto'){
object.transformProperty(
config,
{ kit: { adapter: (property) => { /* ... */ } } }
);
}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.
not to throw a spanner in the works - but we could also not do it 😅
i'd have to read through the codebase again, but iirc we don't need this often. we use it to clear leading comments usually
so you could just do this at the callsite:
object.overrideProperty(config, {
kit: {
adapter: {
foo: 303
}
}
});
// probably turn this into a helper or make property accept a path
object.property(
object.property(config, 'kit'),
'adapter'
).leadingComments = [];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.
The question is: "Why do I like these?!" 😅
I added a few more tests to cover some more usecases.
Starting to look good. No?!
Let me know
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.
Acutally,
object.overrideProperty(config, {
kit: {
adapter: {
foo: 303
}
}
});Will already reset leading comments (as it's done today, maybe it could be better?!)
And it's not what we want here.
I see: object.overrideProperty as the nice and easy API
and object.transformProperty where you can do everything.
But looking at your comment, I like the simplicity! :o
Going out a bit...
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.
are you sure? overrideProperty will replace the value (of foo in this case), but not the property node itself as far as i remember
this code was previously clearing the leading comments of the adapter property, and setting the value to a new function
but we rarely do this so i think it makes more sense to keep overrideProperty simple and just clear the property's leading comments separately
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.
I added test for overrideProperty and yes you are right, it's only the value.
I removed transformProperty as it was for a very specific case, and added a small helper propertyNode that will do the nice adapter thing.
//Happy
This reverts commit 52961f0.
manuel3108
left a comment
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.
Thanks!
Will simplify in general & reduce the api surface.
To be merged before: #680