seroval 0.2.1 → 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 +7 -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 +37 -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/types.ts
CHANGED
|
@@ -5,23 +5,56 @@ export type PrimitiveValue =
|
|
|
5
5
|
| number
|
|
6
6
|
| undefined
|
|
7
7
|
| null
|
|
8
|
-
| bigint
|
|
8
|
+
| bigint;
|
|
9
|
+
|
|
10
|
+
export type ErrorValue =
|
|
11
|
+
| Error
|
|
12
|
+
| AggregateError
|
|
13
|
+
| EvalError
|
|
14
|
+
| RangeError
|
|
15
|
+
| ReferenceError
|
|
16
|
+
| TypeError
|
|
17
|
+
| SyntaxError
|
|
18
|
+
| URIError;
|
|
19
|
+
|
|
20
|
+
export type TypedArrayValue =
|
|
21
|
+
| Int8Array
|
|
22
|
+
| Int16Array
|
|
23
|
+
| Int32Array
|
|
24
|
+
| Uint8Array
|
|
25
|
+
| Uint16Array
|
|
26
|
+
| Uint32Array
|
|
27
|
+
| Uint8ClampedArray
|
|
28
|
+
| Float32Array
|
|
29
|
+
| Float64Array
|
|
30
|
+
| BigInt64Array
|
|
31
|
+
| BigUint64Array;
|
|
32
|
+
|
|
33
|
+
export type SemiPrimitiveValue =
|
|
34
|
+
| RegExp
|
|
9
35
|
| Date
|
|
10
|
-
|
|
|
36
|
+
| TypedArrayValue;
|
|
11
37
|
|
|
12
|
-
export type
|
|
38
|
+
export type CommonServerValue =
|
|
13
39
|
| PrimitiveValue
|
|
40
|
+
| SemiPrimitiveValue
|
|
41
|
+
| ErrorValue;
|
|
42
|
+
|
|
43
|
+
export type ServerValue =
|
|
44
|
+
| CommonServerValue
|
|
14
45
|
| Array<ServerValue>
|
|
15
46
|
| readonly ServerValue[]
|
|
47
|
+
| Iterable<ServerValue>
|
|
16
48
|
| { [key: string | number]: ServerValue }
|
|
17
49
|
| { readonly [key: string | number]: ServerValue }
|
|
18
50
|
| Set<ServerValue>
|
|
19
51
|
| Map<ServerValue, ServerValue>;
|
|
20
52
|
|
|
21
53
|
export type AsyncServerValue =
|
|
22
|
-
|
|
|
54
|
+
| CommonServerValue
|
|
23
55
|
| Array<AsyncServerValue>
|
|
24
56
|
| readonly AsyncServerValue[]
|
|
57
|
+
| Iterable<AsyncServerValue>
|
|
25
58
|
| { [key: string | number]: AsyncServerValue }
|
|
26
59
|
| { readonly [key: string | number]: AsyncServerValue }
|
|
27
60
|
| Set<AsyncServerValue>
|
package/dist/types/array.d.ts
DELETED
package/dist/types/async.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { SerializationContext } from './context';
|
|
2
|
-
import { AsyncServerValue } from './types';
|
|
3
|
-
export declare function lookupRefsAsync(ctx: SerializationContext, current: AsyncServerValue): Promise<void>;
|
|
4
|
-
export declare function traverseAsync(ctx: SerializationContext, current: AsyncServerValue): Promise<string>;
|
package/dist/types/context.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { AsyncServerValue } from './types';
|
|
2
|
-
export declare const EMPTY_SET = "new Set";
|
|
3
|
-
export declare const EMPTY_MAP = "new Map";
|
|
4
|
-
export declare const EMPTY_ARRAY = "[]";
|
|
5
|
-
export type Assignment = [source: string, value: string];
|
|
6
|
-
export type MapSet = [source: string, key: string, value: string];
|
|
7
|
-
export type SetAdd = [source: string, value: string];
|
|
8
|
-
export interface SerializationContext {
|
|
9
|
-
stack: Set<unknown>;
|
|
10
|
-
assignedRefs: Set<number>;
|
|
11
|
-
vars: string[];
|
|
12
|
-
assignments: Assignment[];
|
|
13
|
-
mapSets: MapSet[];
|
|
14
|
-
setAdds: SetAdd[];
|
|
15
|
-
refCount: Map<unknown, number>;
|
|
16
|
-
refs: Map<unknown, number>;
|
|
17
|
-
}
|
|
18
|
-
export declare function createSerializationContext(): SerializationContext;
|
|
19
|
-
export declare function resolveAssignments(ctx: SerializationContext): string;
|
|
20
|
-
export declare function resolveMapSets(ctx: SerializationContext): string;
|
|
21
|
-
export declare function resolveSetAdds(ctx: SerializationContext): string;
|
|
22
|
-
export declare function resolvePatches(ctx: SerializationContext): string;
|
|
23
|
-
export declare function insertRef(ctx: SerializationContext, current: unknown): boolean;
|
|
24
|
-
export declare function constructorCheck<T extends NonNullable<AsyncServerValue>>(value: NonNullable<AsyncServerValue>, constructor: unknown): value is T;
|
|
25
|
-
export declare function createRef(ctx: SerializationContext, value: unknown): number;
|
|
26
|
-
export declare function getRefParam(ctx: SerializationContext, index: number): string;
|
|
27
|
-
export declare function assignRef(ctx: SerializationContext, index: number, value: string): string;
|
|
28
|
-
export declare function createAssignment(ctx: SerializationContext, source: string, value: string): void;
|
|
29
|
-
export declare function createSetAdd(ctx: SerializationContext, ref: number, value: string): void;
|
|
30
|
-
export declare function createMapSet(ctx: SerializationContext, ref: number, key: string, value: string): void;
|
|
31
|
-
export declare function createArrayAssign(ctx: SerializationContext, ref: number, index: number, value: string): void;
|
|
32
|
-
export declare function createObjectIdentifierAssign(ctx: SerializationContext, ref: number, key: string, value: string): void;
|
|
33
|
-
export declare function createObjectComputedAssign(ctx: SerializationContext, ref: number, key: string, value: string): void;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function isPromise<T>(obj: unknown): obj is PromiseLike<T>;
|
package/dist/types/sync.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { SerializationContext } from './context';
|
|
2
|
-
import { ServerValue } from './types';
|
|
3
|
-
export declare function lookupRefs(ctx: SerializationContext, current: ServerValue): void;
|
|
4
|
-
export declare function traverseSync(ctx: SerializationContext, current: ServerValue): string;
|
package/src/array.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export function forEach<T>(arr: T[], callback: (value: T, index: number) => (boolean | void)) {
|
|
2
|
-
for (let i = 0, len = arr.length; i < len; i++) {
|
|
3
|
-
if (callback(arr[i], i)) {
|
|
4
|
-
break;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function join(arr: string[], joiner: string): string {
|
|
10
|
-
let result = '';
|
|
11
|
-
forEach(arr, (value, index) => {
|
|
12
|
-
result += value;
|
|
13
|
-
if (index < arr.length - 1) {
|
|
14
|
-
result += joiner;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return result;
|
|
18
|
-
}
|
package/src/async.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-await-in-loop */
|
|
2
|
-
import { join } from './array';
|
|
3
|
-
import {
|
|
4
|
-
SerializationContext,
|
|
5
|
-
insertRef,
|
|
6
|
-
constructorCheck,
|
|
7
|
-
getRefParam,
|
|
8
|
-
createRef,
|
|
9
|
-
assignRef,
|
|
10
|
-
createSetAdd,
|
|
11
|
-
EMPTY_SET,
|
|
12
|
-
createMapSet,
|
|
13
|
-
EMPTY_MAP,
|
|
14
|
-
createArrayAssign,
|
|
15
|
-
EMPTY_ARRAY,
|
|
16
|
-
createObjectIdentifierAssign,
|
|
17
|
-
createObjectComputedAssign,
|
|
18
|
-
} from './context';
|
|
19
|
-
import isPrimitive from './is-primitive';
|
|
20
|
-
import isPromise from './is-promise';
|
|
21
|
-
import quote from './quote';
|
|
22
|
-
import serializePrimitive from './serialize-primitive';
|
|
23
|
-
import { ServerValue, AsyncServerValue } from './types';
|
|
24
|
-
|
|
25
|
-
export async function lookupRefsAsync(
|
|
26
|
-
ctx: SerializationContext,
|
|
27
|
-
current: AsyncServerValue,
|
|
28
|
-
) {
|
|
29
|
-
if (isPrimitive(current)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (isPromise(current)) {
|
|
33
|
-
if (insertRef(ctx, current)) {
|
|
34
|
-
await current.then((value) => lookupRefsAsync(ctx, value));
|
|
35
|
-
}
|
|
36
|
-
} else if (Array.isArray(current)) {
|
|
37
|
-
if (insertRef(ctx, current)) {
|
|
38
|
-
for (const value of current) {
|
|
39
|
-
await lookupRefsAsync(ctx, value);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
} else if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
|
|
43
|
-
if (insertRef(ctx, current)) {
|
|
44
|
-
for (const item of current.keys()) {
|
|
45
|
-
await lookupRefsAsync(ctx, item);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
} else if (constructorCheck<Map<AsyncServerValue, AsyncServerValue>>(current, Map)) {
|
|
49
|
-
if (insertRef(ctx, current)) {
|
|
50
|
-
for (const [key, value] of current.entries()) {
|
|
51
|
-
await lookupRefsAsync(ctx, key);
|
|
52
|
-
await lookupRefsAsync(ctx, value);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
} else if (
|
|
56
|
-
(current.constructor === Object || current.constructor == null)
|
|
57
|
-
&& insertRef(ctx, current)
|
|
58
|
-
) {
|
|
59
|
-
for (const value of Object.values(current)) {
|
|
60
|
-
await lookupRefsAsync(ctx, value);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export async function traverseAsync(
|
|
66
|
-
ctx: SerializationContext,
|
|
67
|
-
current: AsyncServerValue,
|
|
68
|
-
): Promise<string> {
|
|
69
|
-
// Skip primitives
|
|
70
|
-
if (isPrimitive(current)) {
|
|
71
|
-
return serializePrimitive(current);
|
|
72
|
-
}
|
|
73
|
-
// Get reference of the current object
|
|
74
|
-
let refResult = ctx.refs.get(current);
|
|
75
|
-
if (refResult != null) {
|
|
76
|
-
// Return the reference if already assigned a value
|
|
77
|
-
if (ctx.assignedRefs.has(refResult)) {
|
|
78
|
-
return getRefParam(ctx, refResult);
|
|
79
|
-
}
|
|
80
|
-
// Early sign (to prevent recursion)
|
|
81
|
-
ctx.assignedRefs.add(refResult);
|
|
82
|
-
}
|
|
83
|
-
function getCurrentRef() {
|
|
84
|
-
// This object received a ref, we must generate a setter ref
|
|
85
|
-
if (refResult == null) {
|
|
86
|
-
refResult = createRef(ctx, current);
|
|
87
|
-
}
|
|
88
|
-
return refResult;
|
|
89
|
-
}
|
|
90
|
-
function processRef(value: string) {
|
|
91
|
-
if (refResult != null) {
|
|
92
|
-
return assignRef(ctx, refResult, value);
|
|
93
|
-
}
|
|
94
|
-
return value;
|
|
95
|
-
}
|
|
96
|
-
if (isPromise(current)) {
|
|
97
|
-
return current.then(async (value) => {
|
|
98
|
-
ctx.stack.add(current);
|
|
99
|
-
let result: string;
|
|
100
|
-
if (ctx.stack.has(value)) {
|
|
101
|
-
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
102
|
-
result = `Promise.resolve().then(()=>${refParam})`;
|
|
103
|
-
} else {
|
|
104
|
-
result = `Promise.resolve(${await traverseAsync(ctx, value)})`;
|
|
105
|
-
}
|
|
106
|
-
ctx.stack.delete(current);
|
|
107
|
-
return processRef(result);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
// Transform Set
|
|
111
|
-
if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
|
|
112
|
-
if (current.size) {
|
|
113
|
-
const values: string[] = [];
|
|
114
|
-
|
|
115
|
-
ctx.stack.add(current);
|
|
116
|
-
for (const value of current.keys()) {
|
|
117
|
-
if (ctx.stack.has(value)) {
|
|
118
|
-
// Received a ref, this might be a recursive ref, defer an assignment
|
|
119
|
-
createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
|
|
120
|
-
} else {
|
|
121
|
-
values.push(await traverseAsync(ctx, value));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
ctx.stack.delete(current);
|
|
125
|
-
|
|
126
|
-
return processRef(values.length ? `new Set([${join(values, ',')}])` : EMPTY_SET);
|
|
127
|
-
}
|
|
128
|
-
return EMPTY_SET;
|
|
129
|
-
}
|
|
130
|
-
if (constructorCheck<Map<ServerValue, ServerValue>>(current, Map)) {
|
|
131
|
-
if (current.size) {
|
|
132
|
-
const values: string[] = [];
|
|
133
|
-
|
|
134
|
-
ctx.stack.add(current);
|
|
135
|
-
for (const [key, value] of current.entries()) {
|
|
136
|
-
if (ctx.stack.has(key)) {
|
|
137
|
-
const ref = getCurrentRef();
|
|
138
|
-
const keyRef = getRefParam(ctx, createRef(ctx, key));
|
|
139
|
-
if (ctx.stack.has(value)) {
|
|
140
|
-
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
141
|
-
createMapSet(ctx, ref, keyRef, valueRef);
|
|
142
|
-
} else {
|
|
143
|
-
const valueResult = await traverseAsync(ctx, value);
|
|
144
|
-
createMapSet(ctx, ref, keyRef, valueResult);
|
|
145
|
-
}
|
|
146
|
-
} else if (ctx.stack.has(value)) {
|
|
147
|
-
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
148
|
-
const keyResult = await traverseAsync(ctx, key);
|
|
149
|
-
createMapSet(ctx, getCurrentRef(), keyResult, valueRef);
|
|
150
|
-
} else {
|
|
151
|
-
const keyResult = await traverseAsync(ctx, key);
|
|
152
|
-
const valueResult = await traverseAsync(ctx, value);
|
|
153
|
-
values.push(`[${keyResult},${valueResult}]`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
ctx.stack.delete(current);
|
|
157
|
-
return processRef(values.length ? `new Map([${join(values, ',')}])` : EMPTY_MAP);
|
|
158
|
-
}
|
|
159
|
-
return EMPTY_MAP;
|
|
160
|
-
}
|
|
161
|
-
if (Array.isArray(current)) {
|
|
162
|
-
if (current.length) {
|
|
163
|
-
let values = '';
|
|
164
|
-
|
|
165
|
-
ctx.stack.add(current);
|
|
166
|
-
for (let i = 0, len = current.length; i < len; i += 1) {
|
|
167
|
-
if (i in current) {
|
|
168
|
-
const item = current[i];
|
|
169
|
-
if (ctx.stack.has(item)) {
|
|
170
|
-
const refParam = getRefParam(ctx, createRef(ctx, item));
|
|
171
|
-
createArrayAssign(ctx, getCurrentRef(), i, refParam);
|
|
172
|
-
values += ',';
|
|
173
|
-
} else {
|
|
174
|
-
values += await traverseAsync(ctx, item);
|
|
175
|
-
if (i < current.length - 1) {
|
|
176
|
-
values += ',';
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
values += ',';
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
ctx.stack.delete(current);
|
|
184
|
-
return processRef(`[${values}]`);
|
|
185
|
-
}
|
|
186
|
-
return EMPTY_ARRAY;
|
|
187
|
-
}
|
|
188
|
-
const empty = current.constructor == null;
|
|
189
|
-
if (current.constructor === Object || empty) {
|
|
190
|
-
const values: string[] = [];
|
|
191
|
-
|
|
192
|
-
ctx.stack.add(current);
|
|
193
|
-
for (const [key, value] of Object.entries(current)) {
|
|
194
|
-
const check = Number(key);
|
|
195
|
-
// Test if key is a valid number or JS identifier
|
|
196
|
-
// so that we don't have to serialize the key and wrap with brackets
|
|
197
|
-
if (
|
|
198
|
-
check >= 0
|
|
199
|
-
|| (Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key))
|
|
200
|
-
) {
|
|
201
|
-
if (ctx.stack.has(value)) {
|
|
202
|
-
const ref = getCurrentRef();
|
|
203
|
-
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
204
|
-
if (Number.isNaN(check)) {
|
|
205
|
-
createObjectIdentifierAssign(ctx, ref, key, refParam);
|
|
206
|
-
} else {
|
|
207
|
-
createObjectComputedAssign(ctx, ref, key, refParam);
|
|
208
|
-
}
|
|
209
|
-
} else {
|
|
210
|
-
const valueResult = await traverseAsync(ctx, value as AsyncServerValue);
|
|
211
|
-
values.push(`${key}:${valueResult}`);
|
|
212
|
-
}
|
|
213
|
-
} else if (ctx.stack.has(value)) {
|
|
214
|
-
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
215
|
-
createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
|
|
216
|
-
} else {
|
|
217
|
-
const valueResult = await traverseAsync(ctx, value as AsyncServerValue);
|
|
218
|
-
values.push(`${quote(key)}:${valueResult}`);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
ctx.stack.delete(current);
|
|
222
|
-
const value = `{${join(values, ',')}}`;
|
|
223
|
-
if (empty) {
|
|
224
|
-
return processRef(`Object.assign(Object.create(null),${value})`);
|
|
225
|
-
}
|
|
226
|
-
return processRef(value);
|
|
227
|
-
}
|
|
228
|
-
throw new Error('Unserializable value');
|
|
229
|
-
}
|
package/src/context.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { forEach, join } from './array';
|
|
2
|
-
import getIdentifier from './get-identifier';
|
|
3
|
-
import { AsyncServerValue } from './types';
|
|
4
|
-
|
|
5
|
-
export const EMPTY_SET = 'new Set';
|
|
6
|
-
export const EMPTY_MAP = 'new Map';
|
|
7
|
-
export const EMPTY_ARRAY = '[]';
|
|
8
|
-
|
|
9
|
-
// Array of assignments to be done (used for recursion)
|
|
10
|
-
export type Assignment = [source: string, value: string];
|
|
11
|
-
|
|
12
|
-
// Array of Map.prototype.set calls
|
|
13
|
-
export type MapSet = [source: string, key: string, value: string];
|
|
14
|
-
|
|
15
|
-
// Array of Set.prototype.add calls
|
|
16
|
-
export type SetAdd = [source: string, value: string];
|
|
17
|
-
|
|
18
|
-
export interface SerializationContext {
|
|
19
|
-
stack: Set<unknown>;
|
|
20
|
-
// Set to check if ref id already has an assigned value
|
|
21
|
-
assignedRefs: Set<number>;
|
|
22
|
-
// Variables
|
|
23
|
-
vars: string[];
|
|
24
|
-
// Array of assignments to be done (used for recursion)
|
|
25
|
-
assignments: Assignment[];
|
|
26
|
-
// Array of Map.prototype.set calls
|
|
27
|
-
mapSets: MapSet[];
|
|
28
|
-
// Array of Set.prototype.add calls
|
|
29
|
-
setAdds: SetAdd[];
|
|
30
|
-
// Reference counter
|
|
31
|
-
refCount: Map<unknown, number>;
|
|
32
|
-
// Value-to-ref map
|
|
33
|
-
refs: Map<unknown, number>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function createSerializationContext(): SerializationContext {
|
|
37
|
-
return {
|
|
38
|
-
refCount: new Map(),
|
|
39
|
-
stack: new Set(),
|
|
40
|
-
refs: new Map(),
|
|
41
|
-
assignedRefs: new Set(),
|
|
42
|
-
vars: [],
|
|
43
|
-
assignments: [],
|
|
44
|
-
mapSets: [],
|
|
45
|
-
setAdds: [],
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function resolveAssignments(ctx: SerializationContext) {
|
|
50
|
-
if (ctx.assignments.length) {
|
|
51
|
-
const result: Record<string, string> = {};
|
|
52
|
-
|
|
53
|
-
// Merge all assignments with similar source
|
|
54
|
-
forEach(ctx.assignments, ([source, value]) => {
|
|
55
|
-
if (value in result) {
|
|
56
|
-
result[value] = `${source}=${result[value]}`;
|
|
57
|
-
} else {
|
|
58
|
-
result[value] = `${source}=${value}`;
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return `${join(Object.values(result), ',')},`;
|
|
63
|
-
}
|
|
64
|
-
return '';
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function resolveMapSets(ctx: SerializationContext) {
|
|
68
|
-
if (ctx.mapSets.length) {
|
|
69
|
-
const result: Record<string, string> = {};
|
|
70
|
-
|
|
71
|
-
// Merge all assignments with similar source
|
|
72
|
-
forEach(ctx.mapSets, ([source, key, value]) => {
|
|
73
|
-
if (source in result) {
|
|
74
|
-
result[source] = `${result[source]}.set(${key},${value})`;
|
|
75
|
-
} else {
|
|
76
|
-
result[source] = `${source}.set(${key},${value})`;
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
return `${join(Object.values(result), ',')},`;
|
|
81
|
-
}
|
|
82
|
-
return '';
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function resolveSetAdds(ctx: SerializationContext) {
|
|
86
|
-
if (ctx.setAdds.length) {
|
|
87
|
-
const result: Record<string, string> = {};
|
|
88
|
-
|
|
89
|
-
// Merge all assignments with similar source
|
|
90
|
-
forEach(ctx.setAdds, ([source, value]) => {
|
|
91
|
-
if (source in result) {
|
|
92
|
-
result[source] = `${result[source]}.add(${value})`;
|
|
93
|
-
} else {
|
|
94
|
-
result[source] = `${source}.add(${value})`;
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
return `${join(Object.values(result), ',')},`;
|
|
99
|
-
}
|
|
100
|
-
return '';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function resolvePatches(ctx: SerializationContext) {
|
|
104
|
-
return `${resolveAssignments(ctx)}${resolveMapSets(ctx)}${resolveSetAdds(ctx)}`;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function insertRef(ctx: SerializationContext, current: unknown) {
|
|
108
|
-
const count = ctx.refCount.get(current) || 0;
|
|
109
|
-
ctx.refCount.set(current, count + 1);
|
|
110
|
-
return count === 0;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function constructorCheck<T extends NonNullable<AsyncServerValue>>(
|
|
114
|
-
value: NonNullable<AsyncServerValue>,
|
|
115
|
-
constructor: unknown,
|
|
116
|
-
): value is T {
|
|
117
|
-
return value.constructor === constructor;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function createRef(
|
|
121
|
-
ctx: SerializationContext,
|
|
122
|
-
value: unknown,
|
|
123
|
-
) {
|
|
124
|
-
const current = ctx.refs.get(value);
|
|
125
|
-
if (current != null) {
|
|
126
|
-
return current;
|
|
127
|
-
}
|
|
128
|
-
const id = ctx.refs.size;
|
|
129
|
-
ctx.refs.set(value, id);
|
|
130
|
-
return id;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function getRefParam(ctx: SerializationContext, index: number) {
|
|
134
|
-
if (ctx.vars[index]) {
|
|
135
|
-
return ctx.vars[index];
|
|
136
|
-
}
|
|
137
|
-
const result = getIdentifier(index);
|
|
138
|
-
ctx.vars[index] = result;
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export function assignRef(
|
|
143
|
-
ctx: SerializationContext,
|
|
144
|
-
index: number,
|
|
145
|
-
value: string,
|
|
146
|
-
) {
|
|
147
|
-
return `${getRefParam(ctx, index)}=${value}`;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function createAssignment(
|
|
151
|
-
ctx: SerializationContext,
|
|
152
|
-
source: string,
|
|
153
|
-
value: string,
|
|
154
|
-
) {
|
|
155
|
-
ctx.assignments.push([source, value]);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function createSetAdd(
|
|
159
|
-
ctx: SerializationContext,
|
|
160
|
-
ref: number,
|
|
161
|
-
value: string,
|
|
162
|
-
) {
|
|
163
|
-
ctx.setAdds.push([getRefParam(ctx, ref), value]);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function createMapSet(
|
|
167
|
-
ctx: SerializationContext,
|
|
168
|
-
ref: number,
|
|
169
|
-
key: string,
|
|
170
|
-
value: string,
|
|
171
|
-
) {
|
|
172
|
-
ctx.mapSets.push([getRefParam(ctx, ref), key, value]);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export function createArrayAssign(
|
|
176
|
-
ctx: SerializationContext,
|
|
177
|
-
ref: number,
|
|
178
|
-
index: number,
|
|
179
|
-
value: string,
|
|
180
|
-
) {
|
|
181
|
-
createAssignment(ctx, `${getRefParam(ctx, ref)}[${index}]`, value);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export function createObjectIdentifierAssign(
|
|
185
|
-
ctx: SerializationContext,
|
|
186
|
-
ref: number,
|
|
187
|
-
key: string,
|
|
188
|
-
value: string,
|
|
189
|
-
) {
|
|
190
|
-
createAssignment(ctx, `${getRefParam(ctx, ref)}.${key}`, value);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function createObjectComputedAssign(
|
|
194
|
-
ctx: SerializationContext,
|
|
195
|
-
ref: number,
|
|
196
|
-
key: string,
|
|
197
|
-
value: string,
|
|
198
|
-
) {
|
|
199
|
-
createAssignment(ctx, `${getRefParam(ctx, ref)}[${key}]`, value);
|
|
200
|
-
}
|
package/src/is-primitive.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { PrimitiveValue } from './types';
|
|
2
|
-
|
|
3
|
-
export default function isPrimitive(current: unknown): current is PrimitiveValue {
|
|
4
|
-
if (!current || current === true) {
|
|
5
|
-
return true;
|
|
6
|
-
}
|
|
7
|
-
const type = typeof current;
|
|
8
|
-
const classConst = current.constructor;
|
|
9
|
-
return type === 'number'
|
|
10
|
-
|| type === 'string'
|
|
11
|
-
|| type === 'bigint'
|
|
12
|
-
|| classConst === Date
|
|
13
|
-
|| classConst === RegExp;
|
|
14
|
-
}
|