Skip to content

Commit 5cbcf99

Browse files
authored
feat(marshalling): add any marshalling (#2054)
1 parent a627c5e commit 5cbcf99

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

packages/client/src/helpers/json.ts

+65
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,68 @@ export const isJSONObject = (obj: unknown): obj is JSONObject => {
4242
objT === 'object'
4343
)
4444
}
45+
46+
/**
47+
* Camelizes a string.
48+
*
49+
* @param str - The string to camelize
50+
* @returns The camelized string
51+
*
52+
* @internal
53+
*/
54+
export const camelize = (str: string): string => {
55+
const strLength = str.length
56+
if (strLength <= 0) {
57+
return str
58+
}
59+
let out = ''
60+
for (let capNext = false, index = 0; index < strLength; index += 1) {
61+
const char = str.charAt(index)
62+
if (char >= 'a' && char <= 'z') {
63+
if (capNext) {
64+
out += char.toUpperCase()
65+
} else {
66+
out += char
67+
}
68+
} else if (char >= 'A' && char <= 'Z') {
69+
out += char
70+
} else if (char >= '0' && char <= '9') {
71+
out += char
72+
}
73+
capNext = char === '_' || char === ' ' || char === '-' || char === '.'
74+
}
75+
76+
return out.charAt(0).toLowerCase() + out.substring(1)
77+
}
78+
79+
/**
80+
* Camelizes keys of an object (deeply).
81+
*
82+
* @param obj - The object
83+
* @param ignoreKeys - The keys to ignore
84+
* @returns The object with camelized keys
85+
*
86+
* @internal
87+
*/
88+
export const camelizeKeys = <T>(
89+
obj: object | unknown[] | unknown,
90+
ignoreKeys: string[] = [],
91+
): T => {
92+
if (Array.isArray(obj)) {
93+
return obj.map(v => camelizeKeys(v, ignoreKeys)) as unknown as T
94+
}
95+
96+
if (obj && typeof obj === 'object' && !(obj instanceof Date)) {
97+
return Object.entries(obj).reduce(
98+
(acc, [key, value]) => ({
99+
...acc,
100+
[camelize(key)]: ignoreKeys.includes(key)
101+
? (value as unknown)
102+
: camelizeKeys(value, ignoreKeys),
103+
}),
104+
{},
105+
) as T
106+
}
107+
108+
return obj as T
109+
}

packages/client/src/scw/custom-marshalling.ts

+59-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isJSONObject } from '../helpers/json'
1+
import { camelizeKeys, isJSONObject } from '../helpers/json'
22
import { unmarshalArrayOfObject, unmarshalDate } from '../helpers/marshalling'
33
import { fromByteArray } from '../vendor/base64'
44
import type {
@@ -207,3 +207,61 @@ export const marshalTimeSeries = (
207207
export const marshalDecimal = (obj: Decimal): { value: string } => ({
208208
value: obj.toString(),
209209
})
210+
211+
/**
212+
* Unmarshals record to convert iso dates from string to Dates.
213+
*
214+
* @param obj - The input
215+
* @param keys - The keys requiring a conversion
216+
* @returns The updated input
217+
*
218+
* @internal
219+
*/
220+
export const unmarshalDates = <T>(obj: unknown, keys: string[]): T => {
221+
if (Array.isArray(obj)) {
222+
return obj.map(v => unmarshalDates(v, keys)) as unknown as T
223+
}
224+
225+
if (obj && typeof obj === 'object') {
226+
return Object.entries(obj).reduce(
227+
(acc, [key, value]) => ({
228+
...acc,
229+
[key]:
230+
typeof value === 'string' && keys.includes(key)
231+
? new Date(value)
232+
: unmarshalDates(value, keys),
233+
}),
234+
{},
235+
) as T
236+
}
237+
238+
return obj as T
239+
}
240+
241+
/**
242+
* Unmarshals input to a record with camilized keys and instanciated Date.
243+
*
244+
* @param obj - The input
245+
* @param ignoreKeys - The keys which should be not be transformed
246+
* @param dateKeys - The keys which should be transformed to Date
247+
* @returns The record
248+
*
249+
* @throws TypeError
250+
* Thrown if the input isn't {@link JSONObject}.
251+
*
252+
* @internal
253+
*/
254+
export const unmarshalAnyRes = <T>(
255+
obj: unknown,
256+
ignoreKeys: string[] = [],
257+
dateKeys?: string[],
258+
): T => {
259+
if (!isJSONObject(obj)) {
260+
throw new TypeError(`Data isn't a dictionary.`)
261+
}
262+
263+
return camelizeKeys(
264+
dateKeys && dateKeys.length > 0 ? unmarshalDates(obj, dateKeys) : obj,
265+
ignoreKeys,
266+
)
267+
}

0 commit comments

Comments
 (0)