Skip to content

Diff returns all nested changes for additions #2893

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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

jdolle
Copy link
Collaborator

@jdolle jdolle commented Jul 8, 2025

Description

This adds fields that are necessary for recreating the patched schema using the input schema and changes array.
This PR modifies the TypeAdded change type to add a Kind, and modifies the onAdded handlers to also execute equivalent logic to onMutual.

This has a few down sides and an important up side.

Cons

  1. Increased noise when listing changes
  2. Increased complexity because it blurs the line between changes and additions. Although arguably some of the changes did this already.
  3. It requires adjusting some of the criticality of these changes when they are created from within the onAdded call. Because e.g. adding an interface to newly create object is completely safe, but adding an interface to an existing object is considered dangerous.

Pro

  1. Does not require parsing additional change events or nested metadata within addition events.

The best alternative approach I could come up with is to add metadata to the "added" change events. This is doable, but requires essentially recreating all the parsing that is already done in onMutual, and then requires any logic using these events to also recreate logic for adding things to the schema, because for example a field could be added to a type via a FieldAdded change OR within a TypeAdded change. And the structures would not match.
This approach would make the meta data very large also, because it would have to capture interfaces, directives, fields, etc..
However, it would prevent us from polluting the existing change set with more noise.

One final idea I had is to add a configuration option to only call the onMutual logic if a boolean "captureAllChangesOnAdd" is set to true.


An additional change is that multiple changes are no longer returned for the same "node". e.g. When adding a deprecated directive with a reason, the reason field is on the added change, and a "deprecatedReasonAdded" change is no longer emitted.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

See unit tests.

Checklist:

  • I have followed the
    CONTRIBUTING doc and the
    style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@jdolle jdolle requested a review from n1ru4l July 8, 2025 17:41
@jdolle jdolle self-assigned this Jul 8, 2025
newDirective: GraphQLDirective,
): Change<typeof ChangeType.DirectiveDescriptionChanged> {
return directiveDescriptionChangedFromMeta({
type: ChangeType.DirectiveDescriptionChanged,
meta: {
directiveName: oldDirective.name,
oldDirectiveDescription: oldDirective.description ?? null,
directiveName: newDirective.name,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In these cases, the type is being used to extract the name only. It doesn't matter if we pass the new or old directive, since the name is the same. However, since calling these functions onAdd -- the old type can be null, which is why this was changed to pass the new type (newDirective)


{
const change = findFirstChangeByPath(changes, 'enumA.A');
expect(change.criticality.level).toEqual(CriticalityLevel.NonBreaking);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test shows that enum additions also contain all nested changes within that enum, and that those changes are flagged as non-breaking.

@jdolle jdolle force-pushed the type-added-meta branch from 359eea3 to cf7fcfc Compare July 9, 2025 04:40
@@ -218,6 +221,7 @@ export function fieldDeprecationRemovedFromMeta(args: FieldDeprecationRemovedCha
return {
type: ChangeType.FieldDeprecationRemoved,
criticality: {
// @todo: Add a reason for why is this dangerous... Why is it??
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ very curious why... It doesn't change behavior/how clients interact. "Dangerous" seems extreme.

parentType: type,
field: newField,
}),
directiveUsageAdded(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this filter out the deprecated directive since that's captured by another change?

@jdolle jdolle requested a review from dotansimha July 9, 2025 04:50
@jdolle jdolle changed the title Enhance TypeAdded meta data Diff returns all nested changes for additions Jul 9, 2025
@@ -0,0 +1,6 @@
---
'@graphql-inspector/core': major
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be convinced that this is a minor patch because the changes to the output's format doesnt break anything. But the actual content of the changes has changed drastically which is why I thought we should be safe and declare a major change.

return lastDividerIndex === -1 ? path : path.substring(0, lastDividerIndex);
};

export const ignoreNestedAdditions: Rule = ({ changes }) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows us to reduce noise when running the diff. If the parent was added during this change set, then the change will be excluded from the list.
See tests for what this looks like in practice.

@jdolle jdolle marked this pull request as ready for review July 9, 2025 21:33
@jdolle jdolle requested a review from ardatan July 17, 2025 04:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant