From 0787f58bb4c690552114046124d3fe58d07034f6 Mon Sep 17 00:00:00 2001 From: Nikita Shilnikov Date: Mon, 14 Jul 2025 11:41:38 +0200 Subject: [PATCH 1/4] Compatibility with rescript 12 --- package-lock.json | 166 ++++++++++++++++++++++++++++++--- package.json | 8 +- bsconfig.json => rescript.json | 0 src/Json.res | 9 +- src/Json_Decode.res | 60 ++++++------ src/Json_Encode.res | 4 +- 6 files changed, 195 insertions(+), 52 deletions(-) rename bsconfig.json => rescript.json (100%) diff --git a/package-lock.json b/package-lock.json index 2562373..6594a90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,34 +9,174 @@ "version": "1.4.0", "license": "(LGPL-3.0 OR MPL-2.0)", "devDependencies": { - "rescript": "^11.0.1" + "rescript": "^12.0.0-beta.1" }, "engines": { "node": "*" } }, + "node_modules/@rescript/darwin-arm64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.1.tgz", + "integrity": "sha512-NSzlBbuGDS1D5NTw2W7lh98Ylek8cTSz/kHmkugj2ePrEyuVDEAqLiyWsj6pbvJ4LQzr8ZOCf8emnmslDgauEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@rescript/darwin-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-Jr0yArQHiwxW3grALCcXDpAbK4V3Zsrg6Ekn6WixzfJR9LaXbquJFST/BOs0aO3kKj2kJrDSbvheHhPcCdNa9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@rescript/linux-arm64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.1.tgz", + "integrity": "sha512-Hj8zcFd/QlNybKrj3AklIib1kbb5LuuXcBbNuD5vaMmbKwfAO8iUA9OTFyaHWqgMKurkKYEc2oa5IE3/EQntag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@rescript/linux-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-ZDTIvFzior+KZ964firAG9Sm6WunJM8+2OIElXvGIL2P5GL9VlU71ap5IBIt5GV5jHRiYq5uJLnQSI+jtpbw/w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@rescript/win32-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-aTXZ2c8AiBmoI3gAA8CQpgKYMjj6pAzuHnl3PQLRr9h5Hz7EWN9ZrktTa2GC0soP414lsl1Yyx7g9YIacypRAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/rescript": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.1.tgz", - "integrity": "sha512-7T4PRp/d0+CBNnY6PYKffFqo9tGZlvnZpboF/n+8SKS+JZ6VvXJO7W538VPZXf3EYx1COGAWWvkF9e/HgSAqHg==", + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.1.tgz", + "integrity": "sha512-MuVs8AcHm3QU5knt5mBeGmvhz4LY4GEkF6MurzGDTcWm6TkdEC5zWfh5cOi08QKjlZDYzNBDCPXzTR7bnsCEAA==", "dev": true, - "hasInstallScript": true, + "workspaces": [ + "packages/*", + "packages/@rescript/*", + "tests/dependencies/**", + "tests/analysis_tests/**", + "tests/docstring_tests", + "tests/gentype_tests/**", + "tests/tools_tests", + "scripts/res" + ], "bin": { - "bsc": "bsc", - "bstracing": "lib/bstracing", - "rescript": "rescript" + "bsc": "cli/bsc.js", + "bstracing": "cli/bstracing.js", + "rescript": "cli/rescript.js", + "rescript-legacy": "cli/rescript-legacy.js", + "rescript-tools": "cli/rescript-tools.js" }, "engines": { - "node": ">=10" + "node": ">=20.11.0" + }, + "optionalDependencies": { + "@rescript/darwin-arm64": "12.0.0-beta.1", + "@rescript/darwin-x64": "12.0.0-beta.1", + "@rescript/linux-arm64": "12.0.0-beta.1", + "@rescript/linux-x64": "12.0.0-beta.1", + "@rescript/win32-x64": "12.0.0-beta.1" } } }, "dependencies": { + "@rescript/darwin-arm64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.1.tgz", + "integrity": "sha512-NSzlBbuGDS1D5NTw2W7lh98Ylek8cTSz/kHmkugj2ePrEyuVDEAqLiyWsj6pbvJ4LQzr8ZOCf8emnmslDgauEg==", + "dev": true, + "optional": true + }, + "@rescript/darwin-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-Jr0yArQHiwxW3grALCcXDpAbK4V3Zsrg6Ekn6WixzfJR9LaXbquJFST/BOs0aO3kKj2kJrDSbvheHhPcCdNa9w==", + "dev": true, + "optional": true + }, + "@rescript/linux-arm64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.1.tgz", + "integrity": "sha512-Hj8zcFd/QlNybKrj3AklIib1kbb5LuuXcBbNuD5vaMmbKwfAO8iUA9OTFyaHWqgMKurkKYEc2oa5IE3/EQntag==", + "dev": true, + "optional": true + }, + "@rescript/linux-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-ZDTIvFzior+KZ964firAG9Sm6WunJM8+2OIElXvGIL2P5GL9VlU71ap5IBIt5GV5jHRiYq5uJLnQSI+jtpbw/w==", + "dev": true, + "optional": true + }, + "@rescript/win32-x64": { + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.1.tgz", + "integrity": "sha512-aTXZ2c8AiBmoI3gAA8CQpgKYMjj6pAzuHnl3PQLRr9h5Hz7EWN9ZrktTa2GC0soP414lsl1Yyx7g9YIacypRAQ==", + "dev": true, + "optional": true + }, "rescript": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.1.tgz", - "integrity": "sha512-7T4PRp/d0+CBNnY6PYKffFqo9tGZlvnZpboF/n+8SKS+JZ6VvXJO7W538VPZXf3EYx1COGAWWvkF9e/HgSAqHg==", - "dev": true + "version": "12.0.0-beta.1", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.1.tgz", + "integrity": "sha512-MuVs8AcHm3QU5knt5mBeGmvhz4LY4GEkF6MurzGDTcWm6TkdEC5zWfh5cOi08QKjlZDYzNBDCPXzTR7bnsCEAA==", + "dev": true, + "requires": { + "@rescript/darwin-arm64": "12.0.0-beta.1", + "@rescript/darwin-x64": "12.0.0-beta.1", + "@rescript/linux-arm64": "12.0.0-beta.1", + "@rescript/linux-x64": "12.0.0-beta.1", + "@rescript/win32-x64": "12.0.0-beta.1" + } } } } diff --git a/package.json b/package.json index f26af36..eae4e5d 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "version": "1.4.0", "description": "Combinator library for JSON decoding and encoding. ", "scripts": { - "build": "rescript build -with-deps", - "start": "rescript build -w -with-deps", + "build": "rescript legacy build -with-deps", + "start": "rescript legacy build -w -with-deps", "clean": "rescript clean", "fmt": "rescript format -all", "test": "true" @@ -28,9 +28,9 @@ "homepage": "https://github.com/glennsl/rescript-json-combinators#readme", "files": [ "src/*.res*", - "bsconfig.json" + "rescript.json" ], "devDependencies": { - "rescript": "^11.0.1" + "rescript": "^12.0.0-beta.1" } } diff --git a/bsconfig.json b/rescript.json similarity index 100% rename from bsconfig.json rename to rescript.json diff --git a/src/Json.res b/src/Json.res index 2a04671..fbfdec0 100644 --- a/src/Json.res +++ b/src/Json.res @@ -7,13 +7,16 @@ let decode = Decode.decode let parse = str => try Ok(str->Js.Json.parseExn) catch { - | Js.Exn.Error(ex) => Error(ex->Js.Exn.message->Js.Option.getWithDefault("Unknown error", _)) + | ex => + let message = ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") + Error(message) } let parseExn = str => try str->Js.Json.parseExn catch { - | Js.Exn.Error(ex) => - raise(ParseError(ex->Js.Exn.message->Js.Option.getWithDefault("Unknown error", _))) + | ex => + let message = ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") + throw(ParseError(message)) } @val external stringify: Js.Json.t => string = "JSON.stringify" diff --git a/src/Json_Decode.res b/src/Json_Decode.res index 3cf2afa..6e071d6 100644 --- a/src/Json_Decode.res +++ b/src/Json_Decode.res @@ -10,7 +10,7 @@ type fieldDecoders = { exception DecodeError(string) module Error = { - let expected = (kind, json) => raise(DecodeError(`Expected ${kind}, got ${stringify(json)}`)) + let expected = (kind, json) => throw(DecodeError(`Expected ${kind}, got ${stringify(json)}`)) } let custom = f => f @@ -66,16 +66,16 @@ let array = (decode) => (. json) => { for i in 0 to Array.length(source) - 1 { try { let value = decode(. %raw("json[i]")) - target->Array.unsafe_set(i, value) + target->Array.setUnsafe(i, value) } catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tin array at index ${string_of_int(i)}`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin array at index ${Int.toString(i)}`)) } } target } -let list = (decode) => (. json) => array(decode)(. json)->Array.to_list +let list = (decode) => (. json) => array(decode)(. json)->List.fromArray let option = decode => (. json) => { if Obj.magic(json) == Js.null { @@ -94,15 +94,15 @@ let tuple2 = (decodeA, decodeB) => (. json) => { let arr: array = Obj.magic(json) if Array.length(arr) != 2 { - raise( + throw( DecodeError( - `Expected array of length 2, got array of length ${Array.length(arr)->string_of_int}`, + `Expected array of length 2, got array of length ${Array.length(arr)->Int.toString}`, ), ) } - try (decodeA(. arr->Array.unsafe_get(0)), decodeB(. arr->Array.unsafe_get(1))) catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tin pair`)) + try (decodeA(. arr->Array.getUnsafe(0)), decodeB(. arr->Array.getUnsafe(1))) catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) } } let pair = tuple2 @@ -114,19 +114,19 @@ let tuple3 = (decodeA, decodeB, decodeC) => (. json) => { let arr: array = Obj.magic(json) if Array.length(arr) != 3 { - raise( + throw( DecodeError( - `Expected array of length 3, got array of length ${Array.length(arr)->string_of_int}`, + `Expected array of length 3, got array of length ${Array.length(arr)->Int.toString}`, ), ) } try ( - decodeA(. arr->Array.unsafe_get(0)), - decodeB(. arr->Array.unsafe_get(1)), - decodeC(. arr->Array.unsafe_get(2)), + decodeA(. arr->Array.getUnsafe(0)), + decodeB(. arr->Array.getUnsafe(1)), + decodeC(. arr->Array.getUnsafe(2)), ) catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tin pair`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) } } @@ -137,20 +137,20 @@ let tuple4 = (decodeA, decodeB, decodeC, decodeD) => (. json) => { let arr: array = Obj.magic(json) if Array.length(arr) != 4 { - raise( + throw( DecodeError( - `Expected array of length 4, got array of length ${Array.length(arr)->string_of_int}`, + `Expected array of length 4, got array of length ${Array.length(arr)->Int.toString}`, ), ) } try ( - decodeA(. arr->Array.unsafe_get(0)), - decodeB(. arr->Array.unsafe_get(1)), - decodeC(. arr->Array.unsafe_get(2)), - decodeD(. arr->Array.unsafe_get(3)), + decodeA(. arr->Array.getUnsafe(0)), + decodeB(. arr->Array.getUnsafe(1)), + decodeC(. arr->Array.getUnsafe(2)), + decodeD(. arr->Array.getUnsafe(3)), ) catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tin pair`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) } } @@ -161,7 +161,7 @@ let dict = decode => (. json) => { let source: Js.Dict.t = Obj.magic(json) try Js.Dict.map(decode, source)->Obj.magic catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tin dict'`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin dict'`)) } } @@ -171,17 +171,17 @@ let field = (key, decode) => (. json) => { } if !(%raw("key in json")) { - raise(DecodeError(`${key} required`)) + throw(DecodeError(`${key} required`)) } try decode(. %raw("json[key]")) catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tat field '${key}'`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) } } let object = f => (. json) => { if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { - raise(Error.expected("object", json)) + throw(Error.expected("object", json)) } let optional = (. key, decode) => { @@ -192,18 +192,18 @@ let object = f => (. json) => { let value = decode(. %raw("json[key]")) Some(value) } catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tat field '${key}'`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) } } } let required = (. key, decode) => { if !(%raw("key in json")) { - raise(DecodeError(`${key} required`)) + throw(DecodeError(`${key} required`)) } try decode(. %raw("json[key]")) catch { - | DecodeError(msg) => raise(DecodeError(`${msg}\n\tat field '${key}'`)) + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) } } @@ -215,7 +215,7 @@ let oneOf = decoders => (. json) => { let rec loop = i => { if i >= Array.length(decoders) { - raise( + throw( DecodeError( `All decoders given to oneOf failed. Here are all the errors:\n- ${errors->Js.Array2.joinWith( "\n", @@ -224,7 +224,7 @@ let oneOf = decoders => (. json) => { ) } - let decode = Array.unsafe_get(decoders, i) + let decode = Array.getUnsafe(decoders, i) try decode(. json) catch { | DecodeError(err) => errors->Js.Array2.push(err)->ignore diff --git a/src/Json_Encode.res b/src/Json_Encode.res index 2229b93..6c34bf5 100644 --- a/src/Json_Encode.res +++ b/src/Json_Encode.res @@ -20,12 +20,12 @@ let list = encode => l => switch l { | list{} => jsonArray([]) | list{hd, ...tl} => - let arr = Array.make(l->List.length, hd->encode) + let arr = Array.make(~length=l->List.length, hd->encode) let rec fill = (i, l) => switch l { | list{} => arr | list{hd, ...tl} => - Array.unsafe_set(arr, i, hd->encode) + Array.setUnsafe(arr, i, hd->encode) fill(i + 1, tl) } fill(1, tl)->jsonArray From 3d5b657ca9d012253999d7d7dc6c7e2f97582b48 Mon Sep 17 00:00:00 2001 From: Nikita Shilnikov Date: Thu, 7 Aug 2025 12:52:33 +0300 Subject: [PATCH 2/4] Update rescript to beta.4 --- package-lock.json | 94 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6594a90..6e5fa20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,16 +9,16 @@ "version": "1.4.0", "license": "(LGPL-3.0 OR MPL-2.0)", "devDependencies": { - "rescript": "^12.0.0-beta.1" + "rescript": "^12.0.0-beta.4" }, "engines": { "node": "*" } }, "node_modules/@rescript/darwin-arm64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.1.tgz", - "integrity": "sha512-NSzlBbuGDS1D5NTw2W7lh98Ylek8cTSz/kHmkugj2ePrEyuVDEAqLiyWsj6pbvJ4LQzr8ZOCf8emnmslDgauEg==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.4.tgz", + "integrity": "sha512-UenADkeR86PyFJ89AY0utG5fi1/3DLEBHoof0DjgXpMhZoPg+fjXcxRGhtBpN1Bov59kBLxIDLX0T6ZkFtjbwQ==", "cpu": [ "arm64" ], @@ -32,9 +32,9 @@ } }, "node_modules/@rescript/darwin-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-Jr0yArQHiwxW3grALCcXDpAbK4V3Zsrg6Ekn6WixzfJR9LaXbquJFST/BOs0aO3kKj2kJrDSbvheHhPcCdNa9w==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-aKSabtfetlVvA0EA2G4TBTlDH96CZsnmCMbsGwwMDvLLr4cmnmJoMO/nvgI5AdFcNUW/NGVtGVsgPfcmLd7EWQ==", "cpu": [ "x64" ], @@ -48,9 +48,9 @@ } }, "node_modules/@rescript/linux-arm64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.1.tgz", - "integrity": "sha512-Hj8zcFd/QlNybKrj3AklIib1kbb5LuuXcBbNuD5vaMmbKwfAO8iUA9OTFyaHWqgMKurkKYEc2oa5IE3/EQntag==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.4.tgz", + "integrity": "sha512-UHClm/Gsdv5v2kLgEhkqfIsDeYSIuACGmHWPhskg93+EjeBHpPWr4DG/8XdhywZfTFgIGsIYzpZ3ejRfKq5X+Q==", "cpu": [ "arm64" ], @@ -64,9 +64,9 @@ } }, "node_modules/@rescript/linux-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-ZDTIvFzior+KZ964firAG9Sm6WunJM8+2OIElXvGIL2P5GL9VlU71ap5IBIt5GV5jHRiYq5uJLnQSI+jtpbw/w==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-c7ueadv9lhK77sCi9zfQPkaz4vmzoW4U2b4GgUqkSzDlOxYT3ttWiC2+deGBJ26Q7CsWL/kFb0Hp2rydjkkexw==", "cpu": [ "x64" ], @@ -80,9 +80,9 @@ } }, "node_modules/@rescript/win32-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-aTXZ2c8AiBmoI3gAA8CQpgKYMjj6pAzuHnl3PQLRr9h5Hz7EWN9ZrktTa2GC0soP414lsl1Yyx7g9YIacypRAQ==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-qMhBvqQp0wnKp+z1do79NHb/j3t50946P4QH01/ErtJpTLEJUyx6OzaEaNu5r4iu+AXAKtFG26497JICvuTWJg==", "cpu": [ "x64" ], @@ -96,9 +96,9 @@ } }, "node_modules/rescript": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.1.tgz", - "integrity": "sha512-MuVs8AcHm3QU5knt5mBeGmvhz4LY4GEkF6MurzGDTcWm6TkdEC5zWfh5cOi08QKjlZDYzNBDCPXzTR7bnsCEAA==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.4.tgz", + "integrity": "sha512-Le3fnsa6MUDecmpnfIuJMA8cXraRLrdEd4Ho2m5OavTKbWgINzJiG3sqlnF1yPpWNPZ3nL5D8oRNakcpp1fbtg==", "dev": true, "workspaces": [ "packages/*", @@ -121,61 +121,61 @@ "node": ">=20.11.0" }, "optionalDependencies": { - "@rescript/darwin-arm64": "12.0.0-beta.1", - "@rescript/darwin-x64": "12.0.0-beta.1", - "@rescript/linux-arm64": "12.0.0-beta.1", - "@rescript/linux-x64": "12.0.0-beta.1", - "@rescript/win32-x64": "12.0.0-beta.1" + "@rescript/darwin-arm64": "12.0.0-beta.4", + "@rescript/darwin-x64": "12.0.0-beta.4", + "@rescript/linux-arm64": "12.0.0-beta.4", + "@rescript/linux-x64": "12.0.0-beta.4", + "@rescript/win32-x64": "12.0.0-beta.4" } } }, "dependencies": { "@rescript/darwin-arm64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.1.tgz", - "integrity": "sha512-NSzlBbuGDS1D5NTw2W7lh98Ylek8cTSz/kHmkugj2ePrEyuVDEAqLiyWsj6pbvJ4LQzr8ZOCf8emnmslDgauEg==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/darwin-arm64/-/darwin-arm64-12.0.0-beta.4.tgz", + "integrity": "sha512-UenADkeR86PyFJ89AY0utG5fi1/3DLEBHoof0DjgXpMhZoPg+fjXcxRGhtBpN1Bov59kBLxIDLX0T6ZkFtjbwQ==", "dev": true, "optional": true }, "@rescript/darwin-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-Jr0yArQHiwxW3grALCcXDpAbK4V3Zsrg6Ekn6WixzfJR9LaXbquJFST/BOs0aO3kKj2kJrDSbvheHhPcCdNa9w==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/darwin-x64/-/darwin-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-aKSabtfetlVvA0EA2G4TBTlDH96CZsnmCMbsGwwMDvLLr4cmnmJoMO/nvgI5AdFcNUW/NGVtGVsgPfcmLd7EWQ==", "dev": true, "optional": true }, "@rescript/linux-arm64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.1.tgz", - "integrity": "sha512-Hj8zcFd/QlNybKrj3AklIib1kbb5LuuXcBbNuD5vaMmbKwfAO8iUA9OTFyaHWqgMKurkKYEc2oa5IE3/EQntag==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/linux-arm64/-/linux-arm64-12.0.0-beta.4.tgz", + "integrity": "sha512-UHClm/Gsdv5v2kLgEhkqfIsDeYSIuACGmHWPhskg93+EjeBHpPWr4DG/8XdhywZfTFgIGsIYzpZ3ejRfKq5X+Q==", "dev": true, "optional": true }, "@rescript/linux-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-ZDTIvFzior+KZ964firAG9Sm6WunJM8+2OIElXvGIL2P5GL9VlU71ap5IBIt5GV5jHRiYq5uJLnQSI+jtpbw/w==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/linux-x64/-/linux-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-c7ueadv9lhK77sCi9zfQPkaz4vmzoW4U2b4GgUqkSzDlOxYT3ttWiC2+deGBJ26Q7CsWL/kFb0Hp2rydjkkexw==", "dev": true, "optional": true }, "@rescript/win32-x64": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.1.tgz", - "integrity": "sha512-aTXZ2c8AiBmoI3gAA8CQpgKYMjj6pAzuHnl3PQLRr9h5Hz7EWN9ZrktTa2GC0soP414lsl1Yyx7g9YIacypRAQ==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@rescript/win32-x64/-/win32-x64-12.0.0-beta.4.tgz", + "integrity": "sha512-qMhBvqQp0wnKp+z1do79NHb/j3t50946P4QH01/ErtJpTLEJUyx6OzaEaNu5r4iu+AXAKtFG26497JICvuTWJg==", "dev": true, "optional": true }, "rescript": { - "version": "12.0.0-beta.1", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.1.tgz", - "integrity": "sha512-MuVs8AcHm3QU5knt5mBeGmvhz4LY4GEkF6MurzGDTcWm6TkdEC5zWfh5cOi08QKjlZDYzNBDCPXzTR7bnsCEAA==", + "version": "12.0.0-beta.4", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-12.0.0-beta.4.tgz", + "integrity": "sha512-Le3fnsa6MUDecmpnfIuJMA8cXraRLrdEd4Ho2m5OavTKbWgINzJiG3sqlnF1yPpWNPZ3nL5D8oRNakcpp1fbtg==", "dev": true, "requires": { - "@rescript/darwin-arm64": "12.0.0-beta.1", - "@rescript/darwin-x64": "12.0.0-beta.1", - "@rescript/linux-arm64": "12.0.0-beta.1", - "@rescript/linux-x64": "12.0.0-beta.1", - "@rescript/win32-x64": "12.0.0-beta.1" + "@rescript/darwin-arm64": "12.0.0-beta.4", + "@rescript/darwin-x64": "12.0.0-beta.4", + "@rescript/linux-arm64": "12.0.0-beta.4", + "@rescript/linux-x64": "12.0.0-beta.4", + "@rescript/win32-x64": "12.0.0-beta.4" } } } diff --git a/package.json b/package.json index eae4e5d..3e3a96e 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,6 @@ "rescript.json" ], "devDependencies": { - "rescript": "^12.0.0-beta.1" + "rescript": "^12.0.0-beta.4" } } From 3c299ada432b9b91126462cded220a364d16e288 Mon Sep 17 00:00:00 2001 From: Nikita Shilnikov Date: Thu, 7 Aug 2025 12:53:04 +0300 Subject: [PATCH 3/4] Update scripts --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3e3a96e..b71fe2d 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,10 @@ "version": "1.4.0", "description": "Combinator library for JSON decoding and encoding. ", "scripts": { - "build": "rescript legacy build -with-deps", - "start": "rescript legacy build -w -with-deps", + "build": "rescript build", + "start": "rescript watch", "clean": "rescript clean", - "fmt": "rescript format -all", + "fmt": "rescript format -a", "test": "true" }, "engines": { From dfb92cb43b66cb8832071ea47fc35e3ffd8b8480 Mon Sep 17 00:00:00 2001 From: Nikita Shilnikov Date: Thu, 7 Aug 2025 18:07:33 +0300 Subject: [PATCH 4/4] Run format --- src/Json.res | 6 +- src/Json_Decode.res | 316 ++++++++++++++++++++++--------------------- src/Json_Decode.resi | 12 +- src/Json_Encode.res | 59 ++++---- 4 files changed, 204 insertions(+), 189 deletions(-) diff --git a/src/Json.res b/src/Json.res index fbfdec0..5360a90 100644 --- a/src/Json.res +++ b/src/Json.res @@ -8,14 +8,16 @@ let decode = Decode.decode let parse = str => try Ok(str->Js.Json.parseExn) catch { | ex => - let message = ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") + let message = + ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") Error(message) } let parseExn = str => try str->Js.Json.parseExn catch { | ex => - let message = ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") + let message = + ex->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("Unknown error") throw(ParseError(message)) } diff --git a/src/Json_Decode.res b/src/Json_Decode.res index 6e071d6..c226ae0 100644 --- a/src/Json_Decode.res +++ b/src/Json_Decode.res @@ -1,10 +1,10 @@ open Js.Json -type t<'a> = (. Js.Json.t) => 'a +type t<'a> = Js.Json.t => 'a type fieldDecoders = { - optional: 'a. (. string, t<'a>) => option<'a>, - required: 'a. (. string, t<'a>) => 'a, + optional: 'a. (string, t<'a>) => option<'a>, + required: 'a. (string, t<'a>) => 'a, } exception DecodeError(string) @@ -15,9 +15,9 @@ module Error = { let custom = f => f -let id = (. json) => json +let id = json => json -let float = (. json) => { +let float = json => { if Js.typeof(json) != "number" { Error.expected("float", json) } @@ -25,7 +25,7 @@ let float = (. json) => { Obj.magic(json) } -let int = (. json) => { +let int = json => { if Js.typeof(json) != "number" { Error.expected("int", json) } @@ -39,7 +39,7 @@ let int = (. json) => { Obj.magic(json) } -let bool = (. json) => { +let bool = json => { if Js.typeof(json) != "boolean" { Error.expected("bool", json) } @@ -47,7 +47,7 @@ let bool = (. json) => { Obj.magic(json) } -let string = (. json) => { +let string = json => { if Js.typeof(json) != "string" { Error.expected("string", json) } @@ -55,196 +55,206 @@ let string = (. json) => { Obj.magic(json) } -let array = (decode) => (. json) => { - if !Js.Array.isArray(json) { - Error.expected("array", json) - } - - let source: array = Obj.magic(json) - let target = %raw("new Array(json.length)") - - for i in 0 to Array.length(source) - 1 { - try { - let value = decode(. %raw("json[i]")) - target->Array.setUnsafe(i, value) - } catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin array at index ${Int.toString(i)}`)) +let array = decode => + json => { + if !Js.Array.isArray(json) { + Error.expected("array", json) } - } - - target -} -let list = (decode) => (. json) => array(decode)(. json)->List.fromArray + let source: array = Obj.magic(json) + let target = %raw("new Array(json.length)") -let option = decode => (. json) => { - if Obj.magic(json) == Js.null { - None - } else { - Some(decode(. json)) - } -} - -let date = (. json) => string(. json)->Js.Date.fromString + for i in 0 to Array.length(source) - 1 { + try { + let value = decode(%raw("json[i]")) + target->Array.setUnsafe(i, value) + } catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin array at index ${Int.toString(i)}`)) + } + } -let tuple2 = (decodeA, decodeB) => (. json) => { - if !Js.Array.isArray(json) { - Error.expected("array", json) + target } - let arr: array = Obj.magic(json) - if Array.length(arr) != 2 { - throw( - DecodeError( - `Expected array of length 2, got array of length ${Array.length(arr)->Int.toString}`, - ), - ) - } +let list = decode => json => array(decode)(json)->List.fromArray - try (decodeA(. arr->Array.getUnsafe(0)), decodeB(. arr->Array.getUnsafe(1))) catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) +let option = decode => + json => { + if Obj.magic(json) == Js.null { + None + } else { + Some(decode(json)) + } } -} -let pair = tuple2 -let tuple3 = (decodeA, decodeB, decodeC) => (. json) => { - if !Js.Array.isArray(json) { - Error.expected("array", json) - } +let date = json => string(json)->Js.Date.fromString - let arr: array = Obj.magic(json) - if Array.length(arr) != 3 { - throw( - DecodeError( - `Expected array of length 3, got array of length ${Array.length(arr)->Int.toString}`, - ), - ) - } +let tuple2 = (decodeA, decodeB) => + json => { + if !Js.Array.isArray(json) { + Error.expected("array", json) + } - try ( - decodeA(. arr->Array.getUnsafe(0)), - decodeB(. arr->Array.getUnsafe(1)), - decodeC(. arr->Array.getUnsafe(2)), - ) catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) - } -} + let arr: array = Obj.magic(json) + if Array.length(arr) != 2 { + throw( + DecodeError( + `Expected array of length 2, got array of length ${Array.length(arr)->Int.toString}`, + ), + ) + } -let tuple4 = (decodeA, decodeB, decodeC, decodeD) => (. json) => { - if !Js.Array.isArray(json) { - Error.expected("array", json) + try (decodeA(arr->Array.getUnsafe(0)), decodeB(arr->Array.getUnsafe(1))) catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) + } } +let pair = tuple2 - let arr: array = Obj.magic(json) - if Array.length(arr) != 4 { - throw( - DecodeError( - `Expected array of length 4, got array of length ${Array.length(arr)->Int.toString}`, - ), - ) - } +let tuple3 = (decodeA, decodeB, decodeC) => + json => { + if !Js.Array.isArray(json) { + Error.expected("array", json) + } - try ( - decodeA(. arr->Array.getUnsafe(0)), - decodeB(. arr->Array.getUnsafe(1)), - decodeC(. arr->Array.getUnsafe(2)), - decodeD(. arr->Array.getUnsafe(3)), - ) catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) - } -} + let arr: array = Obj.magic(json) + if Array.length(arr) != 3 { + throw( + DecodeError( + `Expected array of length 3, got array of length ${Array.length(arr)->Int.toString}`, + ), + ) + } -let dict = decode => (. json) => { - if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { - Error.expected("object", json) + try ( + decodeA(arr->Array.getUnsafe(0)), + decodeB(arr->Array.getUnsafe(1)), + decodeC(arr->Array.getUnsafe(2)), + ) catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) + } } - let source: Js.Dict.t = Obj.magic(json) - try Js.Dict.map(decode, source)->Obj.magic catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin dict'`)) - } -} +let tuple4 = (decodeA, decodeB, decodeC, decodeD) => + json => { + if !Js.Array.isArray(json) { + Error.expected("array", json) + } -let field = (key, decode) => (. json) => { - if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { - Error.expected("object", json) - } + let arr: array = Obj.magic(json) + if Array.length(arr) != 4 { + throw( + DecodeError( + `Expected array of length 4, got array of length ${Array.length(arr)->Int.toString}`, + ), + ) + } - if !(%raw("key in json")) { - throw(DecodeError(`${key} required`)) + try ( + decodeA(arr->Array.getUnsafe(0)), + decodeB(arr->Array.getUnsafe(1)), + decodeC(arr->Array.getUnsafe(2)), + decodeD(arr->Array.getUnsafe(3)), + ) catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin pair`)) + } } - try decode(. %raw("json[key]")) catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) - } -} +let dict = decode => + json => { + if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { + Error.expected("object", json) + } -let object = f => (. json) => { - if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { - throw(Error.expected("object", json)) + let source: Js.Dict.t = Obj.magic(json) + try Js.Dict.map(decode, source)->Obj.magic catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tin dict'`)) + } } - let optional = (. key, decode) => { - if !(%raw("key in json")) { - None - } else { - try { - let value = decode(. %raw("json[key]")) - Some(value) - } catch { - | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) - } +let field = (key, decode) => + json => { + if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { + Error.expected("object", json) } - } - let required = (. key, decode) => { if !(%raw("key in json")) { throw(DecodeError(`${key} required`)) } - try decode(. %raw("json[key]")) catch { + try decode(%raw("json[key]")) catch { | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) } } - f({optional: optional, required: required}) -} - -let oneOf = decoders => (. json) => { - let errors = [] +let object = f => + json => { + if Js.typeof(json) != "object" || Js.Array.isArray(json) || Obj.magic(json) == Js.null { + throw(Error.expected("object", json)) + } - let rec loop = i => { - if i >= Array.length(decoders) { - throw( - DecodeError( - `All decoders given to oneOf failed. Here are all the errors:\n- ${errors->Js.Array2.joinWith( - "\n", - )}\nAnd the JSON being decoded: ${stringify(json)}`, - ), - ) + let optional = (key, decode) => { + if !(%raw("key in json")) { + None + } else { + try { + let value = decode(%raw("json[key]")) + Some(value) + } catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) + } + } } - let decode = Array.getUnsafe(decoders, i) - try decode(. json) catch { - | DecodeError(err) => - errors->Js.Array2.push(err)->ignore - loop(i + 1) + let required = (key, decode) => { + if !(%raw("key in json")) { + throw(DecodeError(`${key} required`)) + } + + try decode(%raw("json[key]")) catch { + | DecodeError(msg) => throw(DecodeError(`${msg}\n\tat field '${key}'`)) + } } + + f({optional, required}) } - loop(0) -} +let oneOf = decoders => + json => { + let errors = [] + + let rec loop = i => { + if i >= Array.length(decoders) { + throw( + DecodeError( + `All decoders given to oneOf failed. Here are all the errors:\n- ${errors->Js.Array2.joinWith( + "\n", + )}\nAnd the JSON being decoded: ${stringify(json)}`, + ), + ) + } + + let decode = Array.getUnsafe(decoders, i) + try decode(json) catch { + | DecodeError(err) => + errors->Js.Array2.push(err)->ignore + loop(i + 1) + } + } -let map = (decode, f) => (. json) => f(. decode(. json)) + loop(0) + } -let flatMap = (decodeA, f) => (. json) => { - let decodeB = f(. decodeA(. json)) - decodeB(. json) -} +let map = (decode, f) => json => f(decode(json)) + +let flatMap = (decodeA, f) => + json => { + let decodeB = f(decodeA(json)) + decodeB(json) + } -let indirect = f => (. json) => f()(. json) +let indirect = f => json => f()(json) let decode = (json, decode) => - try Ok(decode(. json)) catch { + try Ok(decode(json)) catch { | DecodeError(msg) => Error(msg) } diff --git a/src/Json_Decode.resi b/src/Json_Decode.resi index 55ef3bc..c2296bf 100644 --- a/src/Json_Decode.resi +++ b/src/Json_Decode.resi @@ -1,8 +1,8 @@ type t<'a> type fieldDecoders = { - optional: 'a. (. string, t<'a>) => option<'a>, - required: 'a. (. string, t<'a>) => 'a, + optional: 'a. (string, t<'a>) => option<'a>, + required: 'a. (string, t<'a>) => 'a, } exception DecodeError(string) @@ -11,7 +11,7 @@ module Error: { let expected: (string, Js.Json.t) => _ } -let custom: ((. Js.Json.t) => 'a) => t<'a> +let custom: (Js.Json.t => 'a) => t<'a> let id: t @@ -34,9 +34,9 @@ let dict: t<'a> => t> let field: (string, t<'a>) => t<'a> let oneOf: array> => t<'a> -let map: (t<'a>, (. 'a) => 'b) => t<'b> -let flatMap: (t<'a>, (. 'a) => t<'b>) => t<'b> +let map: (t<'a>, 'a => 'b) => t<'b> +let flatMap: (t<'a>, 'a => t<'b>) => t<'b> -let indirect: (() => t<'a>) => t<'a> +let indirect: (unit => t<'a>) => t<'a> let decode: (Js.Json.t, t<'a>) => result<'a, string> diff --git a/src/Json_Encode.res b/src/Json_Encode.res index 6c34bf5..eb8b999 100644 --- a/src/Json_Encode.res +++ b/src/Json_Encode.res @@ -16,43 +16,46 @@ external boolArray: array => Js.Json.t = "%identity" let array = encode => arr => arr->Js.Array2.map(x => encode(x))->jsonArray -let list = encode => l => - switch l { - | list{} => jsonArray([]) - | list{hd, ...tl} => - let arr = Array.make(~length=l->List.length, hd->encode) - let rec fill = (i, l) => - switch l { - | list{} => arr - | list{hd, ...tl} => - Array.setUnsafe(arr, i, hd->encode) - fill(i + 1, tl) - } - fill(1, tl)->jsonArray - } +let list = encode => + l => + switch l { + | list{} => jsonArray([]) + | list{hd, ...tl} => + let arr = Array.make(~length=l->List.length, hd->encode) + let rec fill = (i, l) => + switch l { + | list{} => arr + | list{hd, ...tl} => + Array.setUnsafe(arr, i, hd->encode) + fill(i + 1, tl) + } + fill(1, tl)->jsonArray + } let object = props => props->Js.Dict.fromArray->jsonDict -let option = encode => opt => - switch opt { - | None => null - | Some(v) => v->encode - } +let option = encode => + opt => + switch opt { + | None => null + | Some(v) => v->encode + } -let withDefault = (default, encode) => opt => - switch opt { - | None => default - | Some(v) => v->encode - } +let withDefault = (default, encode) => + opt => + switch opt { + | None => default + | Some(v) => v->encode + } let date = date => date->Js.Date.toJSONUnsafe->string let pair = (encodeA, encodeB) => ((a, b)) => [a->encodeA, b->encodeB]->jsonArray let tuple2 = (encodeA, encodeB) => ((a, b)) => [a->encodeA, b->encodeB]->jsonArray -let tuple3 = (encodeA, encodeB, encodeC) => ((a, b, c)) => - [a->encodeA, b->encodeB, c->encodeC]->jsonArray -let tuple4 = (encodeA, encodeB, encodeC, encodeD) => ((a, b, c, d)) => - [a->encodeA, b->encodeB, c->encodeC, d->encodeD]->jsonArray +let tuple3 = (encodeA, encodeB, encodeC) => + ((a, b, c)) => [a->encodeA, b->encodeB, c->encodeC]->jsonArray +let tuple4 = (encodeA, encodeB, encodeC, encodeD) => + ((a, b, c, d)) => [a->encodeA, b->encodeB, c->encodeC, d->encodeD]->jsonArray let dict = encode => dict => Js.Dict.map(v => encode(v), dict)->jsonDict