Skip to content

Commit

Permalink
Merge a18a51d into 61e4b87
Browse files Browse the repository at this point in the history
  • Loading branch information
mlms13 committed Nov 30, 2023
2 parents 61e4b87 + a18a51d commit ee9f9a9
Show file tree
Hide file tree
Showing 31 changed files with 5,193 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
@@ -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
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
@@ -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
@@ -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
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 pin -y add $(project_name).dev . ## somehow needed to get relude to show up in dune?
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
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
27 changes: 27 additions & 0 deletions bs-decode.opam
@@ -0,0 +1,27 @@
opam-version: "2.0"
synopsis: "BS Decode"
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: [
"dot-merlin-reader" {dev}
"dune" {>= "3.8"}
"melange" {>= "2.0.0"}
"ocaml" {>= "5.1.0"}
"reason" {>= "3.10.0" & < "4.0.0"}
"ocaml-lsp-server" {dev}
"ocamlformat" {dev}
"odoc" {with-doc}
"relude" {dev}
"bastet" {dev}
"melange-jest" {>= "0.1.0"}
"opam-check-npm-deps" {with-test}
]

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
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.
23 changes: 13 additions & 10 deletions docs/installation.md
Expand Up @@ -3,24 +3,27 @@ id: installation
title: Installation
---

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

```sh
npm install --save bs-decode
yarn add bs-decode
```

Note that `bs-decode` includes two `peerDependencies`. These are peers instead of regular dependencies to allow you to specify the version in one place so you're less likely to end up with conflicting versions nested in your `node_modules`. If you haven't already, you can install the peer dependencies like this:

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

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

```json
"bs-dependencies": [
"bs-bastet",
"bs-decode",
"relude"
],
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.

```
(subdir
node_modules/bs-decode/src
(library
(name bsDecode)
(modes melange)
(libraries bsBastet relude)))
```

0 comments on commit ee9f9a9

Please sign in to comment.