@greenlabs/ppx-spice 0.1.7 → 0.1.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ # 0.1.8
4
+
5
+ - Fix type error where using tuple constructor type, such as `array<int>` for optional field in the record. https://github.com/green-labs/ppx_spice/pull/32
6
+
3
7
  # 0.1.7
4
8
 
5
9
  #### :rocket: New Feature
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greenlabs/ppx-spice",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "ReScript PPX which generate JSON (de)serializer",
5
5
  "license": "MIT",
6
6
  "author": "Greenlabs Dev <developer@greenlabs.co.kr>",
package/ppx-linux.exe CHANGED
Binary file
package/ppx-osx.exe CHANGED
Binary file
package/ppx-windows.exe CHANGED
Binary file
package/src/ppx/codecs.ml CHANGED
@@ -75,8 +75,7 @@ and generate_constr_codecs { do_encode; do_decode }
75
75
  )
76
76
  | Lapply (_, _) -> fail loc "Lapply syntax not yet handled by spice"
77
77
 
78
- and generate_codecs ?(is_optional = false)
79
- ({ do_encode; do_decode } as generator_settings)
78
+ and generate_codecs ({ do_encode; do_decode } as generator_settings)
80
79
  { ptyp_desc; ptyp_loc; ptyp_attributes } =
81
80
  match ptyp_desc with
82
81
  | Ptyp_any -> fail ptyp_loc "Can't generate codecs for `any` type"
@@ -85,7 +84,7 @@ and generate_codecs ?(is_optional = false)
85
84
  | Ptyp_package _ -> fail ptyp_loc "Can't generate codecs for module type"
86
85
  | Ptyp_tuple types ->
87
86
  let composite_codecs =
88
- List.map (generate_codecs ~is_optional generator_settings) types
87
+ List.map (generate_codecs generator_settings) types
89
88
  in
90
89
  ( some_if_true do_encode
91
90
  (composite_codecs
@@ -115,15 +114,6 @@ and generate_codecs ?(is_optional = false)
115
114
  d] )
116
115
  | Error s -> fail ptyp_loc s
117
116
  in
118
- let encode, decode =
119
- if is_optional then
120
- match (encode, decode) with
121
- | Some encode, Some decode ->
122
- ( Some [%expr Spice.optionToJson [%e encode]],
123
- Some [%expr Spice.optionFromJson [%e decode]] )
124
- | _ -> (encode, decode)
125
- else (encode, decode)
126
- in
127
117
  match List.length typeArgs = 0 with
128
118
  | true -> (encode, decode)
129
119
  | false -> parameterize_codecs typeArgs encode decode generator_settings)
@@ -136,12 +136,22 @@ let parse_decl generator_settings
136
136
  |> List.map (fun attr -> get_attribute_by_name pld_attributes attr)
137
137
  |> List.exists (function Ok (Some _) -> true | _ -> false)
138
138
  in
139
+ let codecs = Codecs.generate_codecs generator_settings pld_type in
140
+ let codecs =
141
+ if is_optional then
142
+ match codecs with
143
+ | Some encode, Some decode ->
144
+ ( Some [%expr Spice.optionToJson [%e encode]],
145
+ Some [%expr Spice.optionFromJson [%e decode]] )
146
+ | _ -> codecs
147
+ else codecs
148
+ in
139
149
 
140
150
  {
141
151
  name = txt;
142
152
  key;
143
153
  field = Exp.field [%expr v] (lid txt);
144
- codecs = Codecs.generate_codecs ~is_optional generator_settings pld_type;
154
+ codecs;
145
155
  default;
146
156
  is_optional;
147
157
  }
@@ -1,6 +1,6 @@
1
1
  opam-version: "2.0"
2
2
  name: "ppx_spice"
3
- version: "0.1.7"
3
+ version: "0.1.8"
4
4
  synopsis: "ReScript PPX which generate JSON (de)serializer"
5
5
  description: """
6
6
  ReScript PPX which generate JSON (de)serializer
@@ -0,0 +1,91 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ 'use strict';
3
+
4
+ var Jest = require("@glennsl/bs-jest/src/jest.js");
5
+ var OptionalFieldRecords = require("../src/OptionalFieldRecords.js");
6
+
7
+ Jest.describe("optional field record", (function (param) {
8
+ var sample = {};
9
+ sample["a"] = 1;
10
+ sample["b"] = 1;
11
+ var sampleRecord = {
12
+ a: 1,
13
+ b: 1
14
+ };
15
+ Jest.test("encode", (function (param) {
16
+ var encoded = OptionalFieldRecords.t0_encode(sampleRecord);
17
+ return Jest.Expect.toEqual(sample, Jest.Expect.expect(encoded));
18
+ }));
19
+ Jest.test("decode", (function (param) {
20
+ var decoded = OptionalFieldRecords.t0_decode(sample);
21
+ return Jest.Expect.toEqual({
22
+ TAG: /* Ok */0,
23
+ _0: sampleRecord
24
+ }, Jest.Expect.expect(decoded));
25
+ }));
26
+ }));
27
+
28
+ Jest.describe("optional field record: array<int>", (function (param) {
29
+ var sample = {};
30
+ sample["a"] = 1;
31
+ sample["bs"] = [1];
32
+ var sampleRecord_bs = [1];
33
+ var sampleRecord = {
34
+ a: 1,
35
+ bs: sampleRecord_bs
36
+ };
37
+ Jest.test("encode", (function (param) {
38
+ var encoded = OptionalFieldRecords.t1_encode(sampleRecord);
39
+ return Jest.Expect.toEqual(sample, Jest.Expect.expect(encoded));
40
+ }));
41
+ Jest.test("decode", (function (param) {
42
+ var decoded = OptionalFieldRecords.t1_decode(sample);
43
+ return Jest.Expect.toEqual({
44
+ TAG: /* Ok */0,
45
+ _0: sampleRecord
46
+ }, Jest.Expect.expect(decoded));
47
+ }));
48
+ }));
49
+
50
+ Jest.describe("optional field record: array<variant>", (function (param) {
51
+ var sample = {};
52
+ sample["a"] = 1;
53
+ sample["bs"] = ["B1"];
54
+ var sampleRecord_bs = [/* B1 */1];
55
+ var sampleRecord = {
56
+ a: 1,
57
+ bs: sampleRecord_bs
58
+ };
59
+ Jest.test("encode", (function (param) {
60
+ var encoded = OptionalFieldRecords.t2_encode(sampleRecord);
61
+ return Jest.Expect.toEqual(sample, Jest.Expect.expect(encoded));
62
+ }));
63
+ Jest.test("decode", (function (param) {
64
+ var decoded = OptionalFieldRecords.t2_decode(sample);
65
+ return Jest.Expect.toEqual({
66
+ TAG: /* Ok */0,
67
+ _0: sampleRecord
68
+ }, Jest.Expect.expect(decoded));
69
+ }));
70
+ }));
71
+
72
+ Jest.describe("optional field record: omit array<variant>", (function (param) {
73
+ var sample = {};
74
+ sample["a"] = 1;
75
+ var sampleRecord = {
76
+ a: 1
77
+ };
78
+ Jest.test("encode", (function (param) {
79
+ var encoded = OptionalFieldRecords.t2_encode(sampleRecord);
80
+ return Jest.Expect.toEqual(sample, Jest.Expect.expect(encoded));
81
+ }));
82
+ Jest.test("decode", (function (param) {
83
+ var decoded = OptionalFieldRecords.t2_decode(sample);
84
+ return Jest.Expect.toEqual({
85
+ TAG: /* Ok */0,
86
+ _0: sampleRecord
87
+ }, Jest.Expect.expect(decoded));
88
+ }));
89
+ }));
90
+
91
+ /* Not a pure module */
@@ -0,0 +1,98 @@
1
+ open Jest
2
+ open Expect
3
+ // open Belt
4
+
5
+ describe("optional field record", _ => {
6
+ open OptionalFieldRecords
7
+
8
+ let sample = Js.Dict.empty()
9
+ sample->Js.Dict.set("a", Js.Json.number(1.))
10
+ sample->Js.Dict.set("b", Js.Json.number(1.))
11
+ let sampleJson = sample->Js.Json.object_
12
+
13
+ let sampleRecord: t0 = {
14
+ a: 1,
15
+ b: 1,
16
+ }
17
+
18
+ test(`encode`, _ => {
19
+ let encoded = sampleRecord->t0_encode
20
+ expect(encoded) |> toEqual(sampleJson)
21
+ })
22
+
23
+ test(`decode`, _ => {
24
+ let decoded = sampleJson->t0_decode
25
+ expect(decoded) |> toEqual(Belt.Result.Ok(sampleRecord))
26
+ })
27
+ })
28
+
29
+ describe("optional field record: array<int>", _ => {
30
+ open OptionalFieldRecords
31
+
32
+ let sample = Js.Dict.empty()
33
+ sample->Js.Dict.set("a", Js.Json.number(1.))
34
+ sample->Js.Dict.set("bs", Js.Json.array([Js.Json.number(1.)]))
35
+ let sampleJson = sample->Js.Json.object_
36
+
37
+ let sampleRecord: t1 = {
38
+ a: 1,
39
+ bs: [1],
40
+ }
41
+
42
+ test(`encode`, _ => {
43
+ let encoded = sampleRecord->t1_encode
44
+ expect(encoded) |> toEqual(sampleJson)
45
+ })
46
+
47
+ test(`decode`, _ => {
48
+ let decoded = sampleJson->t1_decode
49
+ expect(decoded) |> toEqual(Belt.Result.Ok(sampleRecord))
50
+ })
51
+ })
52
+
53
+ describe("optional field record: array<variant>", _ => {
54
+ open OptionalFieldRecords
55
+
56
+ let sample = Js.Dict.empty()
57
+ sample->Js.Dict.set("a", Js.Json.number(1.))
58
+ sample->Js.Dict.set("bs", Js.Json.array([Js.Json.string("B1")]))
59
+ let sampleJson = sample->Js.Json.object_
60
+
61
+ let sampleRecord: t2 = {
62
+ a: 1,
63
+ bs: [B1],
64
+ }
65
+
66
+ test(`encode`, _ => {
67
+ let encoded = sampleRecord->t2_encode
68
+ expect(encoded) |> toEqual(sampleJson)
69
+ })
70
+
71
+ test(`decode`, _ => {
72
+ let decoded = sampleJson->t2_decode
73
+ expect(decoded) |> toEqual(Belt.Result.Ok(sampleRecord))
74
+ })
75
+ })
76
+
77
+ describe("optional field record: omit array<variant>", _ => {
78
+ open OptionalFieldRecords
79
+
80
+ let sample = Js.Dict.empty()
81
+ sample->Js.Dict.set("a", Js.Json.number(1.))
82
+
83
+ let sampleJson = sample->Js.Json.object_
84
+
85
+ let sampleRecord: t2 = {
86
+ a: 1,
87
+ }
88
+
89
+ test(`encode`, _ => {
90
+ let encoded = sampleRecord->t2_encode
91
+ expect(encoded) |> toEqual(sampleJson)
92
+ })
93
+
94
+ test(`decode`, _ => {
95
+ let decoded = sampleJson->t2_decode
96
+ expect(decoded) |> toEqual(Belt.Result.Ok(sampleRecord))
97
+ })
98
+ })
@@ -0,0 +1,237 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ 'use strict';
3
+
4
+ var Spice = require("./Spice.js");
5
+ var Js_dict = require("rescript/lib/js/js_dict.js");
6
+ var Js_json = require("rescript/lib/js/js_json.js");
7
+ var Belt_Option = require("rescript/lib/js/belt_Option.js");
8
+
9
+ function t0_encode(v) {
10
+ return Js_dict.fromArray(Spice.filterOptional([
11
+ [
12
+ "a",
13
+ false,
14
+ Spice.intToJson(v.a)
15
+ ],
16
+ [
17
+ "b",
18
+ true,
19
+ Spice.optionToJson(Spice.intToJson, v.b)
20
+ ]
21
+ ]));
22
+ }
23
+
24
+ function t0_decode(v) {
25
+ var dict = Js_json.classify(v);
26
+ if (typeof dict === "number") {
27
+ return Spice.error(undefined, "Not an object", v);
28
+ }
29
+ if (dict.TAG !== /* JSONObject */2) {
30
+ return Spice.error(undefined, "Not an object", v);
31
+ }
32
+ var dict$1 = dict._0;
33
+ var a = Spice.intFromJson(Belt_Option.getWithDefault(Js_dict.get(dict$1, "a"), null));
34
+ if (a.TAG === /* Ok */0) {
35
+ var b = Spice.optionFromJson(Spice.intFromJson, Belt_Option.getWithDefault(Js_dict.get(dict$1, "b"), null));
36
+ if (b.TAG === /* Ok */0) {
37
+ return {
38
+ TAG: /* Ok */0,
39
+ _0: {
40
+ a: a._0,
41
+ b: b._0
42
+ }
43
+ };
44
+ }
45
+ var e = b._0;
46
+ return {
47
+ TAG: /* Error */1,
48
+ _0: {
49
+ path: ".b" + e.path,
50
+ message: e.message,
51
+ value: e.value
52
+ }
53
+ };
54
+ }
55
+ var e$1 = a._0;
56
+ return {
57
+ TAG: /* Error */1,
58
+ _0: {
59
+ path: ".a" + e$1.path,
60
+ message: e$1.message,
61
+ value: e$1.value
62
+ }
63
+ };
64
+ }
65
+
66
+ function t1_encode(v) {
67
+ return Js_dict.fromArray(Spice.filterOptional([
68
+ [
69
+ "a",
70
+ false,
71
+ Spice.intToJson(v.a)
72
+ ],
73
+ [
74
+ "bs",
75
+ true,
76
+ Spice.optionToJson((function (param) {
77
+ return Spice.arrayToJson(Spice.intToJson, param);
78
+ }), v.bs)
79
+ ]
80
+ ]));
81
+ }
82
+
83
+ function t1_decode(v) {
84
+ var dict = Js_json.classify(v);
85
+ if (typeof dict === "number") {
86
+ return Spice.error(undefined, "Not an object", v);
87
+ }
88
+ if (dict.TAG !== /* JSONObject */2) {
89
+ return Spice.error(undefined, "Not an object", v);
90
+ }
91
+ var dict$1 = dict._0;
92
+ var a = Spice.intFromJson(Belt_Option.getWithDefault(Js_dict.get(dict$1, "a"), null));
93
+ if (a.TAG === /* Ok */0) {
94
+ var bs = Spice.optionFromJson((function (param) {
95
+ return Spice.arrayFromJson(Spice.intFromJson, param);
96
+ }), Belt_Option.getWithDefault(Js_dict.get(dict$1, "bs"), null));
97
+ if (bs.TAG === /* Ok */0) {
98
+ return {
99
+ TAG: /* Ok */0,
100
+ _0: {
101
+ a: a._0,
102
+ bs: bs._0
103
+ }
104
+ };
105
+ }
106
+ var e = bs._0;
107
+ return {
108
+ TAG: /* Error */1,
109
+ _0: {
110
+ path: ".bs" + e.path,
111
+ message: e.message,
112
+ value: e.value
113
+ }
114
+ };
115
+ }
116
+ var e$1 = a._0;
117
+ return {
118
+ TAG: /* Error */1,
119
+ _0: {
120
+ path: ".a" + e$1.path,
121
+ message: e$1.message,
122
+ value: e$1.value
123
+ }
124
+ };
125
+ }
126
+
127
+ function b_encode(v) {
128
+ switch (v) {
129
+ case /* B0 */0 :
130
+ return "B0";
131
+ case /* B1 */1 :
132
+ return "B1";
133
+ case /* B2 */2 :
134
+ return "B2";
135
+
136
+ }
137
+ }
138
+
139
+ function b_decode(v) {
140
+ var str = Js_json.classify(v);
141
+ if (typeof str === "number") {
142
+ return Spice.error(undefined, "Not a JSONString", v);
143
+ }
144
+ if (str.TAG !== /* JSONString */0) {
145
+ return Spice.error(undefined, "Not a JSONString", v);
146
+ }
147
+ var str$1 = str._0;
148
+ if ("B0" === str$1) {
149
+ return {
150
+ TAG: /* Ok */0,
151
+ _0: /* B0 */0
152
+ };
153
+ } else if ("B1" === str$1) {
154
+ return {
155
+ TAG: /* Ok */0,
156
+ _0: /* B1 */1
157
+ };
158
+ } else if ("B2" === str$1) {
159
+ return {
160
+ TAG: /* Ok */0,
161
+ _0: /* B2 */2
162
+ };
163
+ } else {
164
+ return Spice.error(undefined, "Not matched", v);
165
+ }
166
+ }
167
+
168
+ function t2_encode(v) {
169
+ return Js_dict.fromArray(Spice.filterOptional([
170
+ [
171
+ "a",
172
+ false,
173
+ Spice.intToJson(v.a)
174
+ ],
175
+ [
176
+ "bs",
177
+ true,
178
+ Spice.optionToJson((function (param) {
179
+ return Spice.arrayToJson(b_encode, param);
180
+ }), v.bs)
181
+ ]
182
+ ]));
183
+ }
184
+
185
+ function t2_decode(v) {
186
+ var dict = Js_json.classify(v);
187
+ if (typeof dict === "number") {
188
+ return Spice.error(undefined, "Not an object", v);
189
+ }
190
+ if (dict.TAG !== /* JSONObject */2) {
191
+ return Spice.error(undefined, "Not an object", v);
192
+ }
193
+ var dict$1 = dict._0;
194
+ var a = Spice.intFromJson(Belt_Option.getWithDefault(Js_dict.get(dict$1, "a"), null));
195
+ if (a.TAG === /* Ok */0) {
196
+ var bs = Spice.optionFromJson((function (param) {
197
+ return Spice.arrayFromJson(b_decode, param);
198
+ }), Belt_Option.getWithDefault(Js_dict.get(dict$1, "bs"), null));
199
+ if (bs.TAG === /* Ok */0) {
200
+ return {
201
+ TAG: /* Ok */0,
202
+ _0: {
203
+ a: a._0,
204
+ bs: bs._0
205
+ }
206
+ };
207
+ }
208
+ var e = bs._0;
209
+ return {
210
+ TAG: /* Error */1,
211
+ _0: {
212
+ path: ".bs" + e.path,
213
+ message: e.message,
214
+ value: e.value
215
+ }
216
+ };
217
+ }
218
+ var e$1 = a._0;
219
+ return {
220
+ TAG: /* Error */1,
221
+ _0: {
222
+ path: ".a" + e$1.path,
223
+ message: e$1.message,
224
+ value: e$1.value
225
+ }
226
+ };
227
+ }
228
+
229
+ exports.t0_encode = t0_encode;
230
+ exports.t0_decode = t0_decode;
231
+ exports.t1_encode = t1_encode;
232
+ exports.t1_decode = t1_decode;
233
+ exports.b_encode = b_encode;
234
+ exports.b_decode = b_decode;
235
+ exports.t2_encode = t2_encode;
236
+ exports.t2_decode = t2_decode;
237
+ /* No side effect */
@@ -0,0 +1,23 @@
1
+ @spice
2
+ type t0 = {
3
+ a: int,
4
+ b?: int,
5
+ }
6
+
7
+ @spice
8
+ type t1 = {
9
+ a: int,
10
+ bs?: array<int>,
11
+ }
12
+
13
+ @spice
14
+ type b =
15
+ | @spice.as("B0") B0
16
+ | @spice.as("B1") B1
17
+ | @spice.as("B2") B2
18
+
19
+ @spice
20
+ type t2 = {
21
+ a: int,
22
+ bs?: array<b>,
23
+ }