From 5defa56ef759457ef310249dafeaa2a3ae15795b Mon Sep 17 00:00:00 2001 From: joneshf Date: Mon, 7 Jul 2025 19:27:58 -0700 Subject: [PATCH 01/13] Setup `nix` and `direnv` We want to get back into developing in this repository. The issue is that things are so out of date that it's hard to do anything. We do what we should've done years ago, and setup `nix` and `direnv` here so that we can at least build stuff. This is mostly temporary until we get up to date on versions of things. So even if this doesn't work too well as-is, it hopefully won't be around for long. --- .envrc | 1 + .gitignore | 2 ++ flake.lock | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 2d96631..3be57df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ ### Project-specific ### +.direnv +.jj .psc-ide-port ################################################################################ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a50ed27 --- /dev/null +++ b/flake.lock @@ -0,0 +1,49 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1751413152, + "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "ref": "main", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..1ff2ef6 --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + description = "A data type for optional values"; + + inputs = { + flake-parts = { + inputs = { + nixpkgs-lib = { + follows = "nixpkgs"; + }; + }; + + owner = "hercules-ci"; + + ref = "main"; + + repo = "flake-parts"; + + type = "github"; + }; + + nixpkgs = { + owner = "NixOS"; + + ref = "nixos-unstable"; + + repo = "nixpkgs"; + + type = "github"; + }; + }; + + outputs = + inputs: + inputs.flake-parts.lib.mkFlake { inherit inputs; } { + perSystem = + { pkgs, ... }: + { + devShells = { + default = pkgs.mkShellNoCC { + nativeBuildInputs = [ + pkgs.coreutils + pkgs.findutils + pkgs.gnumake + pkgs.nodejs_22 + ]; + }; + }; + }; + + systems = [ + "x86_64-darwin" + "x86_64-linux" + ]; + }; +} From 7f76158730a98bc99a81c53b449351dbc131c639 Mon Sep 17 00:00:00 2001 From: joneshf Date: Mon, 7 Jul 2025 21:08:00 -0700 Subject: [PATCH 02/13] Support ARM platforms in `nix` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Times have moved on, and devices are using ARM more and more these days. In order to support that in this repository with the version of things we're using, we have to do a bit of work. The version of `purescript` we were using–0.14.0–does not have a pre-built ARM version. The `npm` package for `purescript` will fallback to building from source, but we have to make sure certain dependencies are available in order to do that. Since those dependencies are only necessary if we have to build from source, we make them conditional on the host platform of the system. Unfortunately even with those dependencies, we still cannot build things from source. The version of GHC that `purescript` 0.14.0 wants is 8.10.4, which is not available in the version of `stack`? we're using. We could go down to an older version of `nixpkgs`, but the alternative we decide on is to update the version of `purescript` to 0.14.9. This version of `purescript` requires a newer version of GHC that actually is available in the `stack`? we're using. All this stuff means we can now develop again in the year 2025! --- flake.nix | 25 +- package-lock.json | 890 ++++++++++++++++++++++++++++++---------------- 2 files changed, 607 insertions(+), 308 deletions(-) diff --git a/flake.nix b/flake.nix index 1ff2ef6..1278c62 100644 --- a/flake.nix +++ b/flake.nix @@ -37,17 +37,30 @@ { devShells = { default = pkgs.mkShellNoCC { - nativeBuildInputs = [ - pkgs.coreutils - pkgs.findutils - pkgs.gnumake - pkgs.nodejs_22 - ]; + nativeBuildInputs = + [ + pkgs.coreutils + pkgs.findutils + pkgs.gnumake + pkgs.nodejs_22 + ] + # The version of PureScript we use doesn't have pre-built binaries for ARM architectures. + # The `npm` package will fall back to building from source, + # but we need somre more dependencies in order to do that. + # We should be able to remove this once we update to at least version [0.15.9](https://github.com/purescript/purescript/releases/tag/v0.15.9) of PureScript, + # as this was the first version to start producing pre-built ARM binaries: https://github.com/purescript/purescript/pull/4455. + ++ pkgs.lib.lists.optionals pkgs.stdenv.hostPlatform.isAarch [ + pkgs.llvmPackages_12.libcxxClang + pkgs.llvmPackages_12.libllvm + pkgs.stack + ]; }; }; }; systems = [ + "aarch64-darwin" + "aarch64-linux" "x86_64-darwin" "x86_64-linux" ]; diff --git a/package-lock.json b/package-lock.json index d6ebcff..3532e3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,142 +1,195 @@ { "name": "purescript-option", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "ajv": { + "packages": { + "": { + "name": "purescript-option", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "bower": "^1.8.8", + "purescript": "^0.14.0", + "purescript-psa": "^0.8.2", + "purty": "^7.0.0" + } + }, + "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "ansi-escapes": { + "node_modules/ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "ansi-regex": { + "node_modules/ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "ansi-styles": { + "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "aproba": { + "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, - "arch": { + "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "asn1": { + "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, - "requires": { + "dependencies": { "safer-buffer": "~2.1.0" } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8" + } }, - "asynckit": { + "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "aws-sign2": { + "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "aws4": { + "node_modules/aws4": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "bcrypt-pbkdf": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "requires": { + "dependencies": { "tweetnacl": "^0.14.3" } }, - "bluebird": { + "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "bower": { + "node_modules/bower": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.12.tgz", "integrity": "sha512-u1xy9SrwwoPlgjuHNjhV+YUPVdqyBj2ALBxuzeIUKXaPI2i2xypGgxqXkuHcITGdi5yBj5JuXgyMvgiWiS1S3Q==", - "dev": true + "dev": true, + "bin": { + "bower": "bin/bower" + }, + "engines": { + "node": ">=0.10.0" + } }, - "brace-expansion": { + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "buffer-from": { + "node_modules/buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "byline": { + "node_modules/byline": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "cacache": { + "node_modules/cacache": { "version": "11.3.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", "dev": true, - "requires": { + "dependencies": { "bluebird": "^3.5.5", "chownr": "^1.1.1", "figgy-pudding": "^3.5.1", @@ -153,86 +206,99 @@ "y18n": "^4.0.0" } }, - "caseless": { + "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "chalk": { + "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "chownr": { + "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "cli-cursor": { + "node_modules/cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, - "requires": { + "dependencies": { "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "color-convert": { + "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { + "dependencies": { "color-name": "1.1.3" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combined-stream": { + "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "requires": { + "dependencies": { "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "concat-stream": { + "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, - "requires": { + "engines": [ + "node >= 0.8" + ], + "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, - "copy-concurrently": { + "node_modules/copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "deprecated": "This package is no longer supported.", "dev": true, - "requires": { + "dependencies": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", "iferr": "^0.1.5", @@ -241,110 +307,129 @@ "run-queue": "^1.0.0" } }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "cross-spawn": { + "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "requires": { + "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "cyclist": { + "node_modules/cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, - "dashdash": { + "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "delayed-stream": { + "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "duplexify": { + "node_modules/duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, - "requires": { + "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, - "ecc-jsbn": { + "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, - "requires": { + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "emoji-regex": { + "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "end-of-stream": { + "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "requires": { + "dependencies": { "once": "^1.4.0" } }, - "env-paths": { + "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "execa": { + "node_modules/execa": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", "dev": true, - "requires": { + "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", @@ -354,381 +439,462 @@ "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": "^8.12.0 || >=9.7.0" } }, - "extend": { + "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extsprintf": { + "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "dev": true, + "engines": [ + "node >=0.6.0" + ] }, - "fast-deep-equal": { + "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "figgy-pudding": { + "node_modules/figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "deprecated": "This module is no longer supported.", "dev": true }, - "filesize": { + "node_modules/filesize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-4.2.1.tgz", "integrity": "sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4.0" + } }, - "flush-write-stream": { + "node_modules/flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" } }, - "forever-agent": { + "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "form-data": { + "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, - "requires": { + "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" } }, - "from2": { + "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" } }, - "fs-minipass": { + "node_modules/fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, - "requires": { + "dependencies": { "minipass": "^2.6.0" } }, - "fs-write-stream-atomic": { + "node_modules/fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "deprecated": "This package is no longer supported.", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.2", "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "get-stream": { + "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, - "requires": { + "dependencies": { "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "getpass": { + "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" } }, - "glob": { + "node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "requires": { + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "graceful-fs": { + "node_modules/graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, - "har-schema": { + "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "har-validator": { + "node_modules/har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dev": true, - "requires": { + "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "http-signature": { + "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "iferr": { + "node_modules/iferr": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, - "imurmurhash": { + "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.19" + } }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "is-plain-obj": { + "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-stream": { + "node_modules/is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-typedarray": { + "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "isarray": { + "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isexe": { + "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isstream": { + "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "jsbn": { + "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "json-schema": { + "node_modules/json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stringify-safe": { + "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "jsprim": { + "node_modules/jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" } }, - "log-symbols": { + "node_modules/log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", "dev": true, - "requires": { + "dependencies": { "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" } }, - "log-update": { + "node_modules/log-update": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.4.0.tgz", "integrity": "sha512-ILKe88NeMt4gmDvk/eb615U/IVn7K9KWGkoYbdatQ69Z65nj1ZzjM6fHXfcs0Uge+e+EGnMW7DY4T9yko8vWFg==", "dev": true, - "requires": { + "dependencies": { "ansi-escapes": "^3.2.0", "cli-cursor": "^2.1.0", "wrap-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lru-cache": { + "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "requires": { + "dependencies": { "yallist": "^3.0.2" } }, - "merge-stream": { + "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "mime-db": { + "node_modules/mime-db": { "version": "1.47.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "mime-types": { + "node_modules/mime-types": { "version": "2.1.30", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "dev": true, - "requires": { + "dependencies": { "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" } }, - "mimic-fn": { + "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "minimatch": { + "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "minimist": { + "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "minipass": { + "node_modules/minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, - "minizlib": { + "node_modules/minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, - "requires": { + "dependencies": { "minipass": "^2.9.0" } }, - "mississippi": { + "node_modules/mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, - "requires": { + "dependencies": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", "end-of-stream": "^1.1.0", @@ -739,23 +905,30 @@ "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "mkdirp": { + "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "requires": { + "dependencies": { "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "move-concurrently": { + "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "deprecated": "This package is no longer supported.", "dev": true, - "requires": { + "dependencies": { "aproba": "^1.1.1", "copy-concurrently": "^1.0.0", "fs-write-stream-atomic": "^1.0.8", @@ -764,152 +937,179 @@ "run-queue": "^1.0.3" } }, - "ms": { + "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "npm-run-path": { + "node_modules/npm-run-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", "dev": true, - "requires": { + "dependencies": { "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "oauth-sign": { + "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "requires": { + "dependencies": { "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-finally": { + "node_modules/p-finally": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "parallel-transform": { + "node_modules/parallel-transform": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", "dev": true, - "requires": { + "dependencies": { "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { + "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "performance-now": { + "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "process-nextick-args": { + "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "promise-inflight": { + "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, - "psl": { + "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, - "pump": { + "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, - "requires": { + "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "pumpify": { + "node_modules/pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, - "requires": { + "dependencies": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" - }, + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "punycode": { + "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "purescript": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/purescript/-/purescript-0.14.1.tgz", - "integrity": "sha512-dh87XeDP/JGe/3DKBMglkRuIRfGLGkL8beuLIl9KemzckgyuD+j7VK15eVb9n5Exp3DIr6SNEuGG4FjuQQ7Rpg==", + "node_modules/purescript": { + "version": "0.14.9", + "resolved": "https://registry.npmjs.org/purescript/-/purescript-0.14.9.tgz", + "integrity": "sha512-r0J2JX/QuKYBSj8LDDYKQAY+tz/RtIm9erHrqWV7Y8RpUc6TZu14AxWcnSrohbBcEXImY/o0pMpouZrUeyriKQ==", "dev": true, - "requires": { + "hasInstallScript": true, + "license": "ISC", + "dependencies": { "purescript-installer": "^0.2.0" + }, + "bin": { + "purs": "purs.bin" } }, - "purescript-installer": { + "node_modules/purescript-installer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/purescript-installer/-/purescript-installer-0.2.5.tgz", "integrity": "sha512-fQAWWP5a7scuchXecjpU4r4KEgSPuS6bBnaP01k9f71qqD28HaJ2m4PXHFkhkR4oATAxTPIGCtmTwtVoiBOHog==", "dev": true, - "requires": { + "dependencies": { "arch": "^2.1.1", "byline": "^5.0.0", "cacache": "^11.3.2", @@ -930,32 +1130,52 @@ "tar": "^4.4.6", "which": "^1.3.1", "zen-observable": "^0.8.14" + }, + "bin": { + "install-purescript": "index.js" + }, + "engines": { + "node": ">=8.3.0" } }, - "purescript-psa": { + "node_modules/purescript-psa": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/purescript-psa/-/purescript-psa-0.8.2.tgz", "integrity": "sha512-4Olf0aQQrNCfcDLXQI3gJgINEQ+3U+4QPLmQ2LHX2L/YOXSwM7fOGIUs/wMm/FQnwERUyQmHKQTJKB4LIjE2fg==", - "dev": true + "dev": true, + "bin": { + "psa": "index.js" + } }, - "purty": { + "node_modules/purty": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/purty/-/purty-7.0.0.tgz", "integrity": "sha512-gHHghPEjRY39GUJ8KnOMRfPArJILGCXwEhX6BmEdNiLgZuCjLLBLyawGiKFjYMfy8H5Dsk5NbgwIGslrPrernA==", - "dev": true + "dev": true, + "os": [ + "linux", + "darwin", + "win32" + ], + "bin": { + "purty": "bin/purty.js" + } }, - "qs": { + "node_modules/qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "readable-stream": { + "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, - "requires": { + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -965,12 +1185,13 @@ "util-deprecate": "~1.0.1" } }, - "request": { + "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, - "requires": { + "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", @@ -991,92 +1212,112 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" } }, - "restore-cursor": { + "node_modules/restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, - "requires": { + "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - } + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "rimraf": { + "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "requires": { + "dependencies": { "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "run-queue": { + "node_modules/run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, - "requires": { + "dependencies": { "aproba": "^1.1.1" } }, - "safe-buffer": { + "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "safer-buffer": { + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "shebang-command": { + "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "requires": { + "dependencies": { "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "shebang-regex": { + "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "sshpk": { + "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, - "requires": { + "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -1086,83 +1327,103 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" } }, - "ssri": { + "node_modules/ssri": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", "dev": true, - "requires": { + "dependencies": { "figgy-pudding": "^3.5.1" } }, - "stream-each": { + "node_modules/stream-each": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", "dev": true, - "requires": { + "dependencies": { "end-of-stream": "^1.1.0", "stream-shift": "^1.0.0" } }, - "stream-shift": { + "node_modules/stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, - "string-width": { + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "strip-final-newline": { + "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "tar": { + "node_modules/tar": { "version": "4.4.13", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, - "requires": { + "dependencies": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", "minipass": "^2.8.6", @@ -1170,144 +1431,169 @@ "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" } }, - "through2": { + "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, - "requires": { + "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, - "tough-cookie": { + "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, - "requires": { + "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" } }, - "tunnel-agent": { + "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "tweetnacl": { + "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "typedarray": { + "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "unique-filename": { + "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, - "requires": { + "dependencies": { "unique-slug": "^2.0.0" } }, - "unique-slug": { + "node_modules/unique-slug": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, - "requires": { + "dependencies": { "imurmurhash": "^0.1.4" } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.0" } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { + "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } }, - "verror": { + "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "which": { + "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4" + } }, - "y18n": { + "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, - "yallist": { + "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "zen-observable": { + "node_modules/zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", From 1d12aa73ef786dde445d1de942a7b41bc62e226d Mon Sep 17 00:00:00 2001 From: joneshf Date: Thu, 10 Jul 2025 06:48:13 -0700 Subject: [PATCH 03/13] Fix compiler warnings There's two things we fix in this change: - Ignore third-party dependency warnings. - Remove erroneous `compile` flag. We cannot do anything about what some third-party dependency is doing in this repository. There's no need to surface their warnings to us, so we ignore them. We also were erroneously passing `compile` to `psa`. That isn't how that command works. So we remove `compile`. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3742006..4420a4f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BOWER := npx bower BOWER_FLAGS ?= -COMPILE_FLAGS ?= +COMPILE_FLAGS ?= --censor-lib DEPENDENCIES := 'bower_components/purescript-*/src/**/*.purs' NODE := node NPM := npm @@ -19,12 +19,12 @@ TEST_OUTPUTS := $(patsubst $(TEST).%.purs,$(OUTPUT)/%/index.js,$(subst /,.,$(TES define SRC_OUTPUT_RULE $(patsubst $(SRC).%.purs,$(OUTPUT)/%/index.js,$(subst /,.,$(1))): $(1) bower_components - $(PSA) compile $(COMPILE_FLAGS) $(DEPENDENCIES) $(SRCS) + $(PSA) $(COMPILE_FLAGS) $(DEPENDENCIES) $(SRCS) endef define TEST_OUTPUT_RULE $(patsubst $(TEST).%.purs,$(OUTPUT)/%/index.js,$(subst /,.,$(1))): $(1) $(SRC_OUTPUTS) bower_components - $(PSA) compile $(COMPILE_FLAGS) $(DEPENDENCIES) $(SRCS) $(TESTS) + $(PSA) $(COMPILE_FLAGS) $(DEPENDENCIES) $(SRCS) $(TESTS) endef $(foreach source, $(SRCS), $(eval $(call SRC_OUTPUT_RULE, $(source)))) From 47589eefffedff9d69b6a1e3cd11e39ef8116e70 Mon Sep 17 00:00:00 2001 From: joneshf Date: Tue, 8 Jul 2025 07:56:29 -0700 Subject: [PATCH 04/13] Check lints and formatting with `nix` We move over to using `nix` for formatting and linting. We also setup some pre-commit and pre-push hooks to validate this stuff. We only add the formatters and linters that pass without requiring a change. We'll add more stuff in separate changes, so we can have a smaller, more manageable diff. Unfortunately (or maybe fortunately?) we cannot use `purty` anymore. The developer *cough* hasn't made ARM binaries available, and we're not going to try to figure out how to build it. More than that, it doesn't support 0.15.x syntax. We're going to move on to the currently maintained PureScript formatter in a future change. For now, we remove it from the `Makefile`. We also add a `lint` recipe in the `Makefile`. This gets added as a dependency to `test`, since we generally want to make sure that the lints pass when testing as well. --- Makefile | 13 +++--- flake.lock | 85 +++++++++++++++++++++++++++++++++++++- flake.nix | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 208 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 4420a4f..fbcfba6 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,12 @@ BOWER := npx bower BOWER_FLAGS ?= COMPILE_FLAGS ?= --censor-lib DEPENDENCIES := 'bower_components/purescript-*/src/**/*.purs' +NIX := nix NODE := node NPM := npm OUTPUT := output PSA := npx psa PURS := npx purs -PURTY := npx purty REPL_FLAGS ?= SRC := src TEST := test @@ -61,9 +61,12 @@ clean: output .PHONY: format -format: node_modules - find $(SRC) -name '*.purs' -exec $(PURTY) --write {} \; - find $(TEST) -name '*.purs' -exec $(PURTY) --write {} \; +format: + $(NIX) fmt + +.PHONE: lint +lint: + $(NIX) flake check node_modules: package.json $(NPM) install @@ -74,7 +77,7 @@ repl: bower_components $(PURS) repl $(REPL_FLAGS) $(DEPENDENCIES) $(SRCS) .PHONY: test -test: $(OUTPUT)/test.js bower_components $(SRC_OUTPUTS) $(TEST_OUTPUTS) +test: $(OUTPUT)/test.js bower_components $(SRC_OUTPUTS) $(TEST_OUTPUTS) lint $(NODE) $< .PHONY: variables diff --git a/flake.lock b/flake.lock index a50ed27..94d6d1b 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -21,6 +37,50 @@ "type": "github" } }, + "git-hooks_nix": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "master", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks_nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1751792365, @@ -40,7 +100,30 @@ "root": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs" + "git-hooks_nix": "git-hooks_nix", + "nixpkgs": "nixpkgs", + "treefmt-nix": "treefmt-nix" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750931469, + "narHash": "sha256-0IEdQB1nS+uViQw4k3VGUXntjkDp7aAlqcxdewb/hAc=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "ac8e6f32e11e9c7f153823abc3ab007f2a65d3e1", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "treefmt-nix", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 1278c62..fe09996 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,22 @@ type = "github"; }; + git-hooks_nix = { + inputs = { + nixpkgs = { + follows = "nixpkgs"; + }; + }; + + owner = "cachix"; + + ref = "master"; + + repo = "git-hooks.nix"; + + type = "github"; + }; + nixpkgs = { owner = "NixOS"; @@ -27,16 +43,51 @@ type = "github"; }; + + treefmt-nix = { + inputs = { + nixpkgs = { + follows = "nixpkgs"; + }; + }; + + owner = "numtide"; + + ref = "main"; + + repo = "treefmt-nix"; + + type = "github"; + }; }; outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ + # The `git-hooks_nix` module will play nicely with the `treefmt-nix` module. + # It will take the configuration we supply, + # and use it appropriately instead of competing with it. + inputs.git-hooks_nix.flakeModule + # The `treefmt-nix` module will set the `formatter` to `treefmt`. + # This lets `nix fmt` use our configuration for `treefmt`. + inputs.treefmt-nix.flakeModule + ]; + perSystem = - { pkgs, ... }: + { config, pkgs, ... }: { devShells = { default = pkgs.mkShellNoCC { + inputsFrom = [ + # Include the shell from `git-hooks_nix`. + # This makes all `pre-commit` binaries (include `pre-commit`) available in the shell. + config.pre-commit.devShell + # Include the shell from `treefmt`. + # This makes all `treefmt` binaries (including `treefmt`) available in the shell. + config.treefmt.build.devShell + ]; + nativeBuildInputs = [ pkgs.coreutils @@ -56,6 +107,70 @@ ]; }; }; + + pre-commit = { + settings = { + default_stages = [ + "pre-commit" + "pre-push" + ]; + + hooks = { + # Check Nix code for anything that is unused. + deadnix = { + enable = true; + }; + + # Check that we're not accidentally committing AWS credentials. + detect-aws-credentials = { + enable = true; + }; + + # Check that we're not accidentally committing private keys + detect-private-keys = { + enable = true; + }; + + # Git submodules are nothing but a can of worms that fails in some non-obvious way each time they're used. + forbid-new-submodules = { + enable = true; + }; + + # While `nil` is a language server, + # it also has come static analysis we want to check. + nil = { + enable = true; + }; + }; + }; + }; + + treefmt = { + programs = { + # Format JSON code consistently. + jsonfmt = { + enable = true; + }; + + # Format Nix code consistently. + nixfmt = { + enable = true; + }; + + # Format Shell code consistently. + shfmt = { + enable = true; + }; + }; + + settings.global.excludes = [ + ".direnv/*" + ".jj/*" + "bower_components/*" + "node_modules/*" + "output/*" + ]; + }; }; systems = [ From 179a7ebb298c4051152f3835e43b06e890b98e26 Mon Sep 17 00:00:00 2001 From: joneshf Date: Tue, 8 Jul 2025 07:56:29 -0700 Subject: [PATCH 05/13] Enable `typos` linter We've got a couple of typos in some comments. We enable the `typos` linter to catch this stuff so it doesn't linger for years (like the current typos). --- flake.nix | 7 +++++++ src/Option.purs | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index fe09996..128ab18 100644 --- a/flake.nix +++ b/flake.nix @@ -141,6 +141,13 @@ nil = { enable = true; }; + + # Check that we're not making any simple typos in prose. + # This checks not just plain text files (like Markdown), + # but also comments in source code like this comment you're reading right now. + typos = { + enable = true; + }; }; }; }; diff --git a/src/Option.purs b/src/Option.purs index 919a13e..81399b7 100644 --- a/src/Option.purs +++ b/src/Option.purs @@ -1169,7 +1169,7 @@ else instance getOptionConsValue :: -- | someRecord = Option.getAll' someOption -- | ``` -- | --- | This can also be roughtly thought of as a monomorphic `Data.Traversable.sequence`. +-- | This can also be roughly thought of as a monomorphic `Data.Traversable.sequence`. class GetAll (option :: Row Type) (record :: Row Type) | option -> record where -- | Attempts to fetch all of the values from all of the keys of an option. -- | @@ -1194,7 +1194,7 @@ class GetAll (option :: Row Type) (record :: Row Type) | option -> record where Option option -> Data.Maybe.Maybe (Prim.Record record) --- | This instancce converts an `Option _` to a `Maybe (Record _)`. +-- | This instance converts an `Option _` to a `Maybe (Record _)`. -- | -- | If every key exists in the option, the record of values is returned in `Just _`. -- | From c86414b8a3ffb9934dcc78bb781e1ba6821fc851 Mon Sep 17 00:00:00 2001 From: joneshf Date: Sat, 12 Jul 2025 21:05:47 -0700 Subject: [PATCH 06/13] Enable `shellcheck` We want to catch any issues with Shell code. `shellcheck` tends to be way more useful than some other linters, given just how easy it is to do the wrong with with Bash. Hopefully it will also pay off if we write more Shell code. --- .envrc | 1 + flake.nix | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.envrc b/.envrc index 3550a30..0f94eed 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ +# shellcheck shell=bash use flake diff --git a/flake.nix b/flake.nix index 128ab18..bcab90c 100644 --- a/flake.nix +++ b/flake.nix @@ -142,6 +142,11 @@ enable = true; }; + # Check for any common mistakes in Shell code we write. + shellcheck = { + enable = true; + }; + # Check that we're not making any simple typos in prose. # This checks not just plain text files (like Markdown), # but also comments in source code like this comment you're reading right now. From 4b958381106dd67a9beb47b80799c0e9c5b5fdce Mon Sep 17 00:00:00 2001 From: joneshf Date: Tue, 8 Jul 2025 07:56:29 -0700 Subject: [PATCH 07/13] Enable `markdownlint` We've got quite a bit of Markdown in this repo. We want to make sure we're linting it properly, so we enable the `markdownlint` linter. It catches a few violations, so we fix those. --- README.md | 14 ++++++++++++++ flake.nix | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/README.md b/README.md index 7243586..9b6a711 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ With the `greeting` function, we can pass in an option and alter the behavior: We've allowed people to override the behavior of the function with optional values! It might be instructive to compare how we might write a similar function using a `Record _` instead of `Option _`: + ```PureScript greeting' :: Record ( name :: Data.Maybe.Maybe String, title :: Data.Maybe.Maybe String ) -> @@ -110,6 +111,7 @@ To implement `greeting'`, nothing really changed. We used the built-in dot operator to fetch the keys out of the record, but we could have just as easily used `Record.get` (which would have highlighted the similarlities even more). To use `greeting'`, we force the users of `greeting'` to do always give us a value in the record: + ```PureScript > User.greeting' { name: Data.Maybe.Nothing, title: Data.Maybe.Nothing } "Hello, World" @@ -215,6 +217,7 @@ With the `greeting` function, we can pass in an option and alter the behavior: We've allowed people to override the behavior of the function with optional values! It might be instructive to compare how we might write a similar function using a `Record _` instead of `Option _`: + ```PureScript greeting' :: Record ( name :: String, title :: Data.Maybe.Maybe String ) -> @@ -232,6 +235,7 @@ We don't have to convert down to a language-level Record because the argument is That's the only difference as far as implementing `greeting'`. To use `greeting'`, we force the users of `greeting'` to do always give us a value in the record: + ```PureScript > User.greeting' { name: "Pat", title: Data.Maybe.Nothing } "Hello, Pat" @@ -318,6 +322,7 @@ parse string = case Data.Argonaut.Parser.jsonParser string of ``` We can give that a spin with some different JSON values: + ```PureScript > parse """{}""" (Right (Option.fromRecord {})) @@ -416,6 +421,7 @@ Unless both fields exist, we cannot decode the JSON object. Similarly, no matter what the values are, we always encode them into a JSON object. In order to emulate the behavior of an optional field, we have to name the record, and write our own instances: + ```PureScript newtype Greeting = Greeting @@ -834,6 +840,7 @@ writeJSON = Simple.JSON.writeJSON ``` We can give that a spin with some different JSON values: + ```PureScript > readJSON """{}""" (Right (Option.fromRecord {})) @@ -962,6 +969,7 @@ parse string = case Data.Argonaut.Parser.jsonParser string of ``` We can give that a spin with some different JSON values: + ```PureScript > parse """{}""" (Left "An error occurred while decoding a JSON value:\n At object key 'name':\n No value was found.") @@ -1050,6 +1058,7 @@ Unless both fields exist, we cannot decode the JSON object. Similarly, no matter what the values are, we always encode them into a JSON object. In order to emulate the behavior of an optional field, we have to name the record, and write our own instances: + ```PureScript import Prelude import Data.Argonaut.Core as Data.Argonaut.Core @@ -1495,6 +1504,7 @@ writeJSON = Simple.JSON.writeJSON ``` We can give that a spin with some different JSON values: + ```PureScript > parse """{}""" (Left "Error at property \"name\": Type mismatch: expected String, found Undefined") @@ -1585,6 +1595,7 @@ For instance, constructing a `Data.DateTime.DateTime` can be done by passing in The issue is, how do we construct a `Data.Date.Date` or `Data.Time.Time`. One way to get construct these values is to use the `Data.Enum.Enum` instance for both of them: + ```PureScript > Data.DateTime.DateTime bottom bottom (DateTime (Date (Year -271820) January (Day 1)) (Time (Hour 0) (Minute 0) (Second 0) (Millisecond 0))) @@ -1731,10 +1742,13 @@ E.g. `FromRecord () () ( name :: String )` says that the `Record ()` has no fiel Since there is syntax for creating records, but no syntax for creating options, this typeclass can be useful for providing an easier to use interface to options. E.g. Someone can say: + ```PureScript Option.fromRecord' { foo: true, bar: 31 } ``` + Instead of having to say: + ```PureScript Option.insert (Data.Symbol.SProxy :: _ "foo") diff --git a/flake.nix b/flake.nix index bcab90c..ee822ba 100644 --- a/flake.nix +++ b/flake.nix @@ -136,6 +136,25 @@ enable = true; }; + # Check markdown files for consistency. + markdownlint = { + enable = true; + + settings = { + configuration = { + MD013 = { + # We'd like to use something like `wrap:inner-sentence`: + # https://cirosantilli.com/markdown-style-guide/#option-wrap-inner-sentence, + # or something related to SemBr: https://sembr.org/. + # But that's stymied in an issue: https://github.com/DavidAnson/markdownlint/issues/298. + # + # We set the line length to something large enough to not get hit by it regularly. + line_length = 1000; + }; + }; + }; + }; + # While `nil` is a language server, # it also has come static analysis we want to check. nil = { From c38acd9fd5798d52bd186f609b9d83cf59ba566d Mon Sep 17 00:00:00 2001 From: joneshf Date: Tue, 8 Jul 2025 07:56:29 -0700 Subject: [PATCH 08/13] Enable `mdformat` To make dealing with `markdownlint` a little easier, and to have consistent formatting for Markdown, we enable `mdformat` as a formatter. We also update the Markdown files to use this new formatting. --- README.md | 26 +++++++++++++------------- flake.nix | 5 +++++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9b6a711..9a2bf9d 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,19 @@ A data type for optional values. ## Table of Contents -* [Explanation: Motivation for `Option _`](#explanation-motivation-for-option-_) -* [How To: Make a function with optional values](#how-to-make-a-function-with-optional-values) -* [How To: Make a function with optional values from a record](#how-to-make-a-function-with-optional-values-from-a-record) -* [How To: Make a function with required and optional values](#how-to-make-a-function-with-required-and-optional-values) -* [How To: Make a function with required and optional values from a record](#how-to-make-a-function-with-required-and-optional-values-from-a-record) -* [How To: Decode and Encode JSON with optional values in `purescript-argonaut`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-argonaut) -* [How To: Decode and Encode JSON with optional values in `purescript-codec-argonaut`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-codec-argonaut) -* [How To: Decode and Encode JSON with optional values in `purescript-simple-json`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-simple-json) -* [How To: Decode and Encode JSON with required and optional values in `purescript-argonaut`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-argonaut) -* [How To: Decode and Encode JSON with required and optional values in `purescript-codec-argonaut`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-codec-argonaut) -* [How To: Decode and Encode JSON with required and optional values in `purescript-simple-json`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-simple-json) -* [How To: Provide an easier API for `DateTime`](#how-to-provide-an-easier-api-for-datetime) -* [Reference: `FromRecord _ _ _`](#reference-fromrecord-_-_-_) +- [Explanation: Motivation for `Option _`](#explanation-motivation-for-option-_) +- [How To: Make a function with optional values](#how-to-make-a-function-with-optional-values) +- [How To: Make a function with optional values from a record](#how-to-make-a-function-with-optional-values-from-a-record) +- [How To: Make a function with required and optional values](#how-to-make-a-function-with-required-and-optional-values) +- [How To: Make a function with required and optional values from a record](#how-to-make-a-function-with-required-and-optional-values-from-a-record) +- [How To: Decode and Encode JSON with optional values in `purescript-argonaut`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-argonaut) +- [How To: Decode and Encode JSON with optional values in `purescript-codec-argonaut`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-codec-argonaut) +- [How To: Decode and Encode JSON with optional values in `purescript-simple-json`](#how-to-decode-and-encode-json-with-optional-values-in-purescript-simple-json) +- [How To: Decode and Encode JSON with required and optional values in `purescript-argonaut`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-argonaut) +- [How To: Decode and Encode JSON with required and optional values in `purescript-codec-argonaut`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-codec-argonaut) +- [How To: Decode and Encode JSON with required and optional values in `purescript-simple-json`](#how-to-decode-and-encode-json-with-required-and-optional-values-in-purescript-simple-json) +- [How To: Provide an easier API for `DateTime`](#how-to-provide-an-easier-api-for-datetime) +- [Reference: `FromRecord _ _ _`](#reference-fromrecord-_-_-_) ## Explanation: Motivation for `Option _` diff --git a/flake.nix b/flake.nix index ee822ba..ebd5c2e 100644 --- a/flake.nix +++ b/flake.nix @@ -183,6 +183,11 @@ enable = true; }; + # Format Markdown code consistently. + mdformat = { + enable = true; + }; + # Format Nix code consistently. nixfmt = { enable = true; From 9c119638e5821531556cfe50fd4ef7880c6fb681 Mon Sep 17 00:00:00 2001 From: joneshf Date: Thu, 10 Jul 2025 18:39:59 -0700 Subject: [PATCH 09/13] Migrate to `purs-tidy` Since `purty` is deprecated it in favor of `purs-tidy` (I did mention this in like the old PS Slack or something at some point, but should probably make it explicit in the repository) we migrate over to `purs-tidy`. There are some minor differences in formatting, but that doesn't really matter. Formatting has never been about doing things "my way." But about having _something_ format the code so we Humans don't have to think about it. --- .tidyrc.json | 10 ++ flake.nix | 7 ++ package-lock.json | 18 ++-- package.json | 2 +- src/Option.purs | 58 ++++++------ ...ithOptionalValuesInPureScriptArgonaut.purs | 6 +- ...tionalValuesInPureScriptCodecArgonaut.purs | 8 +- ...hOptionalValuesInPureScriptSimpleJSON.purs | 4 +- ...AndOptionalValuesInPureScriptArgonaut.purs | 6 +- ...tionalValuesInPureScriptCodecArgonaut.purs | 8 +- ...dOptionalValuesInPureScriptSimpleJSON.purs | 6 +- ...HowTo.MakeAFunctionWithOptionalValues.purs | 2 +- ...FunctionWithOptionalValuesFromARecord.purs | 4 +- ...FunctionWithRequiredAndOptionalValues.purs | 4 +- ...hRequiredAndOptionalValuesFromARecord.purs | 6 +- test/HowTo.ProvideAnEasierAPIForDateTime.purs | 18 ++-- test/Test.Main.purs | 3 +- test/Test.Option.purs | 93 +++++++++---------- 18 files changed, 138 insertions(+), 125 deletions(-) create mode 100644 .tidyrc.json diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 0000000..edcadc3 --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "source", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "last", + "unicode": "never", + "width": null +} diff --git a/flake.nix b/flake.nix index ebd5c2e..e55e6f5 100644 --- a/flake.nix +++ b/flake.nix @@ -193,6 +193,13 @@ enable = true; }; + # Format PureScript code consistently. + purs-tidy = { + enable = true; + + includes = [ "*.purs" ]; + }; + # Format Shell code consistently. shfmt = { enable = true; diff --git a/package-lock.json b/package-lock.json index 3532e3f..01775d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "bower": "^1.8.8", "purescript": "^0.14.0", "purescript-psa": "^0.8.2", - "purty": "^7.0.0" + "purs-tidy": "^0.11.0" } }, "node_modules/ajv": { @@ -1147,18 +1147,14 @@ "psa": "index.js" } }, - "node_modules/purty": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/purty/-/purty-7.0.0.tgz", - "integrity": "sha512-gHHghPEjRY39GUJ8KnOMRfPArJILGCXwEhX6BmEdNiLgZuCjLLBLyawGiKFjYMfy8H5Dsk5NbgwIGslrPrernA==", + "node_modules/purs-tidy": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/purs-tidy/-/purs-tidy-0.11.0.tgz", + "integrity": "sha512-HZ8AS6J7Ka2YVl6Gr/H5NV17TU10yGYUTxVwRd5tKuwsVdFZewXSzZ/HTpWrkhdR2gxSVk0BdnpJhyu//oRc+w==", "dev": true, - "os": [ - "linux", - "darwin", - "win32" - ], + "license": "MIT", "bin": { - "purty": "bin/purty.js" + "purs-tidy": "bin/index.js" } }, "node_modules/qs": { diff --git a/package.json b/package.json index b7d7bea..7adbbed 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,6 @@ "bower": "^1.8.8", "purescript": "^0.14.0", "purescript-psa": "^0.8.2", - "purty": "^7.0.0" + "purs-tidy": "^0.11.0" } } diff --git a/src/Option.purs b/src/Option.purs index 81399b7..eadc0cf 100644 --- a/src/Option.purs +++ b/src/Option.purs @@ -157,13 +157,11 @@ import Unsafe.Coerce as Unsafe.Coerce -- | A collection of key/value pairs where any key and value may or may not exist. -- | E.g. `Option (foo :: Boolean, bar :: Int)` means that either only `foo` exists with a value, only `bar` exists with a value, both `foo` and `bar` exist with values, or neither `foo` nor `bar` exist. -newtype Option (row :: Row Type) - = Option (Foreign.Object.Object (forall a. a)) +newtype Option (row :: Row Type) = Option (Foreign.Object.Object (forall a. a)) -- A local proxy for `Prim.RowList.RowList` so as not to impose a hard requirement on `Type.Data.RowList.RLProxy` in the typeclasses we define. -- `Type.Data.RowList.RLProxy` can still be used by callers, but it's not a requirement. -data Proxy (list :: Prim.RowList.RowList Type) - = Proxy +data Proxy (list :: Prim.RowList.RowList Type) = Proxy -- | This instance ignores keys that do not exist in the given JSON object. -- | @@ -274,8 +272,7 @@ instance writeForeignOptionOption :: -- | A combination of both language-level records and options. -- | E.g. `Option.Record (foo :: Boolean) (bar :: Int)` means that `foo` exists with a value all of the time, and either `bar` exists with a value or `bar` doesn't exist with a value. -newtype Record (required :: Row Type) (optional :: Row Type) - = Record +newtype Record (required :: Row Type) (optional :: Row Type) = Record { required :: Prim.Record required , optional :: Option optional } @@ -1717,7 +1714,10 @@ else instance modifyOptionCons :: -- | A typeclass that iterates a `RowList` converting an `Option _` to a `Boolean`. class - (EqOption list option) <= OrdOption (list :: Prim.RowList.RowList Type) (option :: Row Type) | list -> option where + ( EqOption list option + ) <= + OrdOption (list :: Prim.RowList.RowList Type) (option :: Row Type) + | list -> option where -- | The `proxy` can be anything so long as its type variable has kind `Prim.RowList.RowList`. -- | -- | It will commonly be `Type.Data.RowList.RLProxy`, but doesn't have to be. @@ -1782,19 +1782,19 @@ instance partitionNilAnyAnyNilNil :: Partition Prim.RowList.Nil requiredInput optionalInput Prim.RowList.Nil Prim.RowList.Nil else instance partitionConsConsAnyConsAny :: ( Partition list requiredInput optionalInput requiredOutput optionalOutput - ) => + ) => Partition (Prim.RowList.Cons label requiredValue list) (Prim.RowList.Cons label value requiredInput) optionalInput (Prim.RowList.Cons label requiredValue requiredOutput) optionalOutput else instance partitionConsAnyConsAnyCons :: ( Partition list requiredInput optionalInput requiredOutput optionalOutput - ) => + ) => Partition (Prim.RowList.Cons label optionalValue list) requiredInput (Prim.RowList.Cons label value optionalInput) requiredOutput (Prim.RowList.Cons label optionalValue optionalOutput) else instance partitionConsConsAnyAnyAny :: ( Partition (Prim.RowList.Cons label value list) requiredInput optionalInput requiredOutput optionalOutput - ) => + ) => Partition (Prim.RowList.Cons label value list) (Prim.RowList.Cons requiredLabel requiredValue requiredInput) optionalInput requiredOutput optionalOutput else instance partitionConsAnyConsAnyAny :: ( Partition (Prim.RowList.Cons label value list) requiredInput optionalInput requiredOutput optionalOutput - ) => + ) => Partition (Prim.RowList.Cons label value list) requiredInput (Prim.RowList.Cons optionalLabel optionalValue optionalInput) requiredOutput optionalOutput -- | A typeclass that iterates a `RowList` attempting to read a `Foreign` to an `Option _`. @@ -3155,7 +3155,8 @@ toRecord option = toRecord' record staticCheck :: forall a. - a -> Unit + a -> + Unit staticCheck _ = unit -- | Static checks @@ -3205,8 +3206,10 @@ staticChecks = , staticCheck user28 ] -type User - = Option ( username :: String, age :: Int ) +type User = Option + ( username :: String + , age :: Int + ) -- does_not_type1 :: User -- does_not_type1 = fromRecord { height: 10 } @@ -3221,16 +3224,16 @@ age = get (Data.Symbol.SProxy :: _ "age") user user1 :: User user1 = set (Data.Symbol.SProxy :: _ "age") 12 user -user2 :: Option ( username :: String, age :: Int, height :: Int ) +user2 :: Option (username :: String, age :: Int, height :: Int) user2 = insert (Data.Symbol.SProxy :: _ "height") 12 user -user3 :: Option ( username :: String, age :: Boolean ) +user3 :: Option (username :: String, age :: Boolean) user3 = set (Data.Symbol.SProxy :: _ "age") true user -user4 :: Option ( username :: String ) +user4 :: Option (username :: String) user4 = delete (Data.Symbol.SProxy :: _ "age") user -user5 :: Option ( username :: String, age :: Boolean ) +user5 :: Option (username :: String, age :: Boolean) user5 = modify (Data.Symbol.SProxy :: _ "age") (\_ -> true) user user6 :: User @@ -3254,7 +3257,7 @@ user11 = set' { age: 31 } user user12 :: User user12 = set' { age: 31, username: "pat" } user -user13 :: Option ( username :: String, age :: Boolean ) +user13 :: Option (username :: String, age :: Boolean) user13 = set' { age: true } user user14 :: User @@ -3272,16 +3275,16 @@ user17 = delete' { age: unit, username: unit } user user18 :: Prim.Record () user18 = get' {} user -user19 :: Prim.Record ( age :: Int, username :: String ) +user19 :: Prim.Record (age :: Int, username :: String) user19 = get' { age: 0, username: "anonymous" } user -user20 :: Prim.Record ( age :: String, username :: Data.Maybe.Maybe String ) +user20 :: Prim.Record (age :: String, username :: Data.Maybe.Maybe String) user20 = get' { age: Data.Maybe.maybe "unknown" show, username: Data.Maybe.Just "anonymous" } user -user21 :: Option ( age :: Boolean, username :: String ) +user21 :: Option (age :: Boolean, username :: String) user21 = modify' { age: \_ -> true } user -user22 :: Option ( age :: Boolean, username :: String ) +user22 :: Option (age :: Boolean, username :: String) user22 = alter { age: \(_ :: Data.Maybe.Maybe Int) -> Data.Maybe.Just true } user user23 :: User @@ -3296,14 +3299,13 @@ user25 = fromRecord { age: Data.Maybe.Nothing, username: Data.Maybe.Just "Pat" } user26 :: User user26 = fromRecord { age: Data.Maybe.Nothing, username: Data.Maybe.Nothing } -user27 :: Option ( age1 :: Int, username :: String ) +user27 :: Option (age1 :: Int, username :: String) user27 = rename { age: Data.Symbol.SProxy :: Data.Symbol.SProxy "age1" } user -user28 :: Option ( age :: Int, username2 :: String ) +user28 :: Option (age :: Int, username2 :: String) user28 = rename { username: Data.Symbol.SProxy :: Data.Symbol.SProxy "username2" } user -type Greeting - = Record ( name :: String ) ( title :: String ) +type Greeting = Record (name :: String) (title :: String) greeting1 :: Greeting greeting1 = recordFromRecord { name: "Pat" } @@ -3326,5 +3328,5 @@ greeting6 = recordSet { name: "Chris", title: Data.Maybe.Just "Dr." } greeting1 greeting7 :: Greeting greeting7 = recordSet { name: "Chris", title: Data.Maybe.Nothing } greeting1 -greeting8 :: Record ( "Name" :: String ) ( "Title" :: String ) +greeting8 :: Record ("Name" :: String) ("Title" :: String) greeting8 = recordRename { name: Data.Symbol.SProxy :: Data.Symbol.SProxy "Name", title: Data.Symbol.SProxy :: Data.Symbol.SProxy "Title" } greeting1 diff --git a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptArgonaut.purs b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptArgonaut.purs index 580a196..ed7b33a 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptArgonaut.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptArgonaut.purs @@ -17,17 +17,17 @@ import Test.Spec.Assertions as Test.Spec.Assertions decode :: Data.Argonaut.Core.Json -> - Data.Either.Either Data.Argonaut.Decode.Error.JsonDecodeError (Option.Option ( name :: String, title :: String )) + Data.Either.Either Data.Argonaut.Decode.Error.JsonDecodeError (Option.Option (name :: String, title :: String)) decode = Data.Argonaut.Decode.Class.decodeJson encode :: - Option.Option ( name :: String, title :: String ) -> + Option.Option (name :: String, title :: String) -> Data.Argonaut.Core.Json encode = Data.Argonaut.Encode.Class.encodeJson parse :: String -> - Data.Either.Either String (Option.Option ( name :: String, title :: String )) + Data.Either.Either String (Option.Option (name :: String, title :: String)) parse string = case Data.Argonaut.Parser.jsonParser string of Data.Either.Left error -> Data.Either.Left error Data.Either.Right json -> case decode json of diff --git a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptCodecArgonaut.purs b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptCodecArgonaut.purs index 6e25bb1..2baeffe 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptCodecArgonaut.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptCodecArgonaut.purs @@ -15,15 +15,15 @@ import Test.Spec.Assertions as Test.Spec.Assertions decode :: Data.Argonaut.Core.Json -> - Data.Either.Either Data.Codec.Argonaut.JsonDecodeError (Option.Option ( name :: String, title :: String )) + Data.Either.Either Data.Codec.Argonaut.JsonDecodeError (Option.Option (name :: String, title :: String)) decode = Data.Codec.Argonaut.decode jsonCodec encode :: - Option.Option ( name :: String, title :: String ) -> + Option.Option (name :: String, title :: String) -> Data.Argonaut.Core.Json encode = Data.Codec.Argonaut.encode jsonCodec -jsonCodec :: Data.Codec.Argonaut.JsonCodec (Option.Option ( name :: String, title :: String )) +jsonCodec :: Data.Codec.Argonaut.JsonCodec (Option.Option (name :: String, title :: String)) jsonCodec = Option.jsonCodec "Greeting" @@ -33,7 +33,7 @@ jsonCodec = parse :: String -> - Data.Either.Either String (Option.Option ( name :: String, title :: String )) + Data.Either.Either String (Option.Option (name :: String, title :: String)) parse string = do json <- Data.Argonaut.Parser.jsonParser string case decode json of diff --git a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptSimpleJSON.purs b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptSimpleJSON.purs index 26c90a6..2092213 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptSimpleJSON.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithOptionalValuesInPureScriptSimpleJSON.purs @@ -13,11 +13,11 @@ import Test.Spec.Assertions as Test.Spec.Assertions readJSON :: String -> - Simple.JSON.E (Option.Option ( name :: String, title :: String )) + Simple.JSON.E (Option.Option (name :: String, title :: String)) readJSON = Simple.JSON.readJSON writeJSON :: - Option.Option ( name :: String, title :: String ) -> + Option.Option (name :: String, title :: String) -> String writeJSON = Simple.JSON.writeJSON diff --git a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptArgonaut.purs b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptArgonaut.purs index d342e35..0e525bd 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptArgonaut.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptArgonaut.purs @@ -17,17 +17,17 @@ import Test.Spec.Assertions as Test.Spec.Assertions decode :: Data.Argonaut.Core.Json -> - Data.Either.Either Data.Argonaut.Decode.Error.JsonDecodeError (Option.Record ( name :: String ) ( title :: String )) + Data.Either.Either Data.Argonaut.Decode.Error.JsonDecodeError (Option.Record (name :: String) (title :: String)) decode = Data.Argonaut.Decode.Class.decodeJson encode :: - Option.Record ( name :: String ) ( title :: String ) -> + Option.Record (name :: String) (title :: String) -> Data.Argonaut.Core.Json encode = Data.Argonaut.Encode.Class.encodeJson parse :: String -> - Data.Either.Either String (Option.Record ( name :: String ) ( title :: String )) + Data.Either.Either String (Option.Record (name :: String) (title :: String)) parse string = case Data.Argonaut.Parser.jsonParser string of Data.Either.Left error -> Data.Either.Left error Data.Either.Right json -> case decode json of diff --git a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptCodecArgonaut.purs b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptCodecArgonaut.purs index 2a901c7..dda0256 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptCodecArgonaut.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptCodecArgonaut.purs @@ -15,15 +15,15 @@ import Test.Spec.Assertions as Test.Spec.Assertions decode :: Data.Argonaut.Core.Json -> - Data.Either.Either Data.Codec.Argonaut.JsonDecodeError (Option.Record ( name :: String ) ( title :: String )) + Data.Either.Either Data.Codec.Argonaut.JsonDecodeError (Option.Record (name :: String) (title :: String)) decode = Data.Codec.Argonaut.decode jsonCodec encode :: - Option.Record ( name :: String ) ( title :: String ) -> + Option.Record (name :: String) (title :: String) -> Data.Argonaut.Core.Json encode = Data.Codec.Argonaut.encode jsonCodec -jsonCodec :: Data.Codec.Argonaut.JsonCodec (Option.Record ( name :: String ) ( title :: String )) +jsonCodec :: Data.Codec.Argonaut.JsonCodec (Option.Record (name :: String) (title :: String)) jsonCodec = Option.jsonCodecRecord "Greeting" @@ -33,7 +33,7 @@ jsonCodec = parse :: String -> - Data.Either.Either String (Option.Record ( name :: String ) ( title :: String )) + Data.Either.Either String (Option.Record (name :: String) (title :: String)) parse string = do json <- Data.Argonaut.Parser.jsonParser string case decode json of diff --git a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptSimpleJSON.purs b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptSimpleJSON.purs index f86c380..ddc1346 100644 --- a/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptSimpleJSON.purs +++ b/test/HowTo.DecodeAndEncodeJSONWithRequiredAndOptionalValuesInPureScriptSimpleJSON.purs @@ -15,18 +15,18 @@ import Test.Spec.Assertions as Test.Spec.Assertions parse :: String -> - Data.Either.Either String (Option.Record ( name :: String ) ( title :: String )) + Data.Either.Either String (Option.Record (name :: String) (title :: String)) parse string = case readJSON string of Data.Either.Left errors -> Data.Either.Left (Data.Semigroup.Foldable.intercalateMap " " Foreign.renderForeignError errors) Data.Either.Right record -> Data.Either.Right record readJSON :: String -> - Simple.JSON.E (Option.Record ( name :: String ) ( title :: String )) + Simple.JSON.E (Option.Record (name :: String) (title :: String)) readJSON = Simple.JSON.readJSON writeJSON :: - Option.Record ( name :: String ) ( title :: String ) -> + Option.Record (name :: String) (title :: String) -> String writeJSON = Simple.JSON.writeJSON diff --git a/test/HowTo.MakeAFunctionWithOptionalValues.purs b/test/HowTo.MakeAFunctionWithOptionalValues.purs index 869190e..3c88e56 100644 --- a/test/HowTo.MakeAFunctionWithOptionalValues.purs +++ b/test/HowTo.MakeAFunctionWithOptionalValues.purs @@ -11,7 +11,7 @@ import Option as Option import Test.Spec as Test.Spec import Test.Spec.Assertions as Test.Spec.Assertions -greeting :: Option.Option ( name :: String, title :: String ) -> String +greeting :: Option.Option (name :: String, title :: String) -> String greeting option = "Hello, " <> title' <> name' where name' :: String diff --git a/test/HowTo.MakeAFunctionWithOptionalValuesFromARecord.purs b/test/HowTo.MakeAFunctionWithOptionalValuesFromARecord.purs index a6d25ea..f6113c6 100644 --- a/test/HowTo.MakeAFunctionWithOptionalValuesFromARecord.purs +++ b/test/HowTo.MakeAFunctionWithOptionalValuesFromARecord.purs @@ -13,7 +13,7 @@ import Test.Spec.Assertions as Test.Spec.Assertions greeting :: forall record. - Option.FromRecord record () ( name :: String, title :: String ) => + Option.FromRecord record () (name :: String, title :: String) => Record record -> String greeting record = "Hello, " <> title' <> name' @@ -23,7 +23,7 @@ greeting record = "Hello, " <> title' <> name' Data.Maybe.Just name -> name Data.Maybe.Nothing -> "World" - option :: Option.Option ( name :: String, title :: String ) + option :: Option.Option (name :: String, title :: String) option = Option.fromRecord record title' :: String diff --git a/test/HowTo.MakeAFunctionWithRequiredAndOptionalValues.purs b/test/HowTo.MakeAFunctionWithRequiredAndOptionalValues.purs index f4c0d9b..e18a682 100644 --- a/test/HowTo.MakeAFunctionWithRequiredAndOptionalValues.purs +++ b/test/HowTo.MakeAFunctionWithRequiredAndOptionalValues.purs @@ -11,11 +11,11 @@ import Test.Spec as Test.Spec import Test.Spec.Assertions as Test.Spec.Assertions greeting :: - Option.Record ( name :: String ) ( title :: String ) -> + Option.Record (name :: String) (title :: String) -> String greeting record' = "Hello, " <> title' <> record.name where - record :: Record ( name :: String, title :: Data.Maybe.Maybe String ) + record :: Record (name :: String, title :: Data.Maybe.Maybe String) record = Option.recordToRecord record' title' :: String diff --git a/test/HowTo.MakeAFunctionWithRequiredAndOptionalValuesFromARecord.purs b/test/HowTo.MakeAFunctionWithRequiredAndOptionalValuesFromARecord.purs index 79c3c40..05945fa 100644 --- a/test/HowTo.MakeAFunctionWithRequiredAndOptionalValuesFromARecord.purs +++ b/test/HowTo.MakeAFunctionWithRequiredAndOptionalValuesFromARecord.purs @@ -12,15 +12,15 @@ import Test.Spec.Assertions as Test.Spec.Assertions greeting :: forall record. - Option.FromRecord record ( name :: String ) ( title :: String ) => + Option.FromRecord record (name :: String) (title :: String) => Record record -> String greeting record'' = "Hello, " <> title' <> record.name where - record :: Record ( name :: String, title :: Data.Maybe.Maybe String ) + record :: Record (name :: String, title :: Data.Maybe.Maybe String) record = Option.recordToRecord record' - record' :: Option.Record ( name :: String ) ( title :: String ) + record' :: Option.Record (name :: String) (title :: String) record' = Option.recordFromRecord record'' title' :: String diff --git a/test/HowTo.ProvideAnEasierAPIForDateTime.purs b/test/HowTo.ProvideAnEasierAPIForDateTime.purs index f2c0e24..b175886 100644 --- a/test/HowTo.ProvideAnEasierAPIForDateTime.purs +++ b/test/HowTo.ProvideAnEasierAPIForDateTime.purs @@ -18,15 +18,15 @@ import Prim.Row as Prim.Row import Test.Spec as Test.Spec import Test.Spec.Assertions as Test.Spec.Assertions -type Option - = ( day :: Int - , hour :: Int - , millisecond :: Int - , minute :: Int - , month :: Data.Date.Component.Month - , second :: Int - , year :: Int - ) +type Option = + ( day :: Int + , hour :: Int + , millisecond :: Int + , minute :: Int + , month :: Data.Date.Component.Month + , second :: Int + , year :: Int + ) dateTime :: forall record. diff --git a/test/Test.Main.purs b/test/Test.Main.purs index 2822d72..06a055e 100644 --- a/test/Test.Main.purs +++ b/test/Test.Main.purs @@ -19,8 +19,7 @@ import Test.Spec as Test.Spec import Test.Spec.Reporter.Console as Test.Spec.Reporter.Console import Test.Spec.Runner as Test.Spec.Runner -data Proxy (symbol :: Symbol) - = Proxy +data Proxy (symbol :: Symbol) = Proxy main :: Effect.Effect Unit main = Effect.Aff.launchAff_ (Test.Spec.Runner.runSpec reporters spec) diff --git a/test/Test.Option.purs b/test/Test.Option.purs index 9e866df..a582e3a 100644 --- a/test/Test.Option.purs +++ b/test/Test.Option.purs @@ -8,8 +8,7 @@ import Option as Option import Test.Spec as Test.Spec import Test.Spec.Assertions as Test.Spec.Assertions -data Proxy (symbol :: Symbol) - = Proxy +data Proxy (symbol :: Symbol) = Proxy spec :: Test.Spec.Spec Unit spec = @@ -31,7 +30,7 @@ spec_alter = Test.Spec.describe "alter" do Test.Spec.it "does nothing if values are not set" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.empty bar :: @@ -43,7 +42,7 @@ spec_alter = Option.alter { bar } someOption `Test.Spec.Assertions.shouldEqual` Option.fromRecord {} Test.Spec.it "manipulates all fields it can" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.fromRecord { bar: 31, qux: "hi" } bar :: @@ -132,7 +131,7 @@ spec_get' = Test.Spec.describe "get'" do Test.Spec.it "gets all fields it can" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.empty bar :: @@ -148,7 +147,7 @@ spec_modify' = Test.Spec.describe "modify'" do Test.Spec.it "does nothing if values are not set" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.empty bar :: @@ -158,7 +157,7 @@ spec_modify' = Option.modify' { bar } someOption `Test.Spec.Assertions.shouldEqual` Option.fromRecord {} Test.Spec.it "manipulates all fields it can" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.fromRecord { bar: 31 } bar :: @@ -191,34 +190,34 @@ spec_recordRename = Test.Spec.describe "recordRename" do Test.Spec.it "renames a value when it doesn't exist" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar2 :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar2 :: Int) anotherRecord = Option.recordRename { bar: Proxy :: Proxy "bar2" } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar2: Data.Maybe.Nothing, foo: false } Test.Spec.it "can rename both required and optional values" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo1 :: Boolean ) ( bar2 :: Int ) + anotherRecord :: Option.Record (foo1 :: Boolean) (bar2 :: Int) anotherRecord = Option.recordRename { foo: Proxy :: Proxy "foo1", bar: Proxy :: Proxy "bar2" } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar2: Data.Maybe.Nothing, foo1: false } Test.Spec.it "can rename any required and optional values" do let - someRecord :: Option.Record ( foo :: Boolean, bar :: Int, baz :: String ) ( qux :: Boolean, cor :: Int, gar :: String ) + someRecord :: Option.Record (foo :: Boolean, bar :: Int, baz :: String) (qux :: Boolean, cor :: Int, gar :: String) someRecord = Option.recordFromRecord { foo: false, bar: 31, baz: "hi" } - anotherRecord :: Option.Record ( foo :: Boolean, bar :: Int, baz3 :: String ) ( qux4 :: Boolean, cor :: Int, gar :: String ) + anotherRecord :: Option.Record (foo :: Boolean, bar :: Int, baz3 :: String) (qux4 :: Boolean, cor :: Int, gar :: String) anotherRecord = Option.recordRename { baz: Proxy :: Proxy "baz3", qux: Proxy :: Proxy "qux4" } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: 31, baz3: "hi", cor: Data.Maybe.Nothing, foo: false, gar: Data.Maybe.Nothing, qux4: Data.Maybe.Nothing } Test.Spec.it "can rename any required and optional values with any interleaving of names" do let - someRecord :: Option.Record ( a :: Boolean, c :: Boolean, e :: Boolean ) ( b :: Boolean, d :: Boolean, f :: Boolean ) + someRecord :: Option.Record (a :: Boolean, c :: Boolean, e :: Boolean) (b :: Boolean, d :: Boolean, f :: Boolean) someRecord = Option.recordFromRecord { a: false, c: false, e: false } - anotherRecord :: Option.Record ( a :: Boolean, c2 :: Boolean, e :: Boolean ) ( b4 :: Boolean, d5 :: Boolean, f :: Boolean ) + anotherRecord :: Option.Record (a :: Boolean, c2 :: Boolean, e :: Boolean) (b4 :: Boolean, d5 :: Boolean, f :: Boolean) anotherRecord = Option.recordRename { b: Proxy :: Proxy "b4", c: Proxy :: Proxy "c2", d: Proxy :: Proxy "d5" } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { a: false, b4: Data.Maybe.Nothing, c2: false, d5: Data.Maybe.Nothing, e: false, f: Data.Maybe.Nothing } @@ -227,66 +226,66 @@ spec_recordSet = Test.Spec.describe "recordSet" do Test.Spec.it "sets a value when it doesn't exist" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar :: Int) anotherRecord = Option.recordSet { bar: 31 } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Just 31, foo: false } Test.Spec.it "can change the type" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Boolean ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Boolean) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar :: Int) anotherRecord = Option.recordSet { bar: 31 } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Just 31, foo: false } Test.Spec.it "can use a `Data.Maybe.Maybe _`" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar :: Int) anotherRecord = Option.recordSet { bar: Data.Maybe.Just 31 } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Just 31, foo: false } Test.Spec.it "`Data.Maybe.Nothing` removes the previous value" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { bar: 31, foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar :: Int) anotherRecord = Option.recordSet { bar: Data.Maybe.Nothing } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Nothing, foo: false } Test.Spec.it "can set both required and optional values" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Int) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Boolean ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Boolean) (bar :: Int) anotherRecord = Option.recordSet { bar: 31 } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Just 31, foo: false } Test.Spec.it "can set any required and optional values" do let - someRecord :: Option.Record ( foo :: Boolean, bar :: Int, baz :: String ) ( qux :: Boolean, cor :: Int, gar :: String ) + someRecord :: Option.Record (foo :: Boolean, bar :: Int, baz :: String) (qux :: Boolean, cor :: Int, gar :: String) someRecord = Option.recordFromRecord { foo: false, bar: 31, baz: "hi" } - anotherRecord :: Option.Record ( foo :: Boolean, bar :: Int, baz :: String ) ( qux :: Boolean, cor :: Int, gar :: String ) + anotherRecord :: Option.Record (foo :: Boolean, bar :: Int, baz :: String) (qux :: Boolean, cor :: Int, gar :: String) anotherRecord = Option.recordSet { baz: "hello", qux: true } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: 31, baz: "hello", cor: Data.Maybe.Nothing, foo: false, gar: Data.Maybe.Nothing, qux: Data.Maybe.Just true } Test.Spec.it "can set any required and optional values with any interleaving of names" do let - someRecord :: Option.Record ( a :: Boolean, c :: Boolean, e :: Boolean ) ( b :: Boolean, d :: Boolean, f :: Boolean ) + someRecord :: Option.Record (a :: Boolean, c :: Boolean, e :: Boolean) (b :: Boolean, d :: Boolean, f :: Boolean) someRecord = Option.recordFromRecord { a: false, c: false, e: false } - anotherRecord :: Option.Record ( a :: Boolean, c :: Boolean, e :: Boolean ) ( b :: Boolean, d :: Boolean, f :: Boolean ) + anotherRecord :: Option.Record (a :: Boolean, c :: Boolean, e :: Boolean) (b :: Boolean, d :: Boolean, f :: Boolean) anotherRecord = Option.recordSet { b: true, c: true, d: true } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { a: false, b: Data.Maybe.Just true, c: true, d: Data.Maybe.Just true, e: false, f: Data.Maybe.Nothing } Test.Spec.it "can change the type of both required and optional values" do let - someRecord :: Option.Record ( foo :: Boolean ) ( bar :: Boolean ) + someRecord :: Option.Record (foo :: Boolean) (bar :: Boolean) someRecord = Option.recordFromRecord { foo: false } - anotherRecord :: Option.Record ( foo :: Int ) ( bar :: Int ) + anotherRecord :: Option.Record (foo :: Int) (bar :: Int) anotherRecord = Option.recordSet { bar: 31, foo: 43 } someRecord Option.recordToRecord anotherRecord `Test.Spec.Assertions.shouldEqual` { bar: Data.Maybe.Just 31, foo: 43 } @@ -314,18 +313,18 @@ spec_rename = Test.Spec.describe "rename" do Test.Spec.it "renames a value when it doesn't exist" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int ) + someOption :: Option.Option (foo :: Boolean, bar :: Int) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar2 :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar2 :: Int) anotherOption = Option.rename { bar: Proxy :: Proxy "bar2" } someOption Option.get (Proxy :: _ "bar2") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Nothing Test.Spec.it "can rename any field" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int, qux3 :: String ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int, qux3 :: String) anotherOption = Option.rename { qux: Proxy :: Proxy "qux3" } someOption Option.get (Proxy :: _ "qux3") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Nothing @@ -334,10 +333,10 @@ spec_set = Test.Spec.describe "set" do Test.Spec.it "sets a value when it doesn't exist" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int ) + someOption :: Option.Option (foo :: Boolean, bar :: Int) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int) anotherOption = Option.set (Proxy :: _ "bar") 31 someOption Option.get (Proxy :: _ "bar") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Just 31 @@ -346,41 +345,41 @@ spec_set' = Test.Spec.describe "set'" do Test.Spec.it "sets a value when it doesn't exist" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int ) + someOption :: Option.Option (foo :: Boolean, bar :: Int) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int) anotherOption = Option.set' { bar: 31 } someOption Option.get (Proxy :: _ "bar") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Just 31 Test.Spec.it "can work for any field" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + someOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int, qux :: String ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int, qux :: String) anotherOption = Option.set' { qux: "hi" } someOption Option.get (Proxy :: _ "qux") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Just "hi" Test.Spec.it "can change the type" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Boolean ) + someOption :: Option.Option (foo :: Boolean, bar :: Boolean) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int) anotherOption = Option.set' { bar: 31 } someOption Option.get (Proxy :: _ "bar") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Just 31 Test.Spec.it "can use a `Data.Maybe.Maybe _`" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int ) + someOption :: Option.Option (foo :: Boolean, bar :: Int) someOption = Option.empty - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int) anotherOption = Option.set' { bar: Data.Maybe.Just 31 } someOption Option.get (Proxy :: _ "bar") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Just 31 Test.Spec.it "`Data.Maybe.Nothing` removes the previous value" do let - someOption :: Option.Option ( foo :: Boolean, bar :: Int ) + someOption :: Option.Option (foo :: Boolean, bar :: Int) someOption = Option.fromRecord { bar: 31 } - anotherOption :: Option.Option ( foo :: Boolean, bar :: Int ) + anotherOption :: Option.Option (foo :: Boolean, bar :: Int) anotherOption = Option.set' { bar: Data.Maybe.Nothing } someOption Option.get (Proxy :: _ "bar") anotherOption `Test.Spec.Assertions.shouldEqual` Data.Maybe.Nothing From 1d450cc2d90b728426b06cc0e99cd4fe01b9a1c4 Mon Sep 17 00:00:00 2001 From: joneshf Date: Sat, 12 Jul 2025 19:46:08 -0700 Subject: [PATCH 10/13] Enable `yamlfmt` We want YAML to be formatted consistently just like all the other stuff. We enable `yamlfmt` in `treefmt` so we get that with `make format` as well. --- .github/workflows/nodejs.yml | 16 ++++++++-------- .yamlfmt.yaml | 3 +++ flake.nix | 5 +++++ 3 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .yamlfmt.yaml diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index c554cf7..43ccdb0 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,16 +1,16 @@ name: CI on: -- push + - push jobs: build: runs-on: ubuntu-18.04 steps: - - uses: actions/checkout@53bed0742eb3f0455187c7c7042d27f51b856f02 - - name: Use Node.js 10.x - uses: actions/setup-node@56899e050abffc08c2b3b61f3ec6a79a9dc3223d - with: - node-version: 10.x - - name: test - run: make test + - uses: actions/checkout@53bed0742eb3f0455187c7c7042d27f51b856f02 + - name: Use Node.js 10.x + uses: actions/setup-node@56899e050abffc08c2b3b61f3ec6a79a9dc3223d + with: + node-version: 10.x + - name: test + run: make test diff --git a/.yamlfmt.yaml b/.yamlfmt.yaml new file mode 100644 index 0000000..3c194f9 --- /dev/null +++ b/.yamlfmt.yaml @@ -0,0 +1,3 @@ +formatter: + retain_line_breaks_single: true + type: basic diff --git a/flake.nix b/flake.nix index e55e6f5..2caca2e 100644 --- a/flake.nix +++ b/flake.nix @@ -204,6 +204,11 @@ shfmt = { enable = true; }; + + # Format YAML code consistently. + yamlfmt = { + enable = true; + }; }; settings.global.excludes = [ From 38bc2f055b6f3ae7d13ab090465a75dfb8254425 Mon Sep 17 00:00:00 2001 From: joneshf Date: Fri, 11 Jul 2025 05:27:45 -0700 Subject: [PATCH 11/13] Enable `actionlint` We want our GitHub Actions to do the right thing. There's a linter that checks we're not doing something wrong: `actionlint`. So we enable it. It already caught that the old `ubuntu-18.04` is no longer suported. So it's paying for itself. --- .github/workflows/nodejs.yml | 2 +- flake.nix | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 43ccdb0..6cb53d0 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -5,7 +5,7 @@ on: jobs: build: - runs-on: ubuntu-18.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@53bed0742eb3f0455187c7c7042d27f51b856f02 - name: Use Node.js 10.x diff --git a/flake.nix b/flake.nix index 2caca2e..1f0c892 100644 --- a/flake.nix +++ b/flake.nix @@ -116,6 +116,11 @@ ]; hooks = { + # Check `.github/workflows` code. + actionlint = { + enable = true; + }; + # Check Nix code for anything that is unused. deadnix = { enable = true; From 76a910f878fc2de6f476fbfa4ed344f3ee179d45 Mon Sep 17 00:00:00 2001 From: joneshf Date: Sun, 13 Jul 2025 21:33:07 -0700 Subject: [PATCH 12/13] Update some transitive `npm` dependencies Addressing some CVEs in `npm`, even though this isn't really how things work for this package. Still good to have some of this stuff not blasting warnings. We cannot update all `npm` dependencies just yet, since that requires bumping `purescript` and friends, and that's too big a change to make right now. --- package-lock.json | 134 +++++++++++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01775d1..76bfcf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,10 +41,11 @@ } }, "node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -160,10 +161,11 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -314,10 +316,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -746,10 +749,11 @@ "dev": true }, "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -764,18 +768,19 @@ "dev": true }, "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], + "license": "MIT", "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" } }, "node_modules/log-symbols": { @@ -853,10 +858,11 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -865,10 +871,14 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { "version": "2.9.0", @@ -1105,10 +1115,11 @@ } }, "node_modules/purescript-installer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/purescript-installer/-/purescript-installer-0.2.5.tgz", - "integrity": "sha512-fQAWWP5a7scuchXecjpU4r4KEgSPuS6bBnaP01k9f71qqD28HaJ2m4PXHFkhkR4oATAxTPIGCtmTwtVoiBOHog==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/purescript-installer/-/purescript-installer-0.2.6.tgz", + "integrity": "sha512-22un7k/S0hETctsMMVlCEuXlvy1VAgN/uL49B65dQVPUVd17fh9CbB5kd9xoqiADUyw3t5HgL68lCwmDwrCCVw==", "dev": true, + "license": "ISC", "dependencies": { "arch": "^2.1.1", "byline": "^5.0.0", @@ -1127,6 +1138,7 @@ "pump": "^3.0.0", "request": "^2.88.0", "rimraf": "^2.6.3", + "semver": "^7.3.7", "tar": "^4.4.6", "which": "^1.3.1", "zen-observable": "^0.8.14" @@ -1158,10 +1170,11 @@ } }, "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.6" } @@ -1281,6 +1294,19 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1415,23 +1441,45 @@ } }, "node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, + "license": "ISC", "dependencies": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" }, "engines": { "node": ">=4.5" } }, + "node_modules/tar/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", From bef8acd449766c5b1c4d9929c9ad410041926743 Mon Sep 17 00:00:00 2001 From: joneshf Date: Fri, 11 Jul 2025 05:28:04 -0700 Subject: [PATCH 13/13] Update GitHub Actions We update things to be a bit more modern: - We rename the file to not be about `nodejs` (because it never really was, that was an implementation detail). - We trigger on all `pull_request_target` events. - We trigger on pushes to the `main` or `joneshf/` branches. - We rename the job from `build` to `test` (because that's what we're actually doing: testing). - We bump the version of `actions/checkout`. - We switch to using `cachix/install-nix-action`. It would be nice to have this stuff cached somewhere, but caching with GitHub Actions plus Nix plus Node.js takes more than a modicum of effort, so we're not going to deal with it. --- .github/workflows/nodejs.yml | 16 ----------- .github/workflows/test.yaml | 53 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) delete mode 100644 .github/workflows/nodejs.yml create mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml deleted file mode 100644 index 6cb53d0..0000000 --- a/.github/workflows/nodejs.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: CI - -on: - - push - -jobs: - build: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@53bed0742eb3f0455187c7c7042d27f51b856f02 - - name: Use Node.js 10.x - uses: actions/setup-node@56899e050abffc08c2b3b61f3ec6a79a9dc3223d - with: - node-version: 10.x - - name: test - run: make test diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..2a68ef1 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,53 @@ +name: Test + +on: + - push + +jobs: + test: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - name: Install Nix + uses: nixbuild/nix-quick-install-action@63ca48f939ee3b8d835f4126562537df0fee5b91 + - name: Cache Nix store + uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a + with: + # The key includes the os/arch pair as artifacts in the Nix store are platform-specific. + primary-key: nix-${{ format('{0}_{1}', runner.os, runner.arch) }}-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }} + restore-prefixes-first-match: | + nix-${{ format('{0}_{1}', runner.os, runner.arch) }}-${{ hashFiles('flake.lock') }}- + nix-${{ format('{0}_{1}', runner.os, runner.arch) }}- + - name: Cache node_modules + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 + with: + # The key includes the os/arch pair as artifacts in `node_modules` can be platform-specific. + key: node_modules-${{ format('{0}_{1}', runner.os, runner.arch) }}-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }} + path: "**/node_modules" + restore-keys: | + node_modules-${{ format('{0}_{1}', runner.os, runner.arch) }}-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}- + node_modules-${{ format('{0}_{1}', runner.os, runner.arch) }}-${{ hashFiles('flake.lock') }}- + node_modules-${{ format('{0}_{1}', runner.os, runner.arch) }}- + - name: Cache bower_components + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 + with: + key: bower_components-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('bower.json') }} + path: bower_components + restore-keys: | + bower_components-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }}- + bower_components-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}- + bower_components-${{ hashFiles('flake.lock') }}- + bower_components- + - name: Cache output + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 + with: + key: output-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('bower.json') }}-${{ hashFiles('**/*.js', '**/*.purs') }} + path: output + restore-keys: | + output-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('bower.json') }}- + output-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}-${{ hashFiles('**/package-lock.json') }}- + output-${{ hashFiles('flake.lock') }}-${{ hashFiles('**/*.nix') }}- + output-${{ hashFiles('flake.lock') }}- + output- + - name: Test + run: nix develop . --command make test