@kaiko.io/rescript-deser 6.0.1 → 7.0.0-alpha.2

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 (56) hide show
  1. package/README.md +16 -5
  2. package/lib/bs/.compiler.log +2 -2
  3. package/lib/bs/build.ninja +0 -27
  4. package/lib/bs/compiler-info.json +8 -0
  5. package/lib/bs/src/Deser.ast +0 -0
  6. package/lib/bs/src/Deser.cmi +0 -0
  7. package/lib/bs/src/Deser.cmj +0 -0
  8. package/lib/bs/src/Deser.cmt +0 -0
  9. package/lib/bs/src/Deser.res +341 -0
  10. package/lib/bs/tests/QUnit.ast +0 -0
  11. package/lib/bs/tests/QUnit.cmi +0 -0
  12. package/lib/bs/tests/QUnit.cmj +0 -0
  13. package/lib/bs/tests/QUnit.cmt +0 -0
  14. package/lib/bs/tests/QUnit.res +72 -0
  15. package/lib/bs/tests/index.ast +0 -0
  16. package/lib/bs/tests/index.cmi +0 -0
  17. package/lib/bs/tests/index.cmj +0 -0
  18. package/lib/bs/tests/index.cmt +0 -0
  19. package/lib/bs/tests/index.res +212 -0
  20. package/lib/es6/src/Deser.js +302 -477
  21. package/lib/es6/tests/index.js +260 -241
  22. package/lib/js/src/Deser.js +298 -473
  23. package/lib/js/tests/index.js +261 -242
  24. package/lib/ocaml/.compiler.log +2 -0
  25. package/lib/ocaml/Deser.ast +0 -0
  26. package/lib/ocaml/Deser.cmi +0 -0
  27. package/lib/ocaml/Deser.cmj +0 -0
  28. package/lib/ocaml/Deser.cmt +0 -0
  29. package/lib/ocaml/Deser.res +341 -0
  30. package/lib/ocaml/QUnit.ast +0 -0
  31. package/lib/ocaml/QUnit.cmi +0 -0
  32. package/lib/ocaml/QUnit.cmj +0 -0
  33. package/lib/ocaml/QUnit.cmt +0 -0
  34. package/lib/ocaml/QUnit.res +72 -0
  35. package/lib/ocaml/index.ast +0 -0
  36. package/lib/ocaml/index.cmi +0 -0
  37. package/lib/ocaml/index.cmj +0 -0
  38. package/lib/ocaml/index.cmt +0 -0
  39. package/lib/ocaml/index.res +212 -0
  40. package/lib/rescript.lock +1 -0
  41. package/package.json +5 -6
  42. package/rescript.json +4 -6
  43. package/src/Deser.res +86 -97
  44. package/tests/QUnit.res +4 -4
  45. package/tests/index.res +34 -11
  46. package/tests/run-tests.js +192 -0
  47. package/yarn.lock +683 -0
  48. package/lib/bs/.bsbuild +0 -0
  49. package/lib/bs/.bsdeps +0 -9
  50. package/lib/bs/.ninja_log +0 -93
  51. package/lib/bs/.project-files-cache +0 -0
  52. package/lib/bs/.sourcedirs.json +0 -1
  53. package/lib/bs/install.ninja +0 -10
  54. package/lib/bs/src/Deser.d +0 -0
  55. package/lib/bs/tests/QUnit.d +0 -0
  56. package/lib/bs/tests/index.d +0 -1
@@ -0,0 +1,212 @@
1
+ open QUnit
2
+
3
+ module Appointment = {
4
+ type t = {
5
+ note: string,
6
+ date: Date.t,
7
+ extra: option<string>,
8
+ }
9
+ module Deserializer = Deser.MakeDeserializer({
10
+ type t = t
11
+ open Deser.Field
12
+
13
+ let fields = Object([("note", String), ("date", Date), ("extra", Optional(String))])
14
+ })
15
+ }
16
+
17
+ module_("Basic deserializer", _ => {
18
+ let valid: array<(_, Appointment.t)> = [
19
+ (
20
+ %raw(`{"note": "Bicentennial doctor's appointment", "date": "2100-01-01"}`),
21
+ {
22
+ note: "Bicentennial doctor's appointment",
23
+ date: Date.fromString("2100-01-01"),
24
+ extra: None,
25
+ },
26
+ ),
27
+ (
28
+ %raw(`{
29
+ "note": "Bicentennial doctor's appointment",
30
+ "date": "2100-01-01",
31
+ "extra": "Don't take your stop-aging pills the night before the appointment",
32
+ }`),
33
+ {
34
+ note: "Bicentennial doctor's appointment",
35
+ date: Date.fromString("2100-01-01"),
36
+ extra: Some("Don't take your stop-aging pills the night before the appointment"),
37
+ },
38
+ ),
39
+ ]
40
+
41
+ test("Correctly deserializes data", qunit => {
42
+ qunit->expect(valid->Array.length)
43
+ valid->Array.forEach(
44
+ ((data, expected)) => {
45
+ Console.log2("Running sample", data)
46
+ switch Appointment.Deserializer.fromJSON(data) {
47
+ | Ok(result) => qunit->deepEqual(result, expected, "result == expected")
48
+ | Error(msg) => Console.error(msg)
49
+ }
50
+ },
51
+ )
52
+ })
53
+
54
+ let invalid = [
55
+ (
56
+ "Missing non-optional field",
57
+ %raw(`{"extra": "Bicentennial doctor's appointment", "date": "2100-01-01"}`),
58
+ ),
59
+ ]
60
+
61
+ test("Correctly catches invalid data", qunit => {
62
+ qunit->expect(invalid->Array.length)
63
+ invalid->Array.forEach(
64
+ ((message, data)) => {
65
+ Console.log3("Running sample", message, data)
66
+ switch Appointment.Deserializer.fromJSON(data) {
67
+ | Ok(result) => Console.error2("Invalid being accepted: ", result)
68
+ | Error(msg) => {
69
+ Console.log2("Correctly detected:", msg)
70
+ qunit->ok(true, true)
71
+ }
72
+ }
73
+ },
74
+ )
75
+ })
76
+ })
77
+
78
+ module_("Recursive deserializer", _ => {
79
+ module TrivialTree = {
80
+ type rec t<'a> = {
81
+ data: 'a,
82
+ children: array<t<'a>>,
83
+ }
84
+
85
+ module DeserializerImpl = Deser.MakeDeserializer({
86
+ type payload
87
+ type rec t = {
88
+ data: payload,
89
+ children: array<t>,
90
+ }
91
+ open Deser.Field
92
+
93
+ let fields = Object([("data", Any), ("children", Array(Self))])
94
+ })
95
+
96
+ module Deserializer = {
97
+ include DeserializerImpl
98
+
99
+ let fromJSON = data => data->DeserializerImpl.fromJSON->Result.map(x => x->Obj.magic)
100
+ }
101
+ }
102
+
103
+ let valid: array<(_, TrivialTree.t<string>)> = [
104
+ (
105
+ %raw(`{"data": "A", "children": [{"data": "A1", "children": []}, {"data": "B", "children": [{"data": "C", "children": []}, {"data": "D", "children": []}]}]}`),
106
+ {
107
+ data: "A",
108
+ children: [
109
+ {data: "A1", children: []},
110
+ {data: "B", children: [{data: "C", children: []}, {data: "D", children: []}]},
111
+ ],
112
+ },
113
+ ),
114
+ ]
115
+
116
+ test("Trivial recursion detection: Ok", qunit => {
117
+ qunit->expect(1)
118
+ qunit->deepEqual(TrivialTree.Deserializer.checkFieldsSanity(), Ok(), "Ok")
119
+ })
120
+
121
+ test("Infinite list", qunit => {
122
+ module InfiniteList = Deser.MakeDeserializer({
123
+ open Deser.Field
124
+
125
+ type t
126
+ let fields = Object([("head", String), ("tail", Self)])
127
+ })
128
+
129
+ qunit->expect(1)
130
+ qunit->deepEqual(InfiniteList.checkFieldsSanity()->Result.isError, true, "Ok")
131
+ })
132
+
133
+ test("Finite list", qunit => {
134
+ module List = Deser.MakeDeserializer({
135
+ open Deser.Field
136
+
137
+ type t
138
+ let fields = Object([("head", String), ("tail", Optional(Self))])
139
+ })
140
+
141
+ qunit->expect(1)
142
+ qunit->deepEqual(List.checkFieldsSanity(), Ok(), "Ok")
143
+ })
144
+
145
+ test("Correctly deserializes recursive data", qunit => {
146
+ qunit->expect(valid->Array.length)
147
+ valid->Array.forEach(
148
+ ((data, expected)) => {
149
+ Console.log2("Running sample", data)
150
+ switch TrivialTree.Deserializer.fromJSON(data) {
151
+ | Ok(result) => qunit->deepEqual(result, expected, "result == expected")
152
+ | Error(msg) => Console.error(msg)
153
+ }
154
+ },
155
+ )
156
+ })
157
+
158
+ test("Recursion in sub-deserializer", qunit => {
159
+ module List = Deser.MakeDeserializer({
160
+ open Deser.Field
161
+
162
+ type t
163
+ let fields = Object([("head", String), ("tail", Optional(Self))])
164
+ })
165
+
166
+ module Ledger = Deser.MakeDeserializer({
167
+ open Deser.Field
168
+
169
+ type t
170
+ let fields = Object([("records", Deserializer(module(List))), ("next", Optional(Self))])
171
+ })
172
+
173
+ let data = %raw(`
174
+ {"records": {"head": "A", "tail": {"head": "B"}},
175
+ "next": {"records": {"head": "A", "tail": {"head": "B"}}}}
176
+ `)
177
+ let expected = {
178
+ "records": {"head": "A", "tail": {"head": "B", "tail": None}},
179
+ "next": {
180
+ "records": {"head": "A", "tail": {"head": "B", "tail": None}},
181
+ "next": None,
182
+ },
183
+ }
184
+
185
+ qunit->expect(1)
186
+ qunit->deepEqual(data->Ledger.fromJSON->Obj.magic, Ok(expected), "nice ledger")
187
+ })
188
+ })
189
+
190
+ module_("Type safety limits", _ => {
191
+ test("ill-defined deserializer can cheat the type system", qunit => {
192
+ module X = Deser.MakeDeserializer({
193
+ type t = string
194
+ let fields = Deser.Field.Array(Int)
195
+ })
196
+
197
+ let data = %raw("[1]")
198
+ qunit->throws(
199
+ _ => {
200
+ let illString = data->X.fromJSON->Result.getOr("")
201
+ try {
202
+ Console.info3(__MODULE__, "This will fail with a type error", illString->String.charAt(0))
203
+ } catch {
204
+ | e =>
205
+ Console.error(e)
206
+ throw(e)
207
+ }
208
+ },
209
+ "Expected: TypeError: illString.charAt is not a function",
210
+ )
211
+ })
212
+ })