(filename: string)
| 96 | * @param filename path of the file |
| 97 | */ |
| 98 | const JSONDiffForFile = async (filename: string) => { |
| 99 | const patchObject = await JSONPatchForFile(filename) |
| 100 | |
| 101 | if (!patchObject) { |
| 102 | return {} |
| 103 | } |
| 104 | |
| 105 | // Thanks to @wtgtybhertgeghgtwtg for getting this started in #175 |
| 106 | // The idea is to loop through all the JSON patches, then pull out the before and after from those changes. |
| 107 | |
| 108 | const { diff: outerDiff, before, after } = patchObject |
| 109 | return outerDiff.reduce((accumulator, { path }) => { |
| 110 | // We don't want to show the last root object, as these tend to just go directly |
| 111 | // to a single value in the patch. This is fine, but not useful when showing a before/after |
| 112 | const pathSteps = path.split("/") |
| 113 | const backAStepPath = pathSteps.length <= 2 ? path : pathSteps.slice(0, pathSteps.length - 1).join("/") |
| 114 | |
| 115 | const diff: any = { |
| 116 | // If a file is moved/renamed, the file will be in "danger.git.modified_files" |
| 117 | // JSONPatchForFile will return null for the old file, so we need to check for that |
| 118 | before: (before && jsonpointer.get(before, backAStepPath)) || null, |
| 119 | after: (after && jsonpointer.get(after, backAStepPath)) || null, |
| 120 | } |
| 121 | |
| 122 | const emptyValueOfCounterpart = (other: any) => { |
| 123 | if (Array.isArray(other)) { |
| 124 | return [] |
| 125 | } else if (isobject(diff.after)) { |
| 126 | return {} |
| 127 | } |
| 128 | return null |
| 129 | } |
| 130 | |
| 131 | const beforeValue = diff.before || emptyValueOfCounterpart(diff.after) |
| 132 | const afterValue = diff.after || emptyValueOfCounterpart(diff.before) |
| 133 | |
| 134 | // If they both are arrays, add some extra metadata about what was |
| 135 | // added or removed. This makes it really easy to act on specific |
| 136 | // changes to JSON DSLs |
| 137 | |
| 138 | if (Array.isArray(afterValue) && Array.isArray(beforeValue)) { |
| 139 | const arrayBefore = beforeValue as any[] |
| 140 | const arrayAfter = afterValue as any[] |
| 141 | |
| 142 | diff.added = arrayAfter.filter((o) => !includes(arrayBefore, o)) |
| 143 | diff.removed = arrayBefore.filter((o) => !includes(arrayAfter, o)) |
| 144 | // Do the same, but for keys inside an object if they both are objects. |
| 145 | } else if (isobject(afterValue) && isobject(beforeValue)) { |
| 146 | const beforeKeys = Object.keys(beforeValue) as string[] |
| 147 | const afterKeys = Object.keys(afterValue) as string[] |
| 148 | diff.added = afterKeys.filter((o) => !includes(beforeKeys, o)) |
| 149 | diff.removed = beforeKeys.filter((o) => !includes(afterKeys, o)) |
| 150 | } |
| 151 | |
| 152 | jsonpointer.set(accumulator, backAStepPath, diff) |
| 153 | return accumulator |
| 154 | }, Object.create(null)) |
| 155 | } |
nothing calls this directly
no test coverage detected