jasone 0.0.4 → 1.0.0-beta.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 +47 -56
- package/index.d.ts +217 -231
- package/index.js +1 -1
- package/package.json +3 -5
- package/index.cjs +0 -1
- package/index.d.cts +0 -273
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Jasone
|
|
2
2
|
|
|
3
|
-
A lightweight, extensible JSON encoder and decoder
|
|
3
|
+
A lightweight, extensible JSON encoder and decoder that supports custom types.
|
|
4
4
|
|
|
5
|
-
**NOTICE:**
|
|
5
|
+
**NOTICE:** The documentation is still in progress and a lot of things are missing.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- 🚀 Fast & Lightweight: Minimal footprint.
|
|
10
|
+
- 🧩 Zero dependencies: No external packages required.
|
|
10
11
|
- 🔌 Extensible: Easily add custom types.
|
|
11
12
|
- 💻 TypeScript: Written in TypeScript for type safety and better DX.
|
|
12
13
|
|
|
@@ -33,87 +34,77 @@ bun add jasone
|
|
|
33
34
|
```ts
|
|
34
35
|
import { Jasone } from "jasone";
|
|
35
36
|
|
|
36
|
-
const data = { myDate: new Date("2025-04-05T14:30:00.
|
|
37
|
+
const data = { myDate: new Date("2025-04-05T14:30:00.000Z") };
|
|
37
38
|
const encoded = JSON.stringify(Jasone.encode(data));
|
|
38
39
|
|
|
39
|
-
console.log(encoded); // {"myDate":{"$":1,"
|
|
40
|
+
console.log(encoded); // {"myDate":{"$":1,"iso":"2025-04-05T12:30:00.000Z"}}
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
### Decoding
|
|
43
44
|
|
|
44
45
|
```ts
|
|
45
|
-
import {
|
|
46
|
+
import { Jasone } from "jasone";
|
|
46
47
|
|
|
47
|
-
const encoded = '{"myDate":{"$":1,"
|
|
48
|
+
const encoded = '{"myDate":{"$":1,"iso":"2025-04-05T12:30:00.000Z"}}';
|
|
48
49
|
const decoded = Jasone.decode(JSON.parse(encoded));
|
|
49
50
|
|
|
50
|
-
console.log(decoded); // { myDate: new Date("2025-04-
|
|
51
|
+
console.log(decoded); // { myDate: new Date("2025-04-05T12:30:00.000Z") }
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
## Advanced Usage
|
|
54
55
|
|
|
55
|
-
Adding custom types is
|
|
56
|
+
Adding custom types is easy. You just need to create a transformer object and register it with Jasone.
|
|
56
57
|
|
|
57
58
|
```ts
|
|
58
|
-
import { Jasone } from "jasone";
|
|
59
|
+
import { defaultTransformers, Jasone, type Transformer } from "jasone";
|
|
59
60
|
|
|
60
61
|
class Car {
|
|
61
|
-
constructor(
|
|
62
|
+
constructor(
|
|
63
|
+
public brand: string,
|
|
64
|
+
public model: string,
|
|
65
|
+
) {}
|
|
62
66
|
|
|
63
67
|
// ...
|
|
64
68
|
}
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Now the only thing left is to register the type with Jasone:
|
|
97
|
-
|
|
98
|
-
```ts
|
|
99
|
-
Jasone.register(myType);
|
|
70
|
+
const carType: Transformer<Car, { brand: string; model: string }> = {
|
|
71
|
+
encoder: {
|
|
72
|
+
// The filter is used to determine if the transformer can encode the given value.
|
|
73
|
+
// There are many different filters, but for classes, the class constructor is the most efficient.
|
|
74
|
+
filter: { class: Car },
|
|
75
|
+
// The handler is used to encode the value.
|
|
76
|
+
handler: ({ value }) => [
|
|
77
|
+
// The type Id is used to identify the type in the encoded object.
|
|
78
|
+
"Car",
|
|
79
|
+
// Any JSON-compatible value needed to reconstruct the original value.
|
|
80
|
+
{ brand: value.brand, model: value.model },
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
decoder: {
|
|
84
|
+
// The filter is used to determine if the transformer can decode the given value.
|
|
85
|
+
filter: "Car",
|
|
86
|
+
// The handler is used to decode the value.
|
|
87
|
+
handler: ({ value }) => new Car(value.brand, value.model),
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Register the type with an already instantiated Jasone instance
|
|
92
|
+
Jasone.register(carType);
|
|
93
|
+
|
|
94
|
+
// Or create a new Jasone instance with the type already registered
|
|
95
|
+
new Jasone({ types: [carType] });
|
|
96
|
+
|
|
97
|
+
// Or register the type with default built-in transformers like Date, BigInt, Map, etc.
|
|
98
|
+
new Jasone({ types: [carType, ...defaultTransformers] });
|
|
100
99
|
```
|
|
101
100
|
|
|
102
|
-
|
|
101
|
+
## Comparison with Superjson
|
|
103
102
|
|
|
104
|
-
|
|
105
|
-
const jasone = new Jasone({
|
|
106
|
-
types: [myType],
|
|
107
|
-
});
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Or
|
|
103
|
+
Jasone provides fewer features than Superjson, but is more performant, has a smaller footprint, and uses a simpler JSON format.
|
|
111
104
|
|
|
112
|
-
|
|
113
|
-
const jasone = new Jasone();
|
|
105
|
+
If you only need to encode and decode custom types, Jasone is a great choice.
|
|
114
106
|
|
|
115
|
-
|
|
116
|
-
```
|
|
107
|
+
If you need features like referential equality, Superjson may be a better choice. However, most of the time, you don't need those features.
|
|
117
108
|
|
|
118
109
|
## Contributing
|
|
119
110
|
|
package/index.d.ts
CHANGED
|
@@ -1,143 +1,80 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
1
2
|
/**
|
|
2
3
|
* A JSON-compatible value.
|
|
3
4
|
*/
|
|
4
5
|
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
5
|
-
|
|
6
|
+
[key: string]: JsonValue;
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
8
9
|
* The id of an encoded type to identify it on decoding.
|
|
9
10
|
*/
|
|
10
11
|
type TypeId = string | number;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
20
|
-
type TypeEncoder<TType = unknown, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = (value: TType, encode: <T = unknown>(value: T) => JsonValue) => TJson;
|
|
21
|
-
/**
|
|
22
|
-
* A function that is responsible to decode a type back to its decoded value.
|
|
23
|
-
*
|
|
24
|
-
* @param value The value to decode.
|
|
25
|
-
* @param encode A function that works exactly the same as `Jasone.decode` useful
|
|
26
|
-
* to decode values recursively. This function comes from the instance
|
|
27
|
-
* where the type transformer is registered, so it has the same types.
|
|
28
|
-
* @returns A JSON-compatible value.
|
|
29
|
-
*/
|
|
30
|
-
type TypeDecoder<TType = unknown, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = (value: TJson, decode: <T = unknown>(value: JsonValue) => T) => TType;
|
|
31
|
-
type MatchesFn<TType = unknown> = (value: unknown) => value is TType;
|
|
32
|
-
type ClassLike<TInstance> = new <T>(...args: any[]) => TInstance;
|
|
33
|
-
declare const typeOf: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
|
|
34
|
-
type TypeOf = typeof typeOf;
|
|
35
|
-
|
|
36
|
-
type TypeMatcher<TType> = {
|
|
37
|
-
/**
|
|
38
|
-
* The function that is responsible to determine if a value can be
|
|
39
|
-
* encoded with this transformer.
|
|
40
|
-
*/
|
|
41
|
-
matches: MatchesFn<TType>;
|
|
42
|
-
} | {
|
|
43
|
-
/**
|
|
44
|
-
* The class that can be encoded with this transformer.
|
|
45
|
-
*
|
|
46
|
-
* Using the `target` property only works on classes with an
|
|
47
|
-
* `constructor`. Internally, Jasone matches the constructor of the
|
|
48
|
-
* class with the `target` property.
|
|
49
|
-
*/
|
|
50
|
-
target: ClassLike<TType>;
|
|
12
|
+
type ClassLike<TInstance> = new (...args: any[]) => TInstance;
|
|
13
|
+
declare const nonJsonTypes: ("bigint" | "symbol" | "undefined" | "object" | "function")[];
|
|
14
|
+
type NonJsonType = {
|
|
15
|
+
bigint: bigint;
|
|
16
|
+
function: Function;
|
|
17
|
+
object: object;
|
|
18
|
+
symbol: symbol;
|
|
19
|
+
undefined: undefined;
|
|
51
20
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* to avoid conflicts with built-in types (which used positive integers).
|
|
61
|
-
*/
|
|
62
|
-
typeId: string | number;
|
|
63
|
-
/**
|
|
64
|
-
* The function that is responsible to encode the type into a JSON-compatible
|
|
65
|
-
* value.
|
|
66
|
-
*/
|
|
67
|
-
encode: TypeEncoder<TType, TJson>;
|
|
68
|
-
/**
|
|
69
|
-
* The function that is responsible to decode the type from a JSON-compatible
|
|
70
|
-
* value.
|
|
71
|
-
*/
|
|
72
|
-
decode: TypeDecoder<TType, TJson>;
|
|
21
|
+
type EncodeFilter<TType> = {
|
|
22
|
+
class?: ClassLike<TType>;
|
|
23
|
+
any?: (value: unknown) => boolean;
|
|
24
|
+
} & { [Key in keyof NonJsonType]?: ((value: NonJsonType[Key]) => boolean) | boolean };
|
|
25
|
+
type EncodeHandler<TType, TJson extends JsonValue> = (ctx: EncodeContext<TType>) => EncodeResult<TJson>;
|
|
26
|
+
type EncodeContext<TType> = {
|
|
27
|
+
value: TType;
|
|
28
|
+
jasone: Jasone;
|
|
73
29
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
source: string;
|
|
97
|
-
flags: string;
|
|
98
|
-
}>;
|
|
99
|
-
|
|
100
|
-
declare const setType: TypeTransformer<Set<unknown>, {
|
|
101
|
-
set: JsonValue[];
|
|
102
|
-
}>;
|
|
103
|
-
|
|
104
|
-
declare const undefinedType: TypeTransformer<undefined, {}>;
|
|
105
|
-
|
|
106
|
-
declare const urlType: TypeTransformer<URL, {
|
|
107
|
-
url: string;
|
|
108
|
-
}>;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* The default types that are used by the default Jasone instance.
|
|
112
|
-
*/
|
|
113
|
-
declare const defaultTypes: TypeTransformer<any, any>[];
|
|
114
|
-
|
|
30
|
+
type EncodeResult<TJson extends JsonValue> = TJson extends Record<string, JsonValue> ? [TypeId, TJson] | [null, JsonValue] : [null, JsonValue];
|
|
31
|
+
type Encoder<TType = unknown, TJson extends JsonValue = JsonValue> = {
|
|
32
|
+
filter?: EncodeFilter<TType> | EncodeFilter<TType>[];
|
|
33
|
+
handler: EncodeHandler<TType, TJson>;
|
|
34
|
+
};
|
|
35
|
+
type DecodeFilter = TypeId | ((typeId: TypeId, value: Record<string, JsonValue>) => boolean);
|
|
36
|
+
type DecodeContext<TJson extends Record<string, JsonValue>> = {
|
|
37
|
+
value: TJson;
|
|
38
|
+
typeId: TypeId;
|
|
39
|
+
jasone: Jasone;
|
|
40
|
+
};
|
|
41
|
+
type DecodeHandler<TType, TJson extends Record<string, JsonValue>> = (ctx: DecodeContext<TJson>) => TType;
|
|
42
|
+
type Decoder<TType = unknown, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = {
|
|
43
|
+
filter?: DecodeFilter | DecodeFilter[];
|
|
44
|
+
handler: DecodeHandler<TType, TJson>;
|
|
45
|
+
};
|
|
46
|
+
type Transformer<TType = unknown, TJson extends JsonValue = JsonValue> = {
|
|
47
|
+
encoder?: Encoder<TType, TJson>;
|
|
48
|
+
decoder?: TJson extends Record<string, JsonValue> ? Decoder<TType, TJson> : never;
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/jasone.d.ts
|
|
115
52
|
/**
|
|
116
53
|
* Jasone options that can be passed to the Jasone constructor.
|
|
117
54
|
*/
|
|
118
55
|
type JasoneOptions = {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
56
|
+
/**
|
|
57
|
+
* The type identifier that is used to determine if an object is a typed object.
|
|
58
|
+
*
|
|
59
|
+
* @default "$"
|
|
60
|
+
*/
|
|
61
|
+
typeIdentifier?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The type transformers that are used to transform types.
|
|
64
|
+
*
|
|
65
|
+
* If not provided, the default transformers are used. By providing your own transformers,
|
|
66
|
+
* the default transformers are not used anymore, so be sure to also include them if needed.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* // your custom transformer WITH default type transformers
|
|
71
|
+
* const jasone = new Jasone({ types: [myCustomTransformer, ...defaultTransformers] });
|
|
72
|
+
*
|
|
73
|
+
* // your custom transformer WITHOUT default type transformers
|
|
74
|
+
* const jasone = new Jasone({ types: [myCustomTransformer] });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
types?: Transformer<any, any>[];
|
|
141
78
|
};
|
|
142
79
|
/**
|
|
143
80
|
* Jasone is a JSON encoder and decoder that can handle custom types.
|
|
@@ -156,118 +93,167 @@ type JasoneOptions = {
|
|
|
156
93
|
*
|
|
157
94
|
* ```ts
|
|
158
95
|
* // use our own types without the default types (Date, BigInt, Map, etc.)
|
|
159
|
-
* const myInstance = new Jasone({
|
|
96
|
+
* const myInstance = new Jasone({
|
|
97
|
+
* types: [myCustomTransformer]
|
|
98
|
+
* });
|
|
160
99
|
*
|
|
161
100
|
* // or use our own types with the default types (recommend)
|
|
162
|
-
* const myInstance = new Jasone({
|
|
101
|
+
* const myInstance = new Jasone({
|
|
102
|
+
* types: [myCustomTransformer, ...defaultTransformers],
|
|
103
|
+
* });
|
|
163
104
|
*
|
|
164
105
|
* const encoded = myInstance.encode(value);
|
|
165
106
|
* const decoded = myInstance.decode(value);
|
|
166
107
|
* ```
|
|
167
108
|
*/
|
|
168
109
|
declare class Jasone {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
110
|
+
#private;
|
|
111
|
+
constructor(options?: JasoneOptions);
|
|
112
|
+
/**
|
|
113
|
+
* Register a new type to this Jasone instance.
|
|
114
|
+
*
|
|
115
|
+
* @param type The type to register.
|
|
116
|
+
*/
|
|
117
|
+
register<TType, TJson extends JsonValue>(transformer: Transformer<TType, TJson>): void;
|
|
118
|
+
/**
|
|
119
|
+
* Encode an arbitrary value to a JSON-compatible Jasone encoded value.
|
|
120
|
+
*
|
|
121
|
+
* @param value The value to encode.
|
|
122
|
+
* @returns A JSON-compatible Jasone encoded value.
|
|
123
|
+
*/
|
|
124
|
+
encode(value: unknown): JsonValue;
|
|
125
|
+
/**
|
|
126
|
+
* Decode an Jasone encoded value to its decoded value.
|
|
127
|
+
*
|
|
128
|
+
* @param value The Jasone encoded value to decode.
|
|
129
|
+
* @returns The decoded value.
|
|
130
|
+
*/
|
|
131
|
+
decode<T = unknown>(value: JsonValue): T;
|
|
132
|
+
/**
|
|
133
|
+
* Alias for `encode`.
|
|
134
|
+
*/
|
|
135
|
+
serialize(value: unknown): JsonValue;
|
|
136
|
+
/**
|
|
137
|
+
* Alias for `decode`.
|
|
138
|
+
*/
|
|
139
|
+
deserialize<T = unknown>(value: JsonValue): T;
|
|
140
|
+
/**
|
|
141
|
+
* A wrapper around `JSON.stringify` that encodes a value and stringifies it.
|
|
142
|
+
*
|
|
143
|
+
* Under the hood, this functions looks like this:
|
|
144
|
+
*
|
|
145
|
+
* ```ts
|
|
146
|
+
* JSON.stringify(this.encode(value));
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
stringify(value: unknown): string;
|
|
150
|
+
/**
|
|
151
|
+
* A wrapper around `JSON.parse` that parses a Jasone encoded value and decodes it.
|
|
152
|
+
*
|
|
153
|
+
* Under the hood, this functions looks like this:
|
|
154
|
+
*
|
|
155
|
+
* ```ts
|
|
156
|
+
* this.decode(JSON.parse(value));
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
parse<T = unknown>(value: string): T;
|
|
160
|
+
/**
|
|
161
|
+
* The default Jasone instance with the default types already registered.
|
|
162
|
+
*/
|
|
163
|
+
static default: Jasone;
|
|
164
|
+
/**
|
|
165
|
+
* Register a new type to the default Jasone instance.
|
|
166
|
+
*
|
|
167
|
+
* @param type The type to register.
|
|
168
|
+
*/
|
|
169
|
+
/**
|
|
170
|
+
* Encode an arbitrary value to a JSON-compatible Jasone encoded value.
|
|
171
|
+
*
|
|
172
|
+
* @param value The value to encode.
|
|
173
|
+
* @returns A JSON-compatible Jasone encoded value.
|
|
174
|
+
*/
|
|
175
|
+
static encode: (value: unknown) => JsonValue;
|
|
176
|
+
/**
|
|
177
|
+
* Alias for `encode`.
|
|
178
|
+
*/
|
|
179
|
+
static serialize: (value: unknown) => JsonValue;
|
|
180
|
+
/**
|
|
181
|
+
* Decode an Jasone encoded value to its decoded value.
|
|
182
|
+
*
|
|
183
|
+
* @param value The Jasone encoded value to decode.
|
|
184
|
+
* @returns The decoded value.
|
|
185
|
+
*/
|
|
186
|
+
static decode: <T = unknown>(value: JsonValue) => T;
|
|
187
|
+
/**
|
|
188
|
+
* Alias for `decode`.
|
|
189
|
+
*/
|
|
190
|
+
static deserialize: <T = unknown>(value: JsonValue) => T;
|
|
191
|
+
/**
|
|
192
|
+
* A wrapper around `JSON.stringify` that encodes a value and stringifies it.
|
|
193
|
+
*
|
|
194
|
+
* Under the hood, this functions looks like this:
|
|
195
|
+
*
|
|
196
|
+
* ```ts
|
|
197
|
+
* JSON.stringify(Jasone.encode(value));
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
static stringify: (value: unknown) => string;
|
|
201
|
+
/**
|
|
202
|
+
* A wrapper around `JSON.parse` that parses a Jasone encoded value and decodes it.
|
|
203
|
+
*
|
|
204
|
+
* Under the hood, this functions looks like this:
|
|
205
|
+
*
|
|
206
|
+
* ```ts
|
|
207
|
+
* Jasone.decode(JSON.parse(value));
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
static parse: <T = unknown>(value: string) => T;
|
|
211
|
+
/**
|
|
212
|
+
* Register a new type to this Jasone instance.
|
|
213
|
+
*
|
|
214
|
+
* @param type The type to register.
|
|
215
|
+
*/
|
|
216
|
+
static register: <TType, TJson extends JsonValue>(transformer: Transformer<TType, TJson>) => void;
|
|
271
217
|
}
|
|
272
|
-
|
|
273
|
-
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/transformers/bigint.d.ts
|
|
220
|
+
declare const bigIntTransformer: Transformer<bigint, {
|
|
221
|
+
bigint: string;
|
|
222
|
+
}>;
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/transformers/date.d.ts
|
|
225
|
+
declare const dateTransformer: Transformer<Date, {
|
|
226
|
+
iso: string;
|
|
227
|
+
}>;
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/transformers/map.d.ts
|
|
230
|
+
declare const mapTransformer: Transformer<Map<unknown, unknown>, {
|
|
231
|
+
entries: [key: JsonValue, value: JsonValue][];
|
|
232
|
+
}>;
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/transformers/regexp.d.ts
|
|
235
|
+
declare const regExpTransformer: Transformer<RegExp, {
|
|
236
|
+
source: string;
|
|
237
|
+
flags: string;
|
|
238
|
+
}>;
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/transformers/set.d.ts
|
|
241
|
+
declare const setTransformer: Transformer<Set<unknown>, {
|
|
242
|
+
values: JsonValue[];
|
|
243
|
+
}>;
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/transformers/undefined.d.ts
|
|
246
|
+
declare const undefinedTransformer: Transformer<undefined, {}>;
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/transformers/url.d.ts
|
|
249
|
+
declare const urlTransformer: Transformer<URL, {
|
|
250
|
+
url: string;
|
|
251
|
+
}>;
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region src/transformers/index.d.ts
|
|
254
|
+
/**
|
|
255
|
+
* The default type transformers that are used by the default Jasone instance.
|
|
256
|
+
*/
|
|
257
|
+
declare const defaultTransformers: Transformer[];
|
|
258
|
+
//#endregion
|
|
259
|
+
export { ClassLike, DecodeContext, DecodeFilter, DecodeHandler, Decoder, EncodeContext, EncodeFilter, EncodeHandler, EncodeResult, Encoder, Jasone, JasoneOptions, JsonValue, NonJsonType, Transformer, TypeId, type bigIntTransformer, type dateTransformer, defaultTransformers, type mapTransformer, nonJsonTypes, type regExpTransformer, type setTransformer, type undefinedTransformer, type urlTransformer };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var JasoneError=class extends Error{},UnknownTypeIdError=class extends JasoneError{constructor(typeId,value){super(`Unknown type id: ${typeId}`,{cause:value})}},NonJsonValueError=class extends JasoneError{constructor(value){super(`Non-JSON value received`,{cause:value})}},IllegalEncoderResultError=class extends JasoneError{constructor(value){super(`Illegal encoder result received: The encoder result cannot contains the type identifer.`,{cause:value})}},UnhandledValueError=class extends JasoneError{constructor(value){super(`Unhandled value received: No encoder found for this value.`,{cause:value})}},DuplicatedTypeIdError=class extends JasoneError{constructor(typeId,decoder){super(`Duplicated type id: The TypeId<${JSON.stringify(typeId)}> is already registered.`,{cause:decoder})}};let TypeIdRegistry=function(TypeIdRegistry$1){return TypeIdRegistry$1[TypeIdRegistry$1.Undefined=0]=`Undefined`,TypeIdRegistry$1[TypeIdRegistry$1.Date=1]=`Date`,TypeIdRegistry$1[TypeIdRegistry$1.BigInt=2]=`BigInt`,TypeIdRegistry$1[TypeIdRegistry$1.RegExp=3]=`RegExp`,TypeIdRegistry$1[TypeIdRegistry$1.Set=4]=`Set`,TypeIdRegistry$1[TypeIdRegistry$1.Map=5]=`Map`,TypeIdRegistry$1[TypeIdRegistry$1.URL=6]=`URL`,TypeIdRegistry$1}({});const bigIntTransformer={encoder:{filter:{bigint:!0},handler:({value})=>[TypeIdRegistry.BigInt,{bigint:value.toString()}]},decoder:{filter:TypeIdRegistry.BigInt,handler:({value})=>BigInt(value.bigint)}},dateTransformer={encoder:{filter:{class:Date,object:obj=>obj instanceof Date},handler:({value})=>[TypeIdRegistry.Date,{iso:value.toISOString()}]},decoder:{filter:TypeIdRegistry.Date,handler:({value})=>new Date(value.iso)}},mapTransformer={encoder:{filter:{class:Map,object:obj=>obj instanceof Map},handler:({value,jasone})=>[TypeIdRegistry.Map,{entries:value.entries().map(([key,val])=>[jasone.encode(key),jasone.encode(val)]).toArray()}]},decoder:{filter:TypeIdRegistry.Map,handler:({value,jasone})=>new Map(value.entries.map(([key,val])=>[jasone.decode(key),jasone.decode(val)]))}},regExpTransformer={encoder:{filter:{class:RegExp,object:obj=>obj instanceof RegExp},handler:({value})=>[TypeIdRegistry.RegExp,{source:value.source,flags:value.flags}]},decoder:{filter:TypeIdRegistry.RegExp,handler:({value})=>new RegExp(value.source,value.flags)}},setTransformer={encoder:{filter:{class:Set,object:obj=>obj instanceof Set},handler:({value,jasone})=>[TypeIdRegistry.Set,{values:value.values().map(entry=>jasone.encode(entry)).toArray()}]},decoder:{filter:TypeIdRegistry.Set,handler:({value,jasone})=>new Set(value.values.map(entry=>jasone.decode(entry)))}},undefinedTransformer={encoder:{filter:{undefined:!0},handler:()=>[TypeIdRegistry.Undefined,{}]},decoder:{filter:TypeIdRegistry.Undefined,handler:()=>void 0}},urlTransformer={encoder:{filter:{class:URL,object:obj=>obj instanceof URL},handler:({value})=>[TypeIdRegistry.URL,{url:value.toString()}]},decoder:{filter:TypeIdRegistry.URL,handler:({value})=>new URL(value.url)}},defaultTransformers=[undefinedTransformer,dateTransformer,bigIntTransformer,regExpTransformer,setTransformer,mapTransformer,urlTransformer],nonJsonTypes=[`bigint`,`function`,`object`,`symbol`,`undefined`],matchEncoderFilters=(filterInput,value)=>{if(!filterInput)return!0;let filters=Array.isArray(filterInput)?filterInput:[filterInput],type=typeof value;for(let filter of filters){if(filter.any?.(value)||type===`object`&&value!==null&&filter.class===value.constructor)return!0;for(let field of nonJsonTypes){if(type!==field)continue;let typeFilter=filter[field];if(typeFilter===!0||typeFilter?.(value))return!0}}return!1},matchDecoderFilters=(filterInput,value,typeId)=>{if(filterInput===void 0)return!0;let filters=Array.isArray(filterInput)?filterInput:[filterInput];for(let filter of filters)if(typeof filter==`function`&&filter(typeId,value)||filter===typeId)return!0;return!1};var Jasone=class Jasone{#typeIdentifier;#anyDecoder=[];#typeIdDecoder=new Map;#anyEncoder=[];#classEncoder=new Map;#customEncoder={bigint:[],function:[],object:[],symbol:[],undefined:[]};constructor(options={}){this.#typeIdentifier=options.typeIdentifier??`$`;for(let transformer of options.types??[])this.register(transformer)}#registerEncoder(encoder){let filters=encoder.filter?Array.isArray(encoder.filter)?encoder.filter:[encoder.filter]:[];filters.length===0&&this.#anyEncoder.push(encoder);for(let filter of filters){if(filter.any&&this.#anyEncoder.push(encoder),filter.class){let classList=this.#classEncoder.get(filter.class);classList||(classList=[],this.#classEncoder.set(filter.class,classList)),classList.push(encoder)}for(let field of Object.keys(filter))nonJsonTypes.includes(field)&&filter[field]&&this.#customEncoder[field].push(encoder)}}#registerDecoder(decoder){let filters=decoder.filter?Array.isArray(decoder.filter)?decoder.filter:[decoder.filter]:[];filters.length===0&&this.#anyDecoder.push(decoder);for(let filter of filters){if(typeof filter==`function`){this.#anyDecoder.push(decoder);continue}if(this.#typeIdDecoder.has(filter))throw new DuplicatedTypeIdError(filter,decoder);this.#typeIdDecoder.set(filter,decoder)}}register(transformer){transformer.encoder&&this.#registerEncoder(transformer.encoder),transformer.decoder&&this.#registerDecoder(transformer.decoder)}encode(value){let type=typeof value;switch(type){case`boolean`:case`number`:case`string`:return value;case`object`:if(value===null)return null;if(Array.isArray(value))return value.map(entry=>this.encode(entry));if(Object.getPrototypeOf(value)===Object.prototype){let encodedObject=Object.fromEntries(Object.entries(value).map(([key,inner])=>[key,this.encode(inner)]));return this.#typeIdentifier in encodedObject&&(encodedObject[this.#typeIdentifier]=[encodedObject[this.#typeIdentifier]]),encodedObject}}let encoder;if(type===`object`&&(encoder??=this.#classEncoder.get(value.constructor)?.find(inner=>matchEncoderFilters(inner.filter,value))),encoder??=this.#customEncoder[type].find(inner=>matchEncoderFilters(inner.filter,value)),encoder??=this.#anyEncoder.find(inner=>matchEncoderFilters(inner.filter,value)),!encoder)throw new UnhandledValueError(value);let[typeId,result]=encoder.handler({value,jasone:this});if(typeId!==null&&this.#typeIdentifier in result)throw new IllegalEncoderResultError(result);return typeId===null?result:{[this.#typeIdentifier]:typeId,...result}}decode(value){return this.#decode(value)}#decode(value,ignoreTypeIdentifier=!1){switch(typeof value){case`boolean`:case`number`:case`string`:return value;case`object`:if(value===null)return null;if(Array.isArray(value))return value.map(inner=>this.#decode(inner));if(this.#typeIdentifier in value&&!Array.isArray(value)&&!ignoreTypeIdentifier){let typeId=value[this.#typeIdentifier];if(Array.isArray(typeId)){let[escaped]=typeId,cloned={...value};return cloned[this.#typeIdentifier]=escaped,this.#decode(cloned,!0)}let decoder;if(decoder??=this.#typeIdDecoder.get(typeId),decoder??=this.#anyDecoder.find(entry=>matchDecoderFilters(entry.filter,value,typeId)),!decoder)throw new UnknownTypeIdError(typeId,value);return decoder.handler({typeId,value,jasone:this})}if(Object.getPrototypeOf(value)===Object.prototype)return Object.fromEntries(Object.entries(value).map(([key,inner])=>[key,this.#decode(inner)]));break}throw new NonJsonValueError(value)}serialize(value){return this.encode(value)}deserialize(value){return this.decode(value)}stringify(value){return JSON.stringify(this.encode(value))}parse(value){return this.decode(JSON.parse(value))}static default=new Jasone({types:defaultTransformers});static encode=Jasone.default.encode.bind(Jasone.default);static serialize=Jasone.default.serialize.bind(Jasone.default);static decode=Jasone.default.decode.bind(Jasone.default);static deserialize=Jasone.default.deserialize.bind(Jasone.default);static stringify=Jasone.default.stringify.bind(Jasone.default);static parse=Jasone.default.parse.bind(Jasone.default);static register=Jasone.default.register.bind(Jasone.default)};export{Jasone,defaultTransformers,nonJsonTypes};
|
package/package.json
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jasone",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Lukas Heizmann <lukas@heizmann.dev>",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"main": "./index.cjs",
|
|
8
7
|
"module": "./index.js",
|
|
9
8
|
"types": "./index.d.ts",
|
|
10
9
|
"exports": {
|
|
11
10
|
".": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"types": "./index.d.ts"
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"default": "./index.js"
|
|
15
13
|
}
|
|
16
14
|
},
|
|
17
15
|
"repository": {
|
package/index.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";var c=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var w=(t,e)=>{for(var r in e)c(t,r,{get:e[r],enumerable:!0})},J=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of I(e))!b.call(t,o)&&o!==r&&c(t,o,{get:()=>e[o],enumerable:!(n=g(e,o))||n.enumerable});return t};var x=t=>J(c({},"__esModule",{value:!0}),t);var E={};w(E,{Jasone:()=>d,bigIntType:()=>a,createType:()=>s,dateType:()=>y,defaultTypes:()=>l,mapType:()=>T,regExpType:()=>f,setType:()=>m,undefinedType:()=>u,urlType:()=>h});module.exports=x(E);var s=t=>t;var a=s({matches:t=>typeof t=="bigint",typeId:2,encode:t=>({bigint:t.toString()}),decode:({bigint:t})=>BigInt(t)});var y=s({target:Date,typeId:1,encode:t=>({timestamp:t.getTime()}),decode:({timestamp:t})=>new Date(t)});var T=s({target:Map,typeId:5,encode:(t,e)=>({map:Array.from(t.entries().map(([r,n])=>[e(r),e(n)]))}),decode:({map:t},e)=>new Map(t.map(([r,n])=>{if(r===void 0||n===void 0)throw new Error("Illegal value received.",{cause:t});return[e(r),e(n)]}))});var f=s({target:RegExp,typeId:3,encode:t=>({source:t.source,flags:t.flags}),decode:({source:t,flags:e})=>new RegExp(t,e)});var m=s({target:Set,typeId:4,encode:(t,e)=>({set:Array.from(t.values().map(r=>e(r)))}),decode:({set:t},e)=>new Set(t.map(r=>e(r)))});var u=s({matches:t=>t===void 0,typeId:0,encode:()=>({}),decode:()=>{}});var h=s({target:URL,typeId:6,encode:t=>({url:t.toString()}),decode:({url:t})=>new URL(t)});var l=[u,y,a,f,m,T,h];var d=class t{#e;#r=new Map;#n=new Map;#o=[];constructor(e={}){this.#e=e.typeIdentifier??"$";for(let r of e.types??[])this.register(r)}register(e){this.#r.set(e.typeId,e.decode),"matches"in e?this.#o.push({matches:e.matches,typeId:e.typeId,encode:e.encode}):this.#n.set(e.target,{typeId:e.typeId,encode:e.encode})}encode(e){switch(typeof e){case"string":case"number":case"boolean":return e;case"object":if(e===null)return null;if(Array.isArray(e))return e.map(o=>this.encode(o));if(Object.getPrototypeOf(e)===Object.prototype){let o=Object.fromEntries(Object.entries(e).map(([i,p])=>[i,this.encode(p)]));return this.#e in o&&(o[this.#e]=[this.encode(o[this.#e])]),o}}let r;if(typeof e=="object"&&e!==null&&(r=this.#n.get(e.constructor)),r||(r=this.#o.find(({matches:o})=>o(e))),!r)throw new Error("No encoder found.",{cause:e});let n=r.encode(e,this.encode.bind(this));return{[this.#e]:r.typeId,...n}}decode(e){return this.#t(e)}#t(e,r=!1){switch(typeof e){case"string":case"number":case"boolean":return e;case"object":if(e===null)return null;if(Array.isArray(e))return e.map(n=>this.#t(n));if(this.#e in e&&!Array.isArray(e)&&!r){let n=e[this.#e];if(Array.isArray(n)){if(n.length!==1)throw new Error("Illegal value received. Escaped type identifiers must have exactly one element.",{cause:e});let[i]=n,p={...e};return p[this.#e]=i,this.#t(p,!0)}let o=this.#r.get(n);if(!o)throw new Error(`No decoder found for type id: ${n}`,{cause:e});return o(e,this.decode.bind(this))}if(Object.getPrototypeOf(e)===Object.prototype)return Object.fromEntries(Object.entries(e).map(([n,o])=>[n,this.#t(o)]));break}throw new Error("Illegal value received.",{cause:e})}serialize(e){return this.encode(e)}deserialize(e){return this.decode(e)}stringify(e){return JSON.stringify(this.encode(e))}parse(e){return this.decode(JSON.parse(e))}static default=new t({types:l});static register=t.default.register.bind(t.default);static encode=t.default.encode.bind(t.default);static serialize=t.default.serialize.bind(t.default);static decode=t.default.decode.bind(t.default);static deserialize=t.default.deserialize.bind(t.default);static stringify=t.default.stringify.bind(t.default);static parse=t.default.parse.bind(t.default)};0&&(module.exports={Jasone,bigIntType,createType,dateType,defaultTypes,mapType,regExpType,setType,undefinedType,urlType});
|
package/index.d.cts
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A JSON-compatible value.
|
|
3
|
-
*/
|
|
4
|
-
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
5
|
-
[key: string]: JsonValue;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* The id of an encoded type to identify it on decoding.
|
|
9
|
-
*/
|
|
10
|
-
type TypeId = string | number;
|
|
11
|
-
/**
|
|
12
|
-
* A function that is responsible to encode a type into a JSON-compatible value.
|
|
13
|
-
*
|
|
14
|
-
* @param value The value to encode.
|
|
15
|
-
* @param encode A function that works exactly the same as `Jasone.encode` useful
|
|
16
|
-
* to encode values recursively. This function comes from the instance
|
|
17
|
-
* where the type transformer is registered, so it has the same types.
|
|
18
|
-
* @returns A JSON-compatible value.
|
|
19
|
-
*/
|
|
20
|
-
type TypeEncoder<TType = unknown, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = (value: TType, encode: <T = unknown>(value: T) => JsonValue) => TJson;
|
|
21
|
-
/**
|
|
22
|
-
* A function that is responsible to decode a type back to its decoded value.
|
|
23
|
-
*
|
|
24
|
-
* @param value The value to decode.
|
|
25
|
-
* @param encode A function that works exactly the same as `Jasone.decode` useful
|
|
26
|
-
* to decode values recursively. This function comes from the instance
|
|
27
|
-
* where the type transformer is registered, so it has the same types.
|
|
28
|
-
* @returns A JSON-compatible value.
|
|
29
|
-
*/
|
|
30
|
-
type TypeDecoder<TType = unknown, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = (value: TJson, decode: <T = unknown>(value: JsonValue) => T) => TType;
|
|
31
|
-
type MatchesFn<TType = unknown> = (value: unknown) => value is TType;
|
|
32
|
-
type ClassLike<TInstance> = new <T>(...args: any[]) => TInstance;
|
|
33
|
-
declare const typeOf: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
|
|
34
|
-
type TypeOf = typeof typeOf;
|
|
35
|
-
|
|
36
|
-
type TypeMatcher<TType> = {
|
|
37
|
-
/**
|
|
38
|
-
* The function that is responsible to determine if a value can be
|
|
39
|
-
* encoded with this transformer.
|
|
40
|
-
*/
|
|
41
|
-
matches: MatchesFn<TType>;
|
|
42
|
-
} | {
|
|
43
|
-
/**
|
|
44
|
-
* The class that can be encoded with this transformer.
|
|
45
|
-
*
|
|
46
|
-
* Using the `target` property only works on classes with an
|
|
47
|
-
* `constructor`. Internally, Jasone matches the constructor of the
|
|
48
|
-
* class with the `target` property.
|
|
49
|
-
*/
|
|
50
|
-
target: ClassLike<TType>;
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* A type transformer which is responsible for encoding and decoding a type.
|
|
54
|
-
*/
|
|
55
|
-
type TypeTransformer<TType, TJson extends Record<string, JsonValue> = Record<string, JsonValue>> = TypeMatcher<TType> & {
|
|
56
|
-
/**
|
|
57
|
-
* The id of the type that is used to identify the type on decoding.
|
|
58
|
-
*
|
|
59
|
-
* This id should be unique for each type and it is recommended to use strings
|
|
60
|
-
* to avoid conflicts with built-in types (which used positive integers).
|
|
61
|
-
*/
|
|
62
|
-
typeId: string | number;
|
|
63
|
-
/**
|
|
64
|
-
* The function that is responsible to encode the type into a JSON-compatible
|
|
65
|
-
* value.
|
|
66
|
-
*/
|
|
67
|
-
encode: TypeEncoder<TType, TJson>;
|
|
68
|
-
/**
|
|
69
|
-
* The function that is responsible to decode the type from a JSON-compatible
|
|
70
|
-
* value.
|
|
71
|
-
*/
|
|
72
|
-
decode: TypeDecoder<TType, TJson>;
|
|
73
|
-
};
|
|
74
|
-
/**
|
|
75
|
-
* A convenience function to create a type transformer which automatically
|
|
76
|
-
* infer the types for you, so you don't have to.
|
|
77
|
-
*
|
|
78
|
-
* @param transformer The transformer to create.
|
|
79
|
-
* @returns The exact same transformer you passed in, but with the types inferred.
|
|
80
|
-
*/
|
|
81
|
-
declare const createType: <TType, TJson extends Record<string, JsonValue>>(transformer: TypeTransformer<TType, TJson>) => TypeTransformer<TType, TJson>;
|
|
82
|
-
|
|
83
|
-
declare const bigIntType: TypeTransformer<bigint, {
|
|
84
|
-
bigint: string;
|
|
85
|
-
}>;
|
|
86
|
-
|
|
87
|
-
declare const dateType: TypeTransformer<Date, {
|
|
88
|
-
timestamp: number;
|
|
89
|
-
}>;
|
|
90
|
-
|
|
91
|
-
declare const mapType: TypeTransformer<Map<unknown, unknown>, {
|
|
92
|
-
map: JsonValue[][];
|
|
93
|
-
}>;
|
|
94
|
-
|
|
95
|
-
declare const regExpType: TypeTransformer<RegExp, {
|
|
96
|
-
source: string;
|
|
97
|
-
flags: string;
|
|
98
|
-
}>;
|
|
99
|
-
|
|
100
|
-
declare const setType: TypeTransformer<Set<unknown>, {
|
|
101
|
-
set: JsonValue[];
|
|
102
|
-
}>;
|
|
103
|
-
|
|
104
|
-
declare const undefinedType: TypeTransformer<undefined, {}>;
|
|
105
|
-
|
|
106
|
-
declare const urlType: TypeTransformer<URL, {
|
|
107
|
-
url: string;
|
|
108
|
-
}>;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* The default types that are used by the default Jasone instance.
|
|
112
|
-
*/
|
|
113
|
-
declare const defaultTypes: TypeTransformer<any, any>[];
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Jasone options that can be passed to the Jasone constructor.
|
|
117
|
-
*/
|
|
118
|
-
type JasoneOptions = {
|
|
119
|
-
/**
|
|
120
|
-
* The type identifier that is used to determine if an object is a typed object.
|
|
121
|
-
*
|
|
122
|
-
* @default "$"
|
|
123
|
-
*/
|
|
124
|
-
typeIdentifier?: string;
|
|
125
|
-
/**
|
|
126
|
-
* The types that are used to encode and decode objects.
|
|
127
|
-
*
|
|
128
|
-
* If not provided, the default types are used. By providing your own types,
|
|
129
|
-
* the default types are not used anymore, so be sure to also include them.
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* ```ts
|
|
133
|
-
* // your custom type WITH default types
|
|
134
|
-
* const jasone = new Jasone({ types: [myCustomType, ...defaultTypes] });
|
|
135
|
-
*
|
|
136
|
-
* // your custom type WITHOUT default types
|
|
137
|
-
* const jasone = new Jasone({ types: [myCustomType] });
|
|
138
|
-
* ```
|
|
139
|
-
*/
|
|
140
|
-
types?: TypeTransformer<any, any>[];
|
|
141
|
-
};
|
|
142
|
-
/**
|
|
143
|
-
* Jasone is a JSON encoder and decoder that can handle custom types.
|
|
144
|
-
*
|
|
145
|
-
* It exposes the default Jasone instance as `Jasone.default` and also
|
|
146
|
-
* registers the methods as static methods on the class itself, so you
|
|
147
|
-
* can easily use them without having to create an instance.
|
|
148
|
-
*
|
|
149
|
-
* ```ts
|
|
150
|
-
* const encoded = Jasone.encode(value);
|
|
151
|
-
* const decoded = Jasone.decode(value);
|
|
152
|
-
* ```
|
|
153
|
-
*
|
|
154
|
-
* If you want to use your own types, you can either register them on any
|
|
155
|
-
* instance (even on `Jasone.default`) or instantiate your own Jasone instance.
|
|
156
|
-
*
|
|
157
|
-
* ```ts
|
|
158
|
-
* // use our own types without the default types (Date, BigInt, Map, etc.)
|
|
159
|
-
* const myInstance = new Jasone({ types: [myCustomType] });
|
|
160
|
-
*
|
|
161
|
-
* // or use our own types with the default types (recommend)
|
|
162
|
-
* const myInstance = new Jasone({ types: [myCustomType, ...defaultTypes] });
|
|
163
|
-
*
|
|
164
|
-
* const encoded = myInstance.encode(value);
|
|
165
|
-
* const decoded = myInstance.decode(value);
|
|
166
|
-
* ```
|
|
167
|
-
*/
|
|
168
|
-
declare class Jasone {
|
|
169
|
-
#private;
|
|
170
|
-
constructor(options?: JasoneOptions);
|
|
171
|
-
/**
|
|
172
|
-
* Register a new type to this Jasone instance.
|
|
173
|
-
*
|
|
174
|
-
* @param type The type to register.
|
|
175
|
-
*/
|
|
176
|
-
register<TType, TJson extends Record<string, JsonValue>>(type: TypeTransformer<TType, TJson>): void;
|
|
177
|
-
/**
|
|
178
|
-
* Encode an arbitrary value to a JSON-compatible Jasone encoded value.
|
|
179
|
-
*
|
|
180
|
-
* @param value The value to encode.
|
|
181
|
-
* @returns A JSON-compatible Jasone encoded value.
|
|
182
|
-
*/
|
|
183
|
-
encode(value: unknown): JsonValue;
|
|
184
|
-
/**
|
|
185
|
-
* Decode an Jasone encoded value to its decoded value.
|
|
186
|
-
*
|
|
187
|
-
* @param value The Jasone encoded value to decode.
|
|
188
|
-
* @returns The decoded value.
|
|
189
|
-
*/
|
|
190
|
-
decode<T = unknown>(value: JsonValue): T;
|
|
191
|
-
/**
|
|
192
|
-
* Alias for `encode`.
|
|
193
|
-
*/
|
|
194
|
-
serialize(value: unknown): JsonValue;
|
|
195
|
-
/**
|
|
196
|
-
* Alias for `decode`.
|
|
197
|
-
*/
|
|
198
|
-
deserialize<T = unknown>(value: JsonValue): T;
|
|
199
|
-
/**
|
|
200
|
-
* A wrapper around `JSON.stringify` that encodes a value and stringifies it.
|
|
201
|
-
*
|
|
202
|
-
* Under the hood, this functions looks like this:
|
|
203
|
-
*
|
|
204
|
-
* ```ts
|
|
205
|
-
* JSON.stringify(this.encode(value));
|
|
206
|
-
* ```
|
|
207
|
-
*/
|
|
208
|
-
stringify(value: unknown): string;
|
|
209
|
-
/**
|
|
210
|
-
* A wrapper around `JSON.parse` that parses a Jasone encoded value and decodes it.
|
|
211
|
-
*
|
|
212
|
-
* Under the hood, this functions looks like this:
|
|
213
|
-
*
|
|
214
|
-
* ```ts
|
|
215
|
-
* this.decode(JSON.parse(value));
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
parse<T = unknown>(value: string): T;
|
|
219
|
-
/**
|
|
220
|
-
* The default Jasone instance with the default types already registered.
|
|
221
|
-
*/
|
|
222
|
-
static default: Jasone;
|
|
223
|
-
/**
|
|
224
|
-
* Register a new type to the default Jasone instance.
|
|
225
|
-
*
|
|
226
|
-
* @param type The type to register.
|
|
227
|
-
*/
|
|
228
|
-
static register: <TType, TJson extends Record<string, JsonValue>>(type: TypeTransformer<TType, TJson>) => void;
|
|
229
|
-
/**
|
|
230
|
-
* Encode an arbitrary value to a JSON-compatible Jasone encoded value.
|
|
231
|
-
*
|
|
232
|
-
* @param value The value to encode.
|
|
233
|
-
* @returns A JSON-compatible Jasone encoded value.
|
|
234
|
-
*/
|
|
235
|
-
static encode: (value: unknown) => JsonValue;
|
|
236
|
-
/**
|
|
237
|
-
* Alias for `encode`.
|
|
238
|
-
*/
|
|
239
|
-
static serialize: (value: unknown) => JsonValue;
|
|
240
|
-
/**
|
|
241
|
-
* Decode an Jasone encoded value to its decoded value.
|
|
242
|
-
*
|
|
243
|
-
* @param value The Jasone encoded value to decode.
|
|
244
|
-
* @returns The decoded value.
|
|
245
|
-
*/
|
|
246
|
-
static decode: <T = unknown>(value: JsonValue) => T;
|
|
247
|
-
/**
|
|
248
|
-
* Alias for `decode`.
|
|
249
|
-
*/
|
|
250
|
-
static deserialize: <T = unknown>(value: JsonValue) => T;
|
|
251
|
-
/**
|
|
252
|
-
* A wrapper around `JSON.stringify` that encodes a value and stringifies it.
|
|
253
|
-
*
|
|
254
|
-
* Under the hood, this functions looks like this:
|
|
255
|
-
*
|
|
256
|
-
* ```ts
|
|
257
|
-
* JSON.stringify(Jasone.encode(value));
|
|
258
|
-
* ```
|
|
259
|
-
*/
|
|
260
|
-
static stringify: (value: unknown) => string;
|
|
261
|
-
/**
|
|
262
|
-
* A wrapper around `JSON.parse` that parses a Jasone encoded value and decodes it.
|
|
263
|
-
*
|
|
264
|
-
* Under the hood, this functions looks like this:
|
|
265
|
-
*
|
|
266
|
-
* ```ts
|
|
267
|
-
* Jasone.decode(JSON.parse(value));
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
static parse: <T = unknown>(value: string) => T;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export { type ClassLike, Jasone, type JasoneOptions, type JsonValue, type MatchesFn, type TypeDecoder, type TypeEncoder, type TypeId, type TypeMatcher, type TypeOf, type TypeTransformer, bigIntType, createType, dateType, defaultTypes, mapType, regExpType, setType, undefinedType, urlType };
|