deepCloneArgs.ts•2.26 kB
import { assertNever } from '@prisma/internals'
import Decimal from 'decimal.js'
import { Sql } from 'sql-template-tag'
import { isFieldRef } from '../core/model/FieldRef'
import { isTypedSql, TypedSql, UnknownTypedSql } from '../core/types/exported'
import { JsArgs, JsInputValue } from '../core/types/exported/JsApi'
import { ObjectEnumValue } from '../core/types/exported/ObjectEnums'
import { RawQueryArgs } from '../core/types/exported/RawQueryArgs'
import { isDate } from './date'
import { isDecimalJsLike } from './decimalJsLike'
export function deepCloneArgs(args: JsArgs | RawQueryArgs): JsArgs | RawQueryArgs {
if (args instanceof Sql) {
return cloneSql(args)
}
if (isTypedSql(args)) {
return cloneTypedSql(args)
}
if (Array.isArray(args)) {
const clone: RawQueryArgs = [args[0]]
for (let i = 1; i < args.length; i++) {
clone[i] = deepCloneValue(args[i] as JsInputValue)
}
return clone
}
const clone: JsArgs = {}
for (const k in args) {
clone[k] = deepCloneValue(args[k])
}
return clone
}
function cloneSql(rawParam: Sql): Sql {
return new Sql(rawParam.strings, rawParam.values)
}
function cloneTypedSql(rawParam: UnknownTypedSql): UnknownTypedSql {
return new TypedSql(rawParam.sql, rawParam.values)
}
// based on https://github.com/lukeed/klona/blob/v2.0.6/src/index.js
function deepCloneValue(x: JsInputValue): JsInputValue {
if (typeof x !== 'object' || x == null || x instanceof ObjectEnumValue || isFieldRef(x)) {
return x
}
if (isDecimalJsLike(x)) {
return new Decimal(x.toFixed())
}
if (isDate(x)) {
return new Date(+x)
}
if (ArrayBuffer.isView(x)) {
return x.slice(0)
}
if (Array.isArray(x)) {
let k = x.length
let copy
for (copy = Array(k); k--; ) {
copy[k] = deepCloneValue(x[k])
}
return copy
}
if (typeof x === 'object') {
const copy = {}
for (const k in x) {
if (k === '__proto__') {
Object.defineProperty(copy, k, {
value: deepCloneValue(x[k]),
configurable: true,
enumerable: true,
writable: true,
})
} else {
copy[k] = deepCloneValue(x[k])
}
}
return copy
}
assertNever(x, 'Unknown value')
}