add clonedeep that copies non-serialisable stuff

This commit is contained in:
Gerard Burns 2024-05-14 09:24:18 +01:00
parent ca452d7dce
commit bad7a535dc
10 changed files with 82 additions and 16 deletions

View File

@ -2,7 +2,7 @@
import { getContext } from "svelte"
import ApexCharts from "apexcharts"
import { Icon } from "@budibase/bbui"
import { cloneDeep } from "lodash"
import { cloneDeep } from "./utils"
const { styleable, builderStore } = getContext("sdk")
const component = getContext("component")
@ -10,7 +10,8 @@
export let options
// Apex charts directly modifies the options object with default properties and internal variables. These being present could unintentionally cause issues to the provider of this prop as the changes are reflected in that component as well. To prevent any issues we clone options here to provide a buffer.
$: optionsCopy = structuredClone(options)
$: optionsCopy = cloneDeep(options)
$: console.log(options, optionsCopy)
let chartElement
let chart

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let title
export let dataProvider

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let dataProvider
export let labelColumn

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let title
export let dataProvider

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let title
export let dataProvider

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let title
export let dataProvider

View File

@ -1,6 +1,6 @@
<script>
import ApexChart from "./ApexChart.svelte"
import formatters from "./formatters"
import { formatters } from "./utils"
export let title
export let dataProvider

View File

@ -1,8 +0,0 @@
const formatters = {
["Default"]: val => val,
["Thousands"]: val => `${Math.round(val / 1000)}K`,
["Millions"]: val => `${Math.round(val / 1000000)}M`,
["Datetime"]: val => new Date(val).toLocaleString(),
}
export default formatters

View File

@ -0,0 +1,40 @@
export const formatters = {
["Default"]: val => val,
["Thousands"]: val => `${Math.round(val / 1000)}K`,
["Millions"]: val => `${Math.round(val / 1000000)}M`,
["Datetime"]: val => new Date(val).toLocaleString(),
}
// Deep clone which copies function references
export const cloneDeep = (value) => {
const typesToNaiveCopy = ["string", "boolean", "number", "function", "symbol"]
if (value === null) {
return null
}
if (value === undefined) {
return undefined
}
if (typesToNaiveCopy.includes(typeof value)) {
return value;
}
if (Array.isArray(value)) {
return value.map(element => cloneDeep(element))
}
// Only copy "pure" objects, we want to error on stuff like Maps or Sets
if (typeof value === "object" && value.constructor.name === "Object") {
const cloneObject = {}
Object.entries(value).forEach(([key, childValue]) => {
cloneObject[key] = cloneDeep(childValue)
})
return cloneObject;
}
throw `Unsupported value: "${value}" of type: "${typeof value}"`
}

View File

@ -0,0 +1,33 @@
import { expect, describe, it, vi } from "vitest"
import {
cloneDeep,
} from "./utils"
describe("utils", () => {
let context;
beforeEach(() => {
vi.clearAllMocks()
context = {};
})
describe("cloneDeep", () => {
beforeEach(() => {
context.value = {
obj: { one: 1, two: 2 },
arr: [1, { first: null, second: undefined }, 2],
str: "test",
num: 123,
bool: true,
sym: Symbol("test"),
func: () => "some value"
}
context.cloneValue = cloneDeep(context.value);
});
it("to clone the object and not copy object references", () => {
expect(context.cloneValue.obj.one).toEqual(1)
expect(context.cloneValue.obj.two).toEqual(2)
});
})
})