seroval 0.2.0 → 0.3.0
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.
- package/README.md +36 -15
- package/dist/cjs/development/index.cjs +625 -434
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +2 -2
- package/dist/esm/development/index.mjs +625 -434
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +2 -2
- package/dist/types/checks.d.ts +5 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/tree.d.ts +93 -0
- package/dist/types/types.d.ts +11 -3
- package/package.json +2 -2
- package/src/checks.ts +41 -0
- package/src/index.ts +25 -37
- package/src/serialize-primitive.ts +10 -7
- package/src/tree.ts +963 -0
- package/src/types.ts +41 -4
- package/dist/types/array.d.ts +0 -2
- package/dist/types/async.d.ts +0 -4
- package/dist/types/context.d.ts +0 -33
- package/dist/types/is-primitive.d.ts +0 -2
- package/dist/types/is-promise.d.ts +0 -1
- package/dist/types/sync.d.ts +0 -4
- package/src/array.ts +0 -18
- package/src/async.ts +0 -229
- package/src/context.ts +0 -200
- package/src/is-primitive.ts +0 -14
- package/src/is-promise.ts +0 -6
- package/src/sync.ts +0 -199
package/src/sync.ts
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { forEach, join } from './array';
|
|
2
|
-
import {
|
|
3
|
-
SerializationContext,
|
|
4
|
-
insertRef,
|
|
5
|
-
constructorCheck,
|
|
6
|
-
getRefParam,
|
|
7
|
-
createRef,
|
|
8
|
-
assignRef,
|
|
9
|
-
createSetAdd,
|
|
10
|
-
EMPTY_SET,
|
|
11
|
-
createMapSet,
|
|
12
|
-
EMPTY_MAP,
|
|
13
|
-
createArrayAssign,
|
|
14
|
-
EMPTY_ARRAY,
|
|
15
|
-
createObjectIdentifierAssign,
|
|
16
|
-
createObjectComputedAssign,
|
|
17
|
-
} from './context';
|
|
18
|
-
import isPrimitive from './is-primitive';
|
|
19
|
-
import quote from './quote';
|
|
20
|
-
import serializePrimitive from './serialize-primitive';
|
|
21
|
-
import { AsyncServerValue, ServerValue } from './types';
|
|
22
|
-
|
|
23
|
-
export function lookupRefs(ctx: SerializationContext, current: ServerValue) {
|
|
24
|
-
if (isPrimitive(current)) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (Array.isArray(current)) {
|
|
28
|
-
if (insertRef(ctx, current)) {
|
|
29
|
-
forEach(current, (value) => {
|
|
30
|
-
lookupRefs(ctx, value);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
} else if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
|
|
34
|
-
if (insertRef(ctx, current)) {
|
|
35
|
-
for (const item of current.keys()) {
|
|
36
|
-
lookupRefs(ctx, item);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
} else if (constructorCheck<Map<AsyncServerValue, AsyncServerValue>>(current, Map)) {
|
|
40
|
-
if (insertRef(ctx, current)) {
|
|
41
|
-
for (const [key, value] of current.entries()) {
|
|
42
|
-
lookupRefs(ctx, key);
|
|
43
|
-
lookupRefs(ctx, value);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
} else if (
|
|
47
|
-
(current.constructor === Object || current.constructor == null)
|
|
48
|
-
&& insertRef(ctx, current)
|
|
49
|
-
) {
|
|
50
|
-
forEach(Object.values(current), (value) => {
|
|
51
|
-
lookupRefs(ctx, value);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function traverseSync(
|
|
57
|
-
ctx: SerializationContext,
|
|
58
|
-
current: ServerValue,
|
|
59
|
-
): string {
|
|
60
|
-
// Skip primitives
|
|
61
|
-
if (isPrimitive(current)) {
|
|
62
|
-
return serializePrimitive(current);
|
|
63
|
-
}
|
|
64
|
-
// Get reference of the current object
|
|
65
|
-
let refResult = ctx.refs.get(current);
|
|
66
|
-
if (refResult != null) {
|
|
67
|
-
// Return the reference if already assigned a value
|
|
68
|
-
if (ctx.assignedRefs.has(refResult)) {
|
|
69
|
-
return getRefParam(ctx, refResult);
|
|
70
|
-
}
|
|
71
|
-
// Early sign (to prevent recursion)
|
|
72
|
-
ctx.assignedRefs.add(refResult);
|
|
73
|
-
}
|
|
74
|
-
function getCurrentRef() {
|
|
75
|
-
// This object received a ref, we must generate a setter ref
|
|
76
|
-
if (refResult == null) {
|
|
77
|
-
refResult = createRef(ctx, current);
|
|
78
|
-
}
|
|
79
|
-
return refResult;
|
|
80
|
-
}
|
|
81
|
-
function processRef(value: string) {
|
|
82
|
-
if (refResult != null) {
|
|
83
|
-
return assignRef(ctx, refResult, value);
|
|
84
|
-
}
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
|
-
// Transform Set
|
|
88
|
-
if (constructorCheck<Set<ServerValue>>(current, Set)) {
|
|
89
|
-
if (current.size) {
|
|
90
|
-
const values: string[] = [];
|
|
91
|
-
|
|
92
|
-
ctx.stack.add(current);
|
|
93
|
-
for (const value of current.keys()) {
|
|
94
|
-
if (ctx.stack.has(value)) {
|
|
95
|
-
// Received a ref, this might be a recursive ref, defer an assignment
|
|
96
|
-
createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
|
|
97
|
-
} else {
|
|
98
|
-
values.push(traverseSync(ctx, value));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
ctx.stack.delete(current);
|
|
102
|
-
|
|
103
|
-
return processRef(values.length ? `new Set([${join(values, ',')}])` : EMPTY_SET);
|
|
104
|
-
}
|
|
105
|
-
return EMPTY_SET;
|
|
106
|
-
}
|
|
107
|
-
if (constructorCheck<Map<ServerValue, ServerValue>>(current, Map)) {
|
|
108
|
-
if (current.size) {
|
|
109
|
-
const values: string[] = [];
|
|
110
|
-
|
|
111
|
-
ctx.stack.add(current);
|
|
112
|
-
for (const [key, value] of current.entries()) {
|
|
113
|
-
if (ctx.stack.has(key)) {
|
|
114
|
-
const ref = getCurrentRef();
|
|
115
|
-
const keyRef = getRefParam(ctx, createRef(ctx, key));
|
|
116
|
-
if (ctx.stack.has(value)) {
|
|
117
|
-
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
118
|
-
createMapSet(ctx, ref, keyRef, valueRef);
|
|
119
|
-
} else {
|
|
120
|
-
createMapSet(ctx, ref, keyRef, traverseSync(ctx, value));
|
|
121
|
-
}
|
|
122
|
-
} else if (ctx.stack.has(value)) {
|
|
123
|
-
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
124
|
-
createMapSet(ctx, getCurrentRef(), traverseSync(ctx, key), valueRef);
|
|
125
|
-
} else {
|
|
126
|
-
values.push(`[${traverseSync(ctx, key)},${traverseSync(ctx, value)}]`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
ctx.stack.delete(current);
|
|
130
|
-
return processRef(values.length ? `new Map([${join(values, ',')}])` : EMPTY_MAP);
|
|
131
|
-
}
|
|
132
|
-
return EMPTY_MAP;
|
|
133
|
-
}
|
|
134
|
-
if (Array.isArray(current)) {
|
|
135
|
-
if (current.length) {
|
|
136
|
-
let values = '';
|
|
137
|
-
|
|
138
|
-
ctx.stack.add(current);
|
|
139
|
-
forEach(current, (item, i) => {
|
|
140
|
-
if (i in current) {
|
|
141
|
-
if (ctx.stack.has(item)) {
|
|
142
|
-
const refParam = getRefParam(ctx, createRef(ctx, item));
|
|
143
|
-
createArrayAssign(ctx, getCurrentRef(), i, refParam);
|
|
144
|
-
values += ',';
|
|
145
|
-
} else {
|
|
146
|
-
values += traverseSync(ctx, item);
|
|
147
|
-
if (i < current.length - 1) {
|
|
148
|
-
values += ',';
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
values += ',';
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
ctx.stack.delete(current);
|
|
156
|
-
return processRef(`[${values}]`);
|
|
157
|
-
}
|
|
158
|
-
return EMPTY_ARRAY;
|
|
159
|
-
}
|
|
160
|
-
const empty = current.constructor == null;
|
|
161
|
-
if (current.constructor === Object || empty) {
|
|
162
|
-
const values: string[] = [];
|
|
163
|
-
|
|
164
|
-
ctx.stack.add(current);
|
|
165
|
-
forEach(Object.entries(current), ([key, value]) => {
|
|
166
|
-
const check = Number(key);
|
|
167
|
-
// Test if key is a valid number or JS identifier
|
|
168
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
169
|
-
if (
|
|
170
|
-
check >= 0
|
|
171
|
-
|| (Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key))
|
|
172
|
-
) {
|
|
173
|
-
if (ctx.stack.has(value)) {
|
|
174
|
-
const ref = getCurrentRef();
|
|
175
|
-
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
176
|
-
if (!Number.isNaN(check)) {
|
|
177
|
-
createObjectComputedAssign(ctx, ref, key, refParam);
|
|
178
|
-
} else {
|
|
179
|
-
createObjectIdentifierAssign(ctx, ref, key, refParam);
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
values.push(`${key}:${traverseSync(ctx, value)}`);
|
|
183
|
-
}
|
|
184
|
-
} else if (ctx.stack.has(value)) {
|
|
185
|
-
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
186
|
-
createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
|
|
187
|
-
} else {
|
|
188
|
-
values.push(`${quote(key)}:${traverseSync(ctx, value)}`);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
ctx.stack.delete(current);
|
|
192
|
-
const value = `{${join(values, ',')}}`;
|
|
193
|
-
if (empty) {
|
|
194
|
-
return processRef(`Object.assign(Object.create(null),${value})`);
|
|
195
|
-
}
|
|
196
|
-
return processRef(value);
|
|
197
|
-
}
|
|
198
|
-
throw new Error('Unserializable value');
|
|
199
|
-
}
|