Skip to content

Commit e26afb1

Browse files
committed
Merge branch 'chore/locked-update-diff' into feat/gui-view-hidden
2 parents 4335574 + 470ddf5 commit e26afb1

File tree

3 files changed

+100
-86
lines changed

3 files changed

+100
-86
lines changed

package-lock.json

Lines changed: 2 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.0.98",
3+
"version": "0.0.97-beta-2",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",
@@ -92,7 +92,6 @@
9292
"dependencies": {
9393
"ansi_up": "^5.2.1",
9494
"fast-json-patch": "^3.1.1",
95-
"jsonpath-plus": "^7.2.0",
9695
"react-monaco-editor": "^0.54.0",
9796
"sass": "^1.69.7",
9897
"tslib": "^2.4.1"

src/Common/Helper.tsx

Lines changed: 97 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
import React, { SyntheticEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
1818
import { components } from 'react-select'
1919
import * as Sentry from '@sentry/browser'
20-
import * as jsonpatch from 'fast-json-patch'
21-
import { JSONPath } from 'jsonpath-plus'
2220
import moment from 'moment'
2321
import { useLocation } from 'react-router-dom'
2422
import { toast } from 'react-toastify'
@@ -622,79 +620,110 @@ export const getFilteredChartVersions = (charts, selectedChartType) =>
622620
chartRefId: item.chartRefId,
623621
}))
624622

625-
function removeEmptyObjectKeysAndNullValues(obj, originaljsonCopy) {
626-
// It recursively removes empty object keys and empty array keys
627-
for (const key in obj) {
628-
if (Array.isArray(obj[key])) {
629-
// Check if the array is empty
630-
if (obj[key].length !== 0) {
631-
obj[key].forEach((element, index) => {
632-
if (element === null || (typeof element === 'object' && Object.keys(element).length === 0))
633-
obj[key].splice(index, 1)
634-
else removeEmptyObjectKeysAndNullValues(element, originaljsonCopy[key][index])
635-
})
636-
}
637-
if (obj[key].length === 0 && originaljsonCopy[key].length !== 0) {
638-
delete obj[key]
639-
}
640-
} else if (obj[key] && typeof obj[key] === 'object') {
641-
if (
642-
removeEmptyObjectKeysAndNullValues(obj[key], originaljsonCopy[key]) &&
643-
Object.keys(originaljsonCopy[key]).length !== 0
644-
) {
645-
delete obj[key]
646-
}
647-
} else if (obj[key] === undefined) {
648-
delete obj[key]
649-
}
623+
/**
624+
* Removes nulls from the arrays in the provided object
625+
* @param {object} object from which we need to delete nulls in its arrays
626+
* @returns object after removing (in-place) the null items in arrays
627+
*/
628+
export const recursivelyRemoveNullsFromArraysInObject = (object: object) => {
629+
// NOTE: typeof null === 'object'
630+
if (typeof object !== 'object' || !object) {
631+
return object
632+
}
633+
if (Array.isArray(object)) {
634+
return object.filter((item) => {
635+
recursivelyRemoveNullsFromArraysInObject(item)
636+
return !!item
637+
})
650638
}
651-
return Object.keys(obj).length === 0
639+
Object.keys(object).forEach((key) => {
640+
object[key] = recursivelyRemoveNullsFromArraysInObject(object[key])
641+
})
642+
return object
652643
}
653644

654-
export function getUnlockedJSON(json, jsonPathArray, removeParentKeysAndEmptyArrays = false) {
655-
if (!jsonPathArray.length) return { newDocument: json, removedPatches: [] }
645+
const _joinObjects = (A: object, B: object) => {
646+
if (typeof A !== 'object' || typeof B !== 'object' || !B) {
647+
return
648+
}
649+
Object.keys(B).forEach((key) => {
650+
if (!A[key]) {
651+
A[key] = structuredClone(B[key])
652+
return
653+
}
654+
_joinObjects(A[key], B[key])
655+
})
656+
}
656657

657-
const jsonCopy = JSON.parse(JSON.stringify(json))
658-
const originaljsonCopy = JSON.parse(JSON.stringify(json))
659-
const removedPatches = []
660-
const patches = jsonPathArray.flatMap((jsonPath) => {
661-
const pathsToRemove = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
662-
// reversing patches to handle correct array index deletion
663-
pathsToRemove.reverse()
664-
return pathsToRemove.map((result) => {
665-
// storing removed patches to have functionality of undo
666-
removedPatches.push({ op: 'add', path: result.pointer, value: result.value })
667-
return { op: 'remove', path: result.pointer }
668-
})
658+
/**
659+
* Merges the objects into one object
660+
* @param {object[]} objects list of js objects
661+
* @returns object after the merge
662+
*/
663+
export const joinObjects = (objects: object[]) => {
664+
const join = {}
665+
objects.forEach((object) => {
666+
_joinObjects(join, object)
669667
})
670-
const { newDocument } = jsonpatch.applyPatch(jsonCopy, patches)
671-
if (removeParentKeysAndEmptyArrays) removeEmptyObjectKeysAndNullValues(newDocument, originaljsonCopy)
672-
return { newDocument, removedPatches: removedPatches.reverse() }
673-
}
674-
675-
export function getLockedJSON(json, jsonPathArray: string[]) {
676-
const jsonCopy = JSON.parse(JSON.stringify(json))
677-
const resultJson = {}
678-
jsonPathArray.forEach((jsonPath) => {
679-
const elements = JSONPath({ path: jsonPath, json: jsonCopy, resultType: 'all' })
680-
elements.forEach((element) => {
681-
const pathArray: string[] = JSONPath.toPathArray(element.path)
682-
const lastPath = pathArray.pop()
683-
let current = resultJson
684-
for (let i = 0; i < pathArray.length; i++) {
685-
const key = isNaN(Number(pathArray[i])) ? pathArray[i] : parseInt(pathArray[i])
686-
if (!current[key]) {
687-
current[key] = isNaN(Number(pathArray[i + 1] ?? lastPath)) ? {} : []
688-
}
689-
current = current[key]
690-
}
691-
const key = isNaN(Number(lastPath)) ? lastPath : parseInt(lastPath)
692-
current[key] = element.value
668+
return join
669+
}
670+
671+
const buildObjectFromPathTokens = (index: number, tokens: string[], value: any) => {
672+
if (index === tokens.length) {
673+
return value
674+
}
675+
const key = tokens[index]
676+
const numberKey = Number(key)
677+
const isKeyNumber = !Number.isNaN(numberKey)
678+
return isKeyNumber
679+
? [...Array(numberKey).fill(null), buildObjectFromPathTokens(index + 1, tokens, value)]
680+
: { [key]: buildObjectFromPathTokens(index + 1, tokens, value) }
681+
}
682+
683+
/**
684+
* Builds an object from the provided path
685+
* @param {string} path JSON pointer path of the form /path/to/1/...
686+
* @param {any} value property value
687+
* @returns final object formed from the path
688+
*/
689+
export const buildObjectFromPath = (path: string, value: any) => {
690+
const parts = path.split('/')
691+
// NOTE: since the path has a leading / we need to delete the first element
692+
parts.splice(0, 1)
693+
return buildObjectFromPathTokens(0, parts, value)
694+
}
695+
696+
/**
697+
* Returns the list of indices at which the regex matched
698+
* @param string the string to process
699+
* @param regex @RegExp
700+
* @returns array of indices where the @regex matched in @string
701+
*/
702+
export const getRegexMatchPositions = (string: string, regex: RegExp): number[] => {
703+
const pos = string.search(regex)
704+
if (pos < 0) {
705+
return []
706+
}
707+
const nextToken = string.slice(pos + 1)
708+
return [pos, ...getRegexMatchPositions(nextToken, regex).map((n) => n + pos + 1)]
709+
}
710+
711+
/**
712+
* Returns all the substrings from 0th index to progressively next regex match position
713+
* Eg. Suppose a string is /path/to/folder then it will return [/path, /path/to, /path/to/folder]
714+
* @param strings list of strings
715+
* @param regex that matches the separators for the substrings
716+
* @returns set of substrings
717+
*/
718+
export const powerSetOfSubstringsFromStart = (strings: string[], regex: RegExp) =>
719+
strings.flatMap((key) => {
720+
const _keys = [key]
721+
const positions = getRegexMatchPositions(key, regex)
722+
positions.forEach((position) => {
723+
_keys.push(key.slice(0, position))
693724
})
725+
return _keys
694726
})
695-
// eslint-disable-next-line dot-notation
696-
return resultJson['$']
697-
}
698727

699728
/**
700729
* Returns a debounced variant of the function

0 commit comments

Comments
 (0)