Skip to content

Commit

Permalink
Merge pull request #1 from riKiMasan/melange21
Browse files Browse the repository at this point in the history
Melange21
  • Loading branch information
rikimasan authored Dec 5, 2023
2 parents 61e4b87 + 5dbad10 commit 989d22b
Show file tree
Hide file tree
Showing 32 changed files with 5,230 additions and 36,611 deletions.
41 changes: 0 additions & 41 deletions .circleci/config.yml

This file was deleted.

47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
build:
name: Build and test the project
strategy:
matrix:
system:
- ubuntu-latest
node-version:
- 18.x
ocaml-compiler:
- 5.1.x

runs-on: ${{ matrix.system }}

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{matrix.node-version}}

- name: Use OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}

- name: Install all deps
run: make install

- name: Build the project
run: make build

- name: Run tests
run: make test-coverage

- name: Publish test report to Coveralls
uses: coverallsapp/github-action@v1
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ node_modules
_build/
_opam/
test/output/
/lib/bs
*.bs.js
/dist
.merlin
.bsb.lock
/website/build
/coverage

Expand Down
13 changes: 8 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
### Getting Started

You'll need to already have [Node.js](https://nodejs.org), [Opam](https://opam.ocaml.org/doc/Install.html), and `make`. These instructions also use `yarn` rather than `npm` for working with Node dependencies and scripts (`npm install -g yarn`).

1. Fork [this repo on Github](https://github.com/mlms13/bs-decode) and clone it locally
2. `npm install` to grab dependencies
3. `npm run cleanbuild && npm run test` to build and run tests
4. Make your changes (and add appropriate tests)
5. [Open a pull request](https://help.github.com/en/articles/about-pull-requests) with your changes
2. `make init` will configure your environment... this only needs to be done once
3. `make install` will install both `npm` and `opam` dependencies
4. `make build` or `make watch` to build the project and `make test` to run tests
5. Make your changes (and add appropriate tests)
6. [Open a pull request](https://help.github.com/en/articles/about-pull-requests) with your changes

### Code style and conventions

Expand All @@ -22,7 +25,7 @@ Also, please make sure that your code has been formatted with [`refmt`](https://

### Tests

`bs-decode` currently has 100% test coverage, and we hope to keep it that way. :) Running `npm run test` (or `jest --coverage`) will run your tests and give you a coverage report. You can see the detailed report in `./coverage/lcov-report/index.html`, which will help you track down any uncovered functions or branches.
`bs-decode` currently has 100% test coverage, and we hope to keep it that way. :) Running `make test-coverage` will run the tests and give you a coverage report. You can see the detailed report in `./coverage/lcov-report/index.html`, which will help you track down any uncovered functions or branches.

### Documentation

Expand Down
60 changes: 60 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
project_name = bs-decode

DUNE = opam exec -- dune

.DEFAULT_GOAL := help

.PHONY: help
help: ## Print this help message
@echo "List of available make commands";
@echo "";
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}';
@echo "";

.PHONY: create-switch
create-switch: ## Create opam switch
opam switch create . -y --deps-only

.PHONY: init
init: create-switch install ## Configure everything to develop this repository in local

.PHONY: install
install: ## Install development dependencies
$(DUNE) build @install
yarn install ## install JavaScript packages that the project might depend on, like `react` or `react-dom`
opam update ## make sure that opam has the latest information about published libraries in the opam repository https://opam.ocaml.org/packages/
opam install -y . --deps-only --with-test ## install the Melange and OCaml dependencies
opam exec opam-check-npm-deps ## check that the versions of the JavaScript packages installed match the requirements defined by Melange libraries

.PHONY: build
build: ## Build the project
$(DUNE) build @main

.PHONY: watch
watch: ## Watch for the filesystem and rebuild on every change
$(DUNE) build --watch @main

.PHONY: clean
clean: ## Clean build artifacts and other generated files
rm test/output/test/utils/BigJson.json
$(DUNE) clean

.PHONY: copy-test-json
copy-test-json: ## Copy test json files to the right place
cp test/utils/BigJson.json test/output/test/utils/BigJson.json

.PHONY: test
test: copy-test-json
yarn test

.PHONY: test-coverage
test-coverage: copy-test-json
yarn test --coverage

.PHONY: format
format: ## Format the codebase with ocamlformat
$(DUNE) build @fmt --auto-promote

.PHONY: format-check
format-check: ## Checks if format is correct
$(DUNE) build @fmt
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@ Decode JSON values into structured ReasonML and OCaml types. Inspired by Elm's [

## Installation

**Install via npm:**
**Install:**

`npm install --save bs-decode relude bs-bastet`
`yarn add bs-decode relude bs-bastet`

**Update your bsconfig.json**
**Add the library stanzas in your dune file**

If you're using [dune](https://dune.build/) to build your project, add a [library stanza](https://dune.readthedocs.io/en/stable/dune-files.html#library) to tell dune about `bs-decode`. You'll need to add similar library stanzas for `bsBastet` and `relude` if you haven't already.

```
"bs-dependencies": [
"bs-bastet",
"bs-decode",
"relude"
],
(subdir
node_modules/bs-decode/src
(library
(name bsDecode)
(modes melange)
(libraries bsBastet relude)))
```


## Usage

The following is available to give you an idea of how the library works, but [the complete documentation](https://mlms13.github.io/bs-decode/docs/simple-example) will probably be more useful if you want to write your own decoders.
Expand Down
41 changes: 41 additions & 0 deletions bs-decode.opam
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Type-safe JSON decoding for ReasonML and OCaml"
description: "Type-safe JSON decoding for ReasonML and OCaml"
maintainer: ["Michael Martin"]
authors: ["Michael Martin"]
license: "MIT"
homepage: "https://github.com/mlms13/bs-decode"
bug-reports: "https://github.com/mlms13/bs-decode/issues"
depends: [
"dune" {>= "3.8"}
"dot-merlin-reader"
"melange" {>= "2.0.0"}
"ocaml" {>= "5.1.0"}
"reason" {>= "3.10.0"}
"ocaml-lsp-server"
"relude"
"bastet"
"melange-jest" {>= "0.1.0"}
"opam-check-npm-deps"
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/mlms13/bs-decode.git"
pin-depends: [
[ "relude.dev" "git+https://github.com/reazen/relude.git#v2" ]
[ "bastet.dev" "git+https://github.com/johnhaley81/bastet.git#6c8f53a9da55254691df49bddf96b279b38be204" ]
]
4 changes: 4 additions & 0 deletions bs-decode.opam.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pin-depends: [
[ "relude.dev" "git+https://github.com/reazen/relude.git#v2" ]
[ "bastet.dev" "git+https://github.com/johnhaley81/bastet.git#6c8f53a9da55254691df49bddf96b279b38be204" ]
]
27 changes: 0 additions & 27 deletions bsconfig.json

This file was deleted.

49 changes: 5 additions & 44 deletions docs/decoding-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ let make = (name, age, isAdmin, lastLogin) =>

...the real goal of `bs-decode` is to give you the tools you need to build up complex record types (like this one) from JSON. You can certainly use `field` and `optionalField` to piece these things together, but the following approaches will make your life easier.

### Let-Ops (Coming Soon)
### Let-Ops

In the very near future, `bs-decode` will be switching from BuckleScript to Melange. This will give us access to newer OCaml features, such as [binding operators](https://v2.ocaml.org/manual/bindingops.html). This dramatically simplifies the syntax for decoding and constructing complex objects:
With the switch to Melange, `bs-decode` now has access to newer OCaml features, such as [binding operators](https://v2.ocaml.org/manual/bindingops.html). This dramatically simplifies the syntax for decoding and constructing complex objects:

```reasonml
let decode = {
Expand All @@ -64,15 +64,15 @@ let decode = {
and+ age = field("age", intFromNumber)
and+ isAdmin = field("isAdmin", boolean)
and+ lastLogin = optionalField("lastLogin", date);
User.make(name, age, isAdmin, lastLogin);
{ name, age, isAdmin, lastLogin };
};
```

Once available, this will replace the "Pipeline" decoding (see below). Unlike the other strategies outlined below, the order of the field decoders doesn't matter. It's much easier to see how each field is used in the constructor, and it works with labeled functions and literal record construction.
This is the preferred method of decoding JSON into Reason records, as it allows constructing tuples, records, and calling functions with labeled arguments.

### Haskell Validation Style

It's also possible to use `map` and `apply` functions (often in their infix form `<$>` and `<*>`) to build up a larger decoder from smaller ones. This style my look more familiar if you've used validation libraries in Haskell.
It's also possible to use `map` and `apply` functions (often in their infix form `<$>` and `<*>`) to build up a larger decoder from smaller ones. This style my look more familiar if you've used validation libraries in Haskell. Importantly, this will not work if `User.make` expects labeled arguments, and it's important to decode the fields in the same order that `User.make` expects to receive its arguments.

```reasonml
let ((<$>), (<*>)) = Decode.(map, apply);
Expand All @@ -86,42 +86,3 @@ let decode =
<*> optionalField("lastLogin", date)
);
```

### Combining Decoders with `mapN`

The provided `map2`...`map5` functions can be used to take the results of up to 5 decoders and combine them using a function that receives the up-to-5 values if all decoders succeed. This is simple to use, but obviously limiting if the record you want to construct has more than 5 fields.

```reasonml
let decode =
Decode.(
map4(
User.make,
field("name", string),
field("age", intFromNumber),
field("isAdmin", boolean),
optionalField("lastLogin", date),
)
);
```

### Pipeline-Style (Deprecated)

**Note:** This style of decoding has been deprecated and will be removed in v2.0.

Given the `user` type above and its `make` function, you can build up a record by decoding each field in a style inspired by the [Elm Decode Pipeline](https://package.elm-lang.org/packages/NoRedInk/elm-decode-pipeline/3.0.1/) library for Elm.

The order of decoded fields is significant, as the pipeline leverages the partial application of the `make` function. Each `field` or `optionalField` line in the example below fills in the next available slot in the `make` function.

```reasonml
let decode = json =>
Decode.Pipeline.(
succeed(make)
|> field("name", string)
|> field("age", intFromNumber)
|> field("isAdmin", boolean)
|> optionalField("lastLogin", date)
|> run(json)
);
```

Unlike other decode functions we've looked at, the Pipeline style is not eager. Instead, nothing will be decoded until the whole pipeline is executed by using the `run` function with the appropriate JSON.
Loading

0 comments on commit 989d22b

Please sign in to comment.