decoders 1.26.0-beta2 → 2.0.0-beta11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +52 -6
  2. package/Decoder.d.ts +28 -0
  3. package/Decoder.js +213 -0
  4. package/Decoder.js.flow +238 -0
  5. package/Decoder.mjs +206 -0
  6. package/NotSupportedTSVersion.d.ts +1 -0
  7. package/README.md +105 -961
  8. package/_utils.d.ts +9 -0
  9. package/_utils.js +102 -0
  10. package/_utils.js.flow +93 -0
  11. package/_utils.mjs +89 -0
  12. package/annotate.d.ts +62 -0
  13. package/annotate.js +161 -0
  14. package/annotate.js.flow +218 -0
  15. package/annotate.mjs +144 -0
  16. package/format.d.ts +4 -0
  17. package/format.js +151 -0
  18. package/format.js.flow +126 -0
  19. package/format.mjs +140 -0
  20. package/index.d.ts +40 -0
  21. package/index.js +90 -0
  22. package/index.js.flow +44 -0
  23. package/index.mjs +11 -0
  24. package/{ts/helpers.d.ts → lib/_helpers.d.ts} +0 -0
  25. package/lib/arrays.d.ts +37 -0
  26. package/lib/arrays.js +138 -0
  27. package/lib/arrays.js.flow +138 -0
  28. package/lib/arrays.mjs +123 -0
  29. package/lib/basics.d.ts +14 -0
  30. package/lib/basics.js +109 -0
  31. package/lib/basics.js.flow +85 -0
  32. package/lib/basics.mjs +85 -0
  33. package/{ts/boolean.d.ts → lib/booleans.d.ts} +1 -1
  34. package/lib/booleans.js +35 -0
  35. package/lib/booleans.js.flow +22 -0
  36. package/lib/booleans.mjs +25 -0
  37. package/{ts/date.d.ts → lib/dates.d.ts} +1 -1
  38. package/lib/dates.js +44 -0
  39. package/lib/dates.js.flow +40 -0
  40. package/lib/dates.mjs +34 -0
  41. package/{ts → lib}/json.d.ts +1 -1
  42. package/lib/json.js +55 -0
  43. package/lib/json.js.flow +50 -0
  44. package/lib/json.mjs +40 -0
  45. package/{ts/number.d.ts → lib/numbers.d.ts} +2 -1
  46. package/lib/numbers.js +52 -0
  47. package/lib/numbers.js.flow +49 -0
  48. package/lib/numbers.mjs +42 -0
  49. package/{ts/object.d.ts → lib/objects.d.ts} +11 -6
  50. package/lib/objects.js +240 -0
  51. package/lib/objects.js.flow +246 -0
  52. package/lib/objects.mjs +223 -0
  53. package/lib/strings.d.ts +13 -0
  54. package/lib/strings.js +101 -0
  55. package/lib/strings.js.flow +90 -0
  56. package/lib/strings.mjs +82 -0
  57. package/lib/unions.d.ts +78 -0
  58. package/lib/unions.js +161 -0
  59. package/lib/unions.js.flow +158 -0
  60. package/lib/unions.mjs +145 -0
  61. package/lib/utilities.d.ts +10 -0
  62. package/lib/utilities.js +94 -0
  63. package/lib/utilities.js.flow +84 -0
  64. package/lib/utilities.mjs +79 -0
  65. package/package.json +79 -28
  66. package/result.d.ts +16 -0
  67. package/result.js +34 -0
  68. package/result.js.flow +26 -0
  69. package/result.mjs +27 -0
  70. package/cjs/array.js +0 -133
  71. package/cjs/array.js.flow +0 -106
  72. package/cjs/boolean.js +0 -42
  73. package/cjs/boolean.js.flow +0 -28
  74. package/cjs/constants.js +0 -67
  75. package/cjs/constants.js.flow +0 -45
  76. package/cjs/date.js +0 -42
  77. package/cjs/date.js.flow +0 -38
  78. package/cjs/describe.js +0 -22
  79. package/cjs/describe.js.flow +0 -17
  80. package/cjs/dispatch.js +0 -58
  81. package/cjs/dispatch.js.flow +0 -57
  82. package/cjs/either.js +0 -85
  83. package/cjs/either.js.flow +0 -131
  84. package/cjs/fail.js +0 -19
  85. package/cjs/fail.js.flow +0 -13
  86. package/cjs/guard.js +0 -30
  87. package/cjs/guard.js.flow +0 -36
  88. package/cjs/index.js +0 -397
  89. package/cjs/index.js.flow +0 -56
  90. package/cjs/instanceOf.js +0 -17
  91. package/cjs/instanceOf.js.flow +0 -21
  92. package/cjs/json.js +0 -33
  93. package/cjs/json.js.flow +0 -28
  94. package/cjs/lazy.js +0 -18
  95. package/cjs/lazy.js.flow +0 -15
  96. package/cjs/mapping.js +0 -113
  97. package/cjs/mapping.js.flow +0 -71
  98. package/cjs/number.js +0 -38
  99. package/cjs/number.js.flow +0 -35
  100. package/cjs/object.js +0 -254
  101. package/cjs/object.js.flow +0 -211
  102. package/cjs/optional.js +0 -52
  103. package/cjs/optional.js.flow +0 -42
  104. package/cjs/string.js +0 -93
  105. package/cjs/string.js.flow +0 -81
  106. package/cjs/tuple.js +0 -199
  107. package/cjs/tuple.js.flow +0 -221
  108. package/cjs/types.js +0 -3
  109. package/cjs/types.js.flow +0 -26
  110. package/cjs/utils.js +0 -70
  111. package/cjs/utils.js.flow +0 -58
  112. package/es/index.js +0 -1039
  113. package/ts/array.d.ts +0 -5
  114. package/ts/constants.d.ts +0 -11
  115. package/ts/describe.d.ts +0 -3
  116. package/ts/dispatch.d.ts +0 -8
  117. package/ts/either.d.ts +0 -61
  118. package/ts/fail.d.ts +0 -3
  119. package/ts/guard.d.ts +0 -7
  120. package/ts/index.d.ts +0 -38
  121. package/ts/instanceOf.d.ts +0 -3
  122. package/ts/lazy.d.ts +0 -3
  123. package/ts/mapping.d.ts +0 -4
  124. package/ts/optional.d.ts +0 -5
  125. package/ts/string.d.ts +0 -7
  126. package/ts/tuple.d.ts +0 -30
  127. package/ts/types.d.ts +0 -18
  128. package/ts/utils.d.ts +0 -13
@@ -0,0 +1,218 @@
1
+ // @flow strict
2
+
3
+ type cast = $FlowFixMe;
4
+
5
+ const _register: WeakSet<{ ... }> = new WeakSet();
6
+
7
+ export type ObjectAnnotation = {|
8
+ +type: 'object',
9
+ +fields: { +[key: string]: Annotation },
10
+ +text?: string,
11
+ |};
12
+
13
+ export type ArrayAnnotation = {|
14
+ +type: 'array',
15
+ +items: $ReadOnlyArray<Annotation>,
16
+ +text?: string,
17
+ |};
18
+
19
+ export type ScalarAnnotation = {|
20
+ +type: 'scalar',
21
+ +value: mixed,
22
+ +text?: string,
23
+ |};
24
+
25
+ export type FunctionAnnotation = {|
26
+ +type: 'function',
27
+ +text?: string,
28
+ |};
29
+
30
+ export type CircularRefAnnotation = {|
31
+ +type: 'circular-ref',
32
+ +text?: string,
33
+ |};
34
+
35
+ export type UnknownAnnotation = {|
36
+ +type: 'unknown',
37
+ +value: mixed,
38
+ +text?: string,
39
+ |};
40
+
41
+ export type Annotation =
42
+ | ObjectAnnotation
43
+ | ArrayAnnotation
44
+ | ScalarAnnotation
45
+ | FunctionAnnotation
46
+ | CircularRefAnnotation
47
+ | UnknownAnnotation;
48
+
49
+ function brand<A: Annotation>(ann: A): A {
50
+ _register.add(ann);
51
+ return ann;
52
+ }
53
+
54
+ export function object(
55
+ fields: { +[key: string]: Annotation },
56
+ text?: string,
57
+ ): ObjectAnnotation {
58
+ return brand({ type: 'object', fields, text });
59
+ }
60
+
61
+ export function array(items: $ReadOnlyArray<Annotation>, text?: string): ArrayAnnotation {
62
+ return brand({
63
+ type: 'array',
64
+ items,
65
+ text,
66
+ });
67
+ }
68
+
69
+ export function func(text?: string): FunctionAnnotation {
70
+ return brand({
71
+ type: 'function',
72
+ text,
73
+ });
74
+ }
75
+
76
+ export function unknown(value: mixed, text?: string): UnknownAnnotation {
77
+ return brand({
78
+ type: 'unknown',
79
+ value,
80
+ text,
81
+ });
82
+ }
83
+
84
+ export function scalar(value: mixed, text?: string): ScalarAnnotation {
85
+ return brand({
86
+ type: 'scalar',
87
+ value,
88
+ text,
89
+ });
90
+ }
91
+
92
+ export function circularRef(text?: string): CircularRefAnnotation {
93
+ return brand({
94
+ type: 'circular-ref',
95
+ text,
96
+ });
97
+ }
98
+
99
+ /**
100
+ * Given an existing Annotation, set the annotation's text to a new value.
101
+ */
102
+ export function updateText<A: Annotation>(annotation: A, text?: string): A {
103
+ if (text !== undefined) {
104
+ return brand({ ...annotation, text });
105
+ } else {
106
+ return annotation;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Given an existing ObjectAnnotation, merges new Annotations in there.
112
+ */
113
+ export function merge(
114
+ objAnnotation: ObjectAnnotation,
115
+ fields: { +[key: string]: Annotation },
116
+ ): ObjectAnnotation {
117
+ const newFields = { ...objAnnotation.fields, ...fields };
118
+ return object(newFields, objAnnotation.text);
119
+ }
120
+
121
+ export function asAnnotation(thing: mixed): Annotation | void {
122
+ return typeof thing === 'object' && thing !== null && _register.has(thing)
123
+ ? ((thing: cast): Annotation)
124
+ : undefined;
125
+ }
126
+
127
+ type RefSet = WeakSet<{ ... } | $ReadOnlyArray<mixed>>;
128
+
129
+ function annotateArray(
130
+ value: $ReadOnlyArray<mixed>,
131
+ text?: string,
132
+ seen: RefSet,
133
+ ): ArrayAnnotation | CircularRefAnnotation {
134
+ seen.add(value);
135
+
136
+ const items = value.map((v) => annotate(v, undefined, seen));
137
+ return array(items, text);
138
+ }
139
+
140
+ function annotateObject(
141
+ obj: { +[string]: mixed },
142
+ text?: string,
143
+ seen: RefSet,
144
+ ): ObjectAnnotation {
145
+ seen.add(obj);
146
+
147
+ const fields = {};
148
+ Object.keys(obj).forEach((key) => {
149
+ const value = obj[key];
150
+ fields[key] = annotate(value, undefined, seen);
151
+ });
152
+ return object(fields, text);
153
+ }
154
+
155
+ function annotate(value: mixed, text?: string, seen: RefSet): Annotation {
156
+ if (
157
+ value === null ||
158
+ value === undefined ||
159
+ typeof value === 'string' ||
160
+ typeof value === 'number' ||
161
+ typeof value === 'boolean' ||
162
+ typeof value === 'symbol' ||
163
+ typeof value.getMonth === 'function'
164
+ ) {
165
+ return scalar(value, text);
166
+ }
167
+
168
+ const ann = asAnnotation(value);
169
+ if (ann) {
170
+ return updateText(ann, text);
171
+ }
172
+
173
+ if (Array.isArray(value)) {
174
+ // "Circular references" can only exist in objects or arrays
175
+ if (seen.has(value)) {
176
+ return circularRef(text);
177
+ } else {
178
+ return annotateArray(value, text, seen);
179
+ }
180
+ }
181
+
182
+ if (typeof value === 'object') {
183
+ // "Circular references" can only exist in objects or arrays
184
+ if (seen.has(value)) {
185
+ return circularRef(text);
186
+ } else {
187
+ return annotateObject(value, text, seen);
188
+ }
189
+ }
190
+
191
+ if (typeof value === 'function') {
192
+ return func(text);
193
+ }
194
+
195
+ return unknown(value, text);
196
+ }
197
+
198
+ function public_annotate(value: mixed, text?: string): Annotation {
199
+ return annotate(value, text, new WeakSet());
200
+ }
201
+
202
+ function public_annotateObject(
203
+ obj: { +[string]: mixed },
204
+ text?: string,
205
+ ): ObjectAnnotation {
206
+ return annotateObject(obj, text, new WeakSet());
207
+ }
208
+
209
+ export {
210
+ // This construct just ensures the "seen" weakmap (used for circular
211
+ // reference detection) isn't made part of the public API.
212
+ public_annotate as annotate,
213
+ public_annotateObject as annotateObject,
214
+ //
215
+ // NOTE: Don't acces theses private APIs directly. They are only exported here
216
+ // to better enable unit testing.
217
+ annotate as __private_annotate,
218
+ };
package/annotate.mjs ADDED
@@ -0,0 +1,144 @@
1
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+
3
+ var _register = new WeakSet();
4
+
5
+ function brand(ann) {
6
+ _register.add(ann);
7
+
8
+ return ann;
9
+ }
10
+
11
+ export function object(fields, text) {
12
+ return brand({
13
+ type: 'object',
14
+ fields: fields,
15
+ text: text
16
+ });
17
+ }
18
+ export function array(items, text) {
19
+ return brand({
20
+ type: 'array',
21
+ items: items,
22
+ text: text
23
+ });
24
+ }
25
+ export function func(text) {
26
+ return brand({
27
+ type: 'function',
28
+ text: text
29
+ });
30
+ }
31
+ export function unknown(value, text) {
32
+ return brand({
33
+ type: 'unknown',
34
+ value: value,
35
+ text: text
36
+ });
37
+ }
38
+ export function scalar(value, text) {
39
+ return brand({
40
+ type: 'scalar',
41
+ value: value,
42
+ text: text
43
+ });
44
+ }
45
+ export function circularRef(text) {
46
+ return brand({
47
+ type: 'circular-ref',
48
+ text: text
49
+ });
50
+ }
51
+ /**
52
+ * Given an existing Annotation, set the annotation's text to a new value.
53
+ */
54
+
55
+ export function updateText(annotation, text) {
56
+ if (text !== undefined) {
57
+ return brand(_extends({}, annotation, {
58
+ text: text
59
+ }));
60
+ } else {
61
+ return annotation;
62
+ }
63
+ }
64
+ /**
65
+ * Given an existing ObjectAnnotation, merges new Annotations in there.
66
+ */
67
+
68
+ export function merge(objAnnotation, fields) {
69
+ var newFields = _extends({}, objAnnotation.fields, fields);
70
+
71
+ return object(newFields, objAnnotation.text);
72
+ }
73
+ export function asAnnotation(thing) {
74
+ return typeof thing === 'object' && thing !== null && _register.has(thing) ? thing : undefined;
75
+ }
76
+
77
+ function annotateArray(value, text, seen) {
78
+ seen.add(value);
79
+ var items = value.map(function (v) {
80
+ return annotate(v, undefined, seen);
81
+ });
82
+ return array(items, text);
83
+ }
84
+
85
+ function annotateObject(obj, text, seen) {
86
+ seen.add(obj);
87
+ var fields = {};
88
+ Object.keys(obj).forEach(function (key) {
89
+ var value = obj[key];
90
+ fields[key] = annotate(value, undefined, seen);
91
+ });
92
+ return object(fields, text);
93
+ }
94
+
95
+ function annotate(value, text, seen) {
96
+ if (value === null || value === undefined || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'symbol' || typeof value.getMonth === 'function') {
97
+ return scalar(value, text);
98
+ }
99
+
100
+ var ann = asAnnotation(value);
101
+
102
+ if (ann) {
103
+ return updateText(ann, text);
104
+ }
105
+
106
+ if (Array.isArray(value)) {
107
+ // "Circular references" can only exist in objects or arrays
108
+ if (seen.has(value)) {
109
+ return circularRef(text);
110
+ } else {
111
+ return annotateArray(value, text, seen);
112
+ }
113
+ }
114
+
115
+ if (typeof value === 'object') {
116
+ // "Circular references" can only exist in objects or arrays
117
+ if (seen.has(value)) {
118
+ return circularRef(text);
119
+ } else {
120
+ return annotateObject(value, text, seen);
121
+ }
122
+ }
123
+
124
+ if (typeof value === 'function') {
125
+ return func(text);
126
+ }
127
+
128
+ return unknown(value, text);
129
+ }
130
+
131
+ function public_annotate(value, text) {
132
+ return annotate(value, text, new WeakSet());
133
+ }
134
+
135
+ function public_annotateObject(obj, text) {
136
+ return annotateObject(obj, text, new WeakSet());
137
+ }
138
+
139
+ export { // This construct just ensures the "seen" weakmap (used for circular
140
+ // reference detection) isn't made part of the public API.
141
+ public_annotate as annotate, public_annotateObject as annotateObject, //
142
+ // NOTE: Don't acces theses private APIs directly. They are only exported here
143
+ // to better enable unit testing.
144
+ annotate as __private_annotate };
package/format.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Annotation } from './annotate';
2
+
3
+ export function formatInline(ann: Annotation): string;
4
+ export function formatShort(ann: Annotation): string;
package/format.js ADDED
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.formatInline = formatInline;
5
+ exports.formatShort = formatShort;
6
+ exports.serializeAnnotation = serializeAnnotation;
7
+ exports.serializeValue = serializeValue;
8
+
9
+ var _utils = require("./_utils");
10
+
11
+ function serializeString(s, width) {
12
+ if (width === void 0) {
13
+ width = 80;
14
+ }
15
+
16
+ // Full string
17
+ // Abbreviated to $maxlen i.e. "Vincent Driess..." [truncated]
18
+ var ser = JSON.stringify(s);
19
+
20
+ if (ser.length <= width) {
21
+ return ser;
22
+ } // Cut off a bit
23
+
24
+
25
+ var truncated = s.substring(0, width - 15) + '...';
26
+ ser = JSON.stringify(truncated) + ' [truncated]';
27
+ return ser;
28
+ }
29
+
30
+ function serializeArray(annotation, prefix) {
31
+ var items = annotation.items;
32
+
33
+ if (items.length === 0) {
34
+ return '[]';
35
+ }
36
+
37
+ var result = [];
38
+ items.forEach(function (item) {
39
+ var _serializeAnnotation = serializeAnnotation(item, prefix + _utils.INDENT),
40
+ ser = _serializeAnnotation[0],
41
+ ann = _serializeAnnotation[1];
42
+
43
+ result.push(prefix + _utils.INDENT + ser + ',');
44
+
45
+ if (ann !== undefined) {
46
+ result.push((0, _utils.indent)(ann, prefix + _utils.INDENT));
47
+ }
48
+ });
49
+ return ['['].concat(result, [prefix + ']']).join('\n');
50
+ }
51
+
52
+ function serializeObject(annotation, prefix) {
53
+ var fields = annotation.fields;
54
+ var fieldNames = Object.keys(fields);
55
+
56
+ if (fieldNames.length === 0) {
57
+ return '{}';
58
+ }
59
+
60
+ var result = [];
61
+ fieldNames.forEach(function (key) {
62
+ var valueAnnotation = fields[key];
63
+ var kser = serializeValue(key);
64
+ var valPrefix = prefix + _utils.INDENT + ' '.repeat(kser.length + 2);
65
+
66
+ var _serializeAnnotation2 = serializeAnnotation(valueAnnotation, prefix + _utils.INDENT),
67
+ vser = _serializeAnnotation2[0],
68
+ vann = _serializeAnnotation2[1];
69
+
70
+ result.push(prefix + _utils.INDENT + kser + ': ' + vser + ',');
71
+
72
+ if (vann !== undefined) {
73
+ result.push((0, _utils.indent)(vann, valPrefix));
74
+ }
75
+ });
76
+ return ['{'].concat(result, [prefix + '}']).join('\n');
77
+ }
78
+
79
+ function serializeValue(value) {
80
+ // istanbul ignore else
81
+ if (typeof value === 'string') {
82
+ return serializeString(value);
83
+ } else if (typeof value === 'number' || typeof value === 'boolean') {
84
+ return value.toString();
85
+ } else if (value === null) {
86
+ return 'null';
87
+ } else if (value === undefined) {
88
+ return 'undefined';
89
+ } else {
90
+ var valueAsDate = (0, _utils.asDate)(value);
91
+
92
+ if (valueAsDate !== null) {
93
+ return "new Date(" + JSON.stringify(valueAsDate.toISOString()) + ")";
94
+ } else if (value instanceof Date) {
95
+ // NOTE: Using `instanceof Date` is unreliable way of checking dates.
96
+ // If this case occurs (and it didn't pass the prior asDate())
97
+ // check, then this must be the case where it's an invalid date.
98
+ return '(Invalid Date)';
99
+ } else {
100
+ return '(unserializable)';
101
+ }
102
+ }
103
+ }
104
+
105
+ function serializeAnnotation(ann, prefix) {
106
+ if (prefix === void 0) {
107
+ prefix = '';
108
+ }
109
+
110
+ // The serialized data (the input object echoed back)
111
+ var serialized;
112
+
113
+ if (ann.type === 'array') {
114
+ serialized = serializeArray(ann, prefix);
115
+ } else if (ann.type === 'object') {
116
+ serialized = serializeObject(ann, prefix);
117
+ } else if (ann.type === 'function') {
118
+ serialized = '<function>';
119
+ } else if (ann.type === 'circular-ref') {
120
+ serialized = '<circular ref>';
121
+ } else if (ann.type === 'unknown') {
122
+ serialized = '???';
123
+ } else {
124
+ serialized = serializeValue(ann.value);
125
+ }
126
+
127
+ var text = ann.text;
128
+
129
+ if (text !== undefined) {
130
+ var sep = '^'.repeat((0, _utils.isMultiline)(serialized) ? 1 : serialized.length);
131
+ return [serialized, [sep, text].join((0, _utils.isMultiline)(text) ? '\n' : ' ')];
132
+ } else {
133
+ return [serialized, undefined];
134
+ }
135
+ }
136
+
137
+ function formatInline(ann) {
138
+ var _serializeAnnotation3 = serializeAnnotation(ann),
139
+ serialized = _serializeAnnotation3[0],
140
+ annotation = _serializeAnnotation3[1];
141
+
142
+ if (annotation !== undefined) {
143
+ return serialized + '\n' + annotation;
144
+ } else {
145
+ return serialized;
146
+ }
147
+ }
148
+
149
+ function formatShort(ann) {
150
+ return (0, _utils.summarize)(ann, []).join('\n');
151
+ }
package/format.js.flow ADDED
@@ -0,0 +1,126 @@
1
+ // @flow strict
2
+
3
+ import { summarize as _summarize, asDate, INDENT, indent, isMultiline } from './_utils';
4
+ import type { Annotation, ArrayAnnotation, ObjectAnnotation } from './annotate';
5
+
6
+ function serializeString(s: string, width: number = 80): string {
7
+ // Full string
8
+ // Abbreviated to $maxlen i.e. "Vincent Driess..." [truncated]
9
+ let ser = JSON.stringify(s);
10
+ if (ser.length <= width) {
11
+ return ser;
12
+ }
13
+
14
+ // Cut off a bit
15
+ const truncated = s.substring(0, width - 15) + '...';
16
+ ser = JSON.stringify(truncated) + ' [truncated]';
17
+ return ser;
18
+ }
19
+
20
+ function serializeArray(annotation: ArrayAnnotation, prefix: string): string {
21
+ const { items } = annotation;
22
+ if (items.length === 0) {
23
+ return '[]';
24
+ }
25
+
26
+ const result = [];
27
+ items.forEach((item) => {
28
+ const [ser, ann] = serializeAnnotation(item, prefix + INDENT);
29
+ result.push(prefix + INDENT + ser + ',');
30
+ if (ann !== undefined) {
31
+ result.push(indent(ann, prefix + INDENT));
32
+ }
33
+ });
34
+ return ['[', ...result, prefix + ']'].join('\n');
35
+ }
36
+
37
+ function serializeObject(annotation: ObjectAnnotation, prefix: string): string {
38
+ const { fields } = annotation;
39
+
40
+ const fieldNames = Object.keys(fields);
41
+ if (fieldNames.length === 0) {
42
+ return '{}';
43
+ }
44
+
45
+ const result = [];
46
+ fieldNames.forEach((key) => {
47
+ const valueAnnotation = fields[key];
48
+ const kser = serializeValue(key);
49
+
50
+ const valPrefix = prefix + INDENT + ' '.repeat(kser.length + 2);
51
+ const [vser, vann] = serializeAnnotation(valueAnnotation, prefix + INDENT);
52
+
53
+ result.push(prefix + INDENT + kser + ': ' + vser + ',');
54
+ if (vann !== undefined) {
55
+ result.push(indent(vann, valPrefix));
56
+ }
57
+ });
58
+ return ['{', ...result, prefix + '}'].join('\n');
59
+ }
60
+
61
+ export function serializeValue(value: mixed): string {
62
+ // istanbul ignore else
63
+ if (typeof value === 'string') {
64
+ return serializeString(value);
65
+ } else if (typeof value === 'number' || typeof value === 'boolean') {
66
+ return value.toString();
67
+ } else if (value === null) {
68
+ return 'null';
69
+ } else if (value === undefined) {
70
+ return 'undefined';
71
+ } else {
72
+ const valueAsDate = asDate(value);
73
+ if (valueAsDate !== null) {
74
+ return `new Date(${JSON.stringify(valueAsDate.toISOString())})`;
75
+ } else if (value instanceof Date) {
76
+ // NOTE: Using `instanceof Date` is unreliable way of checking dates.
77
+ // If this case occurs (and it didn't pass the prior asDate())
78
+ // check, then this must be the case where it's an invalid date.
79
+ return '(Invalid Date)';
80
+ } else {
81
+ return '(unserializable)';
82
+ }
83
+ }
84
+ }
85
+
86
+ export function serializeAnnotation(
87
+ ann: Annotation,
88
+ prefix: string = '',
89
+ ): [string, string | void] {
90
+ // The serialized data (the input object echoed back)
91
+ let serialized;
92
+ if (ann.type === 'array') {
93
+ serialized = serializeArray(ann, prefix);
94
+ } else if (ann.type === 'object') {
95
+ serialized = serializeObject(ann, prefix);
96
+ } else if (ann.type === 'function') {
97
+ serialized = '<function>';
98
+ } else if (ann.type === 'circular-ref') {
99
+ serialized = '<circular ref>';
100
+ } else if (ann.type === 'unknown') {
101
+ serialized = '???';
102
+ } else {
103
+ serialized = serializeValue(ann.value);
104
+ }
105
+
106
+ const text = ann.text;
107
+ if (text !== undefined) {
108
+ const sep = '^'.repeat(isMultiline(serialized) ? 1 : serialized.length);
109
+ return [serialized, [sep, text].join(isMultiline(text) ? '\n' : ' ')];
110
+ } else {
111
+ return [serialized, undefined];
112
+ }
113
+ }
114
+
115
+ export function formatInline(ann: Annotation): string {
116
+ const [serialized, annotation] = serializeAnnotation(ann);
117
+ if (annotation !== undefined) {
118
+ return serialized + '\n' + annotation;
119
+ } else {
120
+ return serialized;
121
+ }
122
+ }
123
+
124
+ export function formatShort(ann: Annotation): string {
125
+ return _summarize(ann, []).join('\n');
126
+ }