File size: 2,167 Bytes
7aec436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import {readAsArrayBuffer} from '../common/readers';
import {encode, decode} from './base64';

const BLOB_IDENTIFIER = '__isBlob';

const isObjectOrArray = (value) => value !== null && typeof value === 'object';

/**

 * Generate an object where any child properties of type Blob will have their data inlined.

 * @param {unknown} object 

 * @returns {Promise<unknown>}

 */
const recursivelySerializeBlobs = async (object) => {
  if (Array.isArray(object)) {
    return object;
  }
  const result = {};
  for (const key of Object.keys(object)) {
    if (key === BLOB_IDENTIFIER) {
      // We could add special handling for this property, but nothing we export should actually
      // use this property anyways so this is fine for now.
      throw new Error(`Can't serialize special key: ${BLOB_IDENTIFIER}`);
    }

    const value = object[key];
    if (value instanceof Blob) {
      const arrayBuffer = await readAsArrayBuffer(value);
      result[key] = {
        [BLOB_IDENTIFIER]: true,
        type: value.type,
        name: value.name || '',
        data: encode(arrayBuffer)
      };
    } else if (isObjectOrArray(value)) {
      result[key] = await recursivelySerializeBlobs(value);
    } else {
      result[key] = value;
    }
  }
  return result;
};

/**

 * Generate an object where any child properties inlined by recursivelySerializeBlobs will be converted

 * back to a blob.

 * @param {unknown} object

 * @returns {unknown}

 */
const recursivelyDeserializeBlobs = (object) => {
  if (Array.isArray(object)) {
    return object;
  }
  const result = {};
  for (const key of Object.keys(object)) {
    const value = object[key];
    if (isObjectOrArray(value)) {
      if (value[BLOB_IDENTIFIER]) {
        const blob = new Blob([decode(value.data)], {
          type: value.type
        });
        blob.name = value.name;
        result[key] = blob;
      } else {
        result[key] = recursivelyDeserializeBlobs(value);
      }
    } else {
      result[key] = value;
    }
  }
  return result;
};

export {
  recursivelySerializeBlobs,
  recursivelyDeserializeBlobs
};