Skip to content

Commit

Permalink
feat: working on unset algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
aviemet committed Jun 8, 2024
1 parent 12a0f19 commit 8f8c9b0
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 13 deletions.
31 changes: 29 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import React from 'react'
import { isPlainObject, unset, get, set, isEmpty } from 'lodash'
import { type NestedObject } from './useInertiaForm'

/**
* Creates context with simplified type notations
* Wraps useContext hook in an error check to enforce context context
*/
export const createContext = <CT extends unknown | null>() => {
const context = React.createContext<CT | undefined>(null)

Expand All @@ -18,15 +22,38 @@ export const createContext = <CT extends unknown | null>() => {
return [useContext, context.Provider] as const
}

/**
* Extends _.unset to remove empty array elements after unsetting an array by index
* e.g. unset(data, 'path[0]')
* Allows special syntax of '[]' to refer to every element of an array
* e.g. unset(data, 'path[].key'), will recursively unset 'key' in every array element
*/
type TArrType = string|number|NestedObject
export const unsetCompact = (data: NestedObject, path: string) => {
const emptyArrayPosition = path.indexOf('[].')
if(emptyArrayPosition >= 0) {
console.log({ emptyArrayPosition })
const restPath = path.slice(emptyArrayPosition + 3)
const arr = get(data, restPath) as TArrType[]

arr.forEach((el, i) => {
// @ts-ignore
unsetCompact(el, restPath)
arr[i] = el
})
console.dir({ data, restPath, arr }, { depth: null })
set(data, restPath, arr.filter(a => a))
}

unset(data, path)

let position = path.indexOf('[')
while(position >= 0) {

if(position >= 0) {
const arrPath = path.slice(0, position)
// @ts-ignore - No way to tell TS that this will be an array
const arr = get(data, arrPath) as TArrType[]


set(data, arrPath, arr.filter(a => a))

position = path.indexOf('[', position + 1)
Expand Down
121 changes: 110 additions & 11 deletions tests/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ const nestedData: NestedObject = {
two: {
three: 'three',
four: [
{ five: 'five' },
{ six: 'six' },
{ five: 'five', six: 'six' },
{ seven: 'seven' },
{ five: 'eight', six: 'nine', ten: [
{ eleven: 'eleven', twelve: 'twelve' },
{ eleven: 'eleven', thirteen: 'thirteen' },
] },
],
seven: {
last: {
just: 'testing',
},
},
Expand All @@ -22,36 +26,131 @@ describe('unsetCompact', () => {
unsetCompact(data, 'one')
unsetCompact(data, 'two.three')

expect(data).toMatchObject({
expect(data).toEqual({
two: {
four: [
{ five: 'five' },
{ six: 'six' },
{ five: 'five', six: 'six' },
{ seven: 'seven' },
{ five: 'eight', six: 'nine', ten: [
{ eleven: 'eleven', twelve: 'twelve' },
{ eleven: 'eleven', thirteen: 'thirteen' },
] },
],
seven: {
last: {
just: 'testing',
},
},
})
})

it('should reorder arrays making all elements sequential', () => {
it('should reorder arrays making all elements sequential and removing empty array elements', () => {
const data = structuredClone(nestedData)

unsetCompact(data, 'two.four[0]')
expect(data).toMatchObject({
unsetCompact(data, 'two.four[1].ten[0]')

expect(data).toEqual({
one: 'one',
two: {
three: 'three',
four: [
{ six: 'six' },
{ seven: 'seven' },
{ five: 'eight', six: 'nine', ten: [
{ eleven: 'eleven', thirteen: 'thirteen' },
] },
],
seven: {
last: {
just: 'testing',
},
},
})
})

describe('recursively unsets array elements by key with empty array brackets', () => {
const data = structuredClone(nestedData)

it('unsets all instances of a key', () => {
unsetCompact(data, 'two.four[].five')
expect(data).toEqual({
one: 'one',
two: {
three: 'three',
four: [
{ six: 'six' },
{ seven: 'seven' },
{ six: 'nine', ten: [
{ eleven: 'eleven', twelve: 'twelve' },
{ eleven: 'eleven', thirteen: 'thirteen' },
] },
],
last: {
just: 'testing',
},
},
})
})

it('works with nested array objects', () => {
unsetCompact(data, 'two.four[].ten[].twelve')
expect(data).toEqual({
one: 'one',
two: {
three: 'three',
four: [
{ six: 'six' },
{ seven: 'seven' },
{ six: 'nine', ten: [
{ eleven: 'eleven' },
{ eleven: 'eleven', thirteen: 'thirteen' },
] },
],
last: {
just: 'testing',
},
},
})
})

it('works when an element is specified after an empty bracket', () => {
unsetCompact(data, 'two.four[].ten[1].thirteen')
expect(data).toEqual({
one: 'one',
two: {
three: 'three',
four: [
{ six: 'six' },
{ seven: 'seven' },
{ six: 'nine', ten: [
{ eleven: 'eleven' },
{ eleven: 'eleven' },
] },
],
last: {
just: 'testing',
},
},
})
})

it('works when an empty bracket is specified after an element ', () => {
unsetCompact(data, 'two.four[2].ten[].eleven')
expect(data).toEqual({
one: 'one',
two: {
three: 'three',
four: [
{ six: 'six' },
{ seven: 'seven' },
{ six: 'nine', ten: [] },
],
last: {
just: 'testing',
},
},
})

})
})
})

describe('fillEmptyValues', () => {
Expand Down

0 comments on commit 8f8c9b0

Please sign in to comment.