generated from tpl/purs
feat: init, basic serde
This commit is contained in:
parent
6fadf32a68
commit
e2eb753317
@ -1,3 +1,2 @@
|
|||||||
bun 1.0.11
|
bun 1.0.35
|
||||||
purescript 0.15.12
|
purescript 0.15.15
|
||||||
nodejs 20.9.0
|
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bun-types": "1.0.11",
|
"bun-types": "1.0.11",
|
||||||
|
"postgres-range": "^1.1.4",
|
||||||
"purs-tidy": "^0.10.0",
|
"purs-tidy": "^0.10.0",
|
||||||
"spago": "next"
|
"spago": "next"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {}
|
"dependencies": { "pg-types": "^4.0.2" }
|
||||||
}
|
}
|
||||||
|
877
spago.lock
Normal file
877
spago.lock
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
workspace:
|
||||||
|
packages:
|
||||||
|
pg:
|
||||||
|
path: ./
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- datetime
|
||||||
|
- effect
|
||||||
|
- exceptions
|
||||||
|
- foldable-traversable
|
||||||
|
- foreign
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- node-buffer
|
||||||
|
- precise-datetime
|
||||||
|
- prelude
|
||||||
|
- transformers
|
||||||
|
- unsafe-coerce
|
||||||
|
test_dependencies:
|
||||||
|
- quickcheck
|
||||||
|
- spec
|
||||||
|
- spec-quickcheck
|
||||||
|
build_plan:
|
||||||
|
- aff
|
||||||
|
- ansi
|
||||||
|
- arraybuffer-types
|
||||||
|
- arrays
|
||||||
|
- avar
|
||||||
|
- bifunctors
|
||||||
|
- catenable-lists
|
||||||
|
- console
|
||||||
|
- const
|
||||||
|
- contravariant
|
||||||
|
- control
|
||||||
|
- datetime
|
||||||
|
- decimals
|
||||||
|
- distributive
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- exceptions
|
||||||
|
- exists
|
||||||
|
- fixed-points
|
||||||
|
- foldable-traversable
|
||||||
|
- foreign
|
||||||
|
- fork
|
||||||
|
- formatters
|
||||||
|
- free
|
||||||
|
- functions
|
||||||
|
- functors
|
||||||
|
- gen
|
||||||
|
- identity
|
||||||
|
- integers
|
||||||
|
- invariant
|
||||||
|
- js-date
|
||||||
|
- lazy
|
||||||
|
- lcg
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- mmorph
|
||||||
|
- newtype
|
||||||
|
- node-buffer
|
||||||
|
- nonempty
|
||||||
|
- now
|
||||||
|
- nullable
|
||||||
|
- numbers
|
||||||
|
- ordered-collections
|
||||||
|
- orders
|
||||||
|
- parallel
|
||||||
|
- parsing
|
||||||
|
- partial
|
||||||
|
- pipes
|
||||||
|
- precise-datetime
|
||||||
|
- prelude
|
||||||
|
- profunctor
|
||||||
|
- quickcheck
|
||||||
|
- random
|
||||||
|
- record
|
||||||
|
- refs
|
||||||
|
- safe-coerce
|
||||||
|
- spec
|
||||||
|
- spec-quickcheck
|
||||||
|
- st
|
||||||
|
- strings
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
- type-equality
|
||||||
|
- unfoldable
|
||||||
|
- unicode
|
||||||
|
- unsafe-coerce
|
||||||
|
extra_packages: {}
|
||||||
|
packages:
|
||||||
|
aff:
|
||||||
|
type: registry
|
||||||
|
version: 7.1.0
|
||||||
|
integrity: sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- datetime
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- exceptions
|
||||||
|
- foldable-traversable
|
||||||
|
- functions
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- parallel
|
||||||
|
- prelude
|
||||||
|
- refs
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- unsafe-coerce
|
||||||
|
ansi:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-ZMB6HD+q9CXvn9fRCmJ8dvuDrOVHcjombL3oNOerVnE=
|
||||||
|
dependencies:
|
||||||
|
- foldable-traversable
|
||||||
|
- lists
|
||||||
|
- strings
|
||||||
|
arraybuffer-types:
|
||||||
|
type: registry
|
||||||
|
version: 3.0.2
|
||||||
|
integrity: sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA=
|
||||||
|
dependencies: []
|
||||||
|
arrays:
|
||||||
|
type: registry
|
||||||
|
version: 7.3.0
|
||||||
|
integrity: sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- foldable-traversable
|
||||||
|
- functions
|
||||||
|
- maybe
|
||||||
|
- nonempty
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- safe-coerce
|
||||||
|
- st
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
- unsafe-coerce
|
||||||
|
avar:
|
||||||
|
type: registry
|
||||||
|
version: 5.0.0
|
||||||
|
integrity: sha256-e7hf0x4hEpcygXP0LtvfvAQ49Bbj2aWtZT3gqM///0A=
|
||||||
|
dependencies:
|
||||||
|
- aff
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- exceptions
|
||||||
|
- functions
|
||||||
|
- maybe
|
||||||
|
bifunctors:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw=
|
||||||
|
dependencies:
|
||||||
|
- const
|
||||||
|
- either
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
catenable-lists:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- foldable-traversable
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
console:
|
||||||
|
type: registry
|
||||||
|
version: 6.1.0
|
||||||
|
integrity: sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- prelude
|
||||||
|
const:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc=
|
||||||
|
dependencies:
|
||||||
|
- invariant
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
contravariant:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c=
|
||||||
|
dependencies:
|
||||||
|
- const
|
||||||
|
- either
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
control:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk=
|
||||||
|
dependencies:
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
datetime:
|
||||||
|
type: registry
|
||||||
|
version: 6.1.0
|
||||||
|
integrity: sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- foldable-traversable
|
||||||
|
- functions
|
||||||
|
- gen
|
||||||
|
- integers
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- numbers
|
||||||
|
- ordered-collections
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
decimals:
|
||||||
|
type: registry
|
||||||
|
version: 7.1.0
|
||||||
|
integrity: sha256-DriR6lPEfFpjVv7e4JAQkr3ZLf0h17Qg2cAIrhxWV7w=
|
||||||
|
dependencies:
|
||||||
|
- maybe
|
||||||
|
distributive:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ=
|
||||||
|
dependencies:
|
||||||
|
- identity
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
- type-equality
|
||||||
|
effect:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.0
|
||||||
|
integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=
|
||||||
|
dependencies:
|
||||||
|
- prelude
|
||||||
|
either:
|
||||||
|
type: registry
|
||||||
|
version: 6.1.0
|
||||||
|
integrity: sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- invariant
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
enums:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.1
|
||||||
|
integrity: sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- either
|
||||||
|
- gen
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nonempty
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
exceptions:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-y/xTAEIZIARCE+50/u1di0ncebJ+CIwNOLswyOWzMTw=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
exists:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8=
|
||||||
|
dependencies:
|
||||||
|
- unsafe-coerce
|
||||||
|
fixed-points:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-hTl5fzeG4mzAOFzEzAeNH7kJvJgYCH7x3v2NdX9pOE4=
|
||||||
|
dependencies:
|
||||||
|
- exists
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- transformers
|
||||||
|
foldable-traversable:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- const
|
||||||
|
- control
|
||||||
|
- either
|
||||||
|
- functors
|
||||||
|
- identity
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- orders
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
foreign:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA=
|
||||||
|
dependencies:
|
||||||
|
- either
|
||||||
|
- functions
|
||||||
|
- identity
|
||||||
|
- integers
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
- strings
|
||||||
|
- transformers
|
||||||
|
fork:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-X7u0SuCvFbLbzuNEKLBNuWjmcroqMqit4xEzpQwAP7E=
|
||||||
|
dependencies:
|
||||||
|
- aff
|
||||||
|
formatters:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-5JaC9d2p0xoqJWjWxlHH19R4iJwFTBr4j7SlYcLgicE=
|
||||||
|
dependencies:
|
||||||
|
- datetime
|
||||||
|
- fixed-points
|
||||||
|
- lists
|
||||||
|
- numbers
|
||||||
|
- parsing
|
||||||
|
- prelude
|
||||||
|
- transformers
|
||||||
|
free:
|
||||||
|
type: registry
|
||||||
|
version: 7.1.0
|
||||||
|
integrity: sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k=
|
||||||
|
dependencies:
|
||||||
|
- catenable-lists
|
||||||
|
- control
|
||||||
|
- distributive
|
||||||
|
- either
|
||||||
|
- exists
|
||||||
|
- foldable-traversable
|
||||||
|
- invariant
|
||||||
|
- lazy
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
- unsafe-coerce
|
||||||
|
functions:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI=
|
||||||
|
dependencies:
|
||||||
|
- prelude
|
||||||
|
functors:
|
||||||
|
type: registry
|
||||||
|
version: 5.0.0
|
||||||
|
integrity: sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- const
|
||||||
|
- contravariant
|
||||||
|
- control
|
||||||
|
- distributive
|
||||||
|
- either
|
||||||
|
- invariant
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- profunctor
|
||||||
|
- tuples
|
||||||
|
- unsafe-coerce
|
||||||
|
gen:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.0
|
||||||
|
integrity: sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI=
|
||||||
|
dependencies:
|
||||||
|
- either
|
||||||
|
- foldable-traversable
|
||||||
|
- identity
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nonempty
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
identity:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- invariant
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
integers:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158=
|
||||||
|
dependencies:
|
||||||
|
- maybe
|
||||||
|
- numbers
|
||||||
|
- prelude
|
||||||
|
invariant:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- prelude
|
||||||
|
js-date:
|
||||||
|
type: registry
|
||||||
|
version: 8.0.0
|
||||||
|
integrity: sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo=
|
||||||
|
dependencies:
|
||||||
|
- datetime
|
||||||
|
- effect
|
||||||
|
- exceptions
|
||||||
|
- foreign
|
||||||
|
- integers
|
||||||
|
- now
|
||||||
|
lazy:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- foldable-traversable
|
||||||
|
- invariant
|
||||||
|
- prelude
|
||||||
|
lcg:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.0
|
||||||
|
integrity: sha256-h7ME5cthLfbgJOJdsZcSfFpwXsx4rf8YmhebU+3iSYg=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- integers
|
||||||
|
- maybe
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- random
|
||||||
|
lists:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- foldable-traversable
|
||||||
|
- lazy
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nonempty
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
maybe:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- invariant
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
mmorph:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-urZlZNNqGeQFe5D/ClHlR8QgGBNHTMFPtJ5S5IpflTQ=
|
||||||
|
dependencies:
|
||||||
|
- free
|
||||||
|
- functors
|
||||||
|
- transformers
|
||||||
|
newtype:
|
||||||
|
type: registry
|
||||||
|
version: 5.0.0
|
||||||
|
integrity: sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw=
|
||||||
|
dependencies:
|
||||||
|
- prelude
|
||||||
|
- safe-coerce
|
||||||
|
node-buffer:
|
||||||
|
type: registry
|
||||||
|
version: 9.0.0
|
||||||
|
integrity: sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4=
|
||||||
|
dependencies:
|
||||||
|
- arraybuffer-types
|
||||||
|
- effect
|
||||||
|
- maybe
|
||||||
|
- nullable
|
||||||
|
- st
|
||||||
|
- unsafe-coerce
|
||||||
|
nonempty:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- foldable-traversable
|
||||||
|
- maybe
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
now:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY=
|
||||||
|
dependencies:
|
||||||
|
- datetime
|
||||||
|
- effect
|
||||||
|
nullable:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- functions
|
||||||
|
- maybe
|
||||||
|
numbers:
|
||||||
|
type: registry
|
||||||
|
version: 9.0.1
|
||||||
|
integrity: sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk=
|
||||||
|
dependencies:
|
||||||
|
- functions
|
||||||
|
- maybe
|
||||||
|
ordered-collections:
|
||||||
|
type: registry
|
||||||
|
version: 3.2.0
|
||||||
|
integrity: sha256-o9jqsj5rpJmMdoe/zyufWHFjYYFTTsJpgcuCnqCO6PM=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- foldable-traversable
|
||||||
|
- gen
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- st
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
orders:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink=
|
||||||
|
dependencies:
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
parallel:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-VJbkGD0rAKX+NUEeBJbYJ78bEKaZbgow+QwQEfPB6ko=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- foldable-traversable
|
||||||
|
- functors
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- profunctor
|
||||||
|
- refs
|
||||||
|
- transformers
|
||||||
|
parsing:
|
||||||
|
type: registry
|
||||||
|
version: 10.2.0
|
||||||
|
integrity: sha256-ZDIdMFAKkst57x6BVa1aUWJnS8smoZnXsZ339Aq1mPA=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- control
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- foldable-traversable
|
||||||
|
- functions
|
||||||
|
- identity
|
||||||
|
- integers
|
||||||
|
- lazy
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nullable
|
||||||
|
- numbers
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- st
|
||||||
|
- strings
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
- unicode
|
||||||
|
- unsafe-coerce
|
||||||
|
partial:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.0
|
||||||
|
integrity: sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=
|
||||||
|
dependencies: []
|
||||||
|
pipes:
|
||||||
|
type: registry
|
||||||
|
version: 8.0.0
|
||||||
|
integrity: sha256-kvfqGM4cPA/wCcBHbp5psouFw5dZGvku2462x7ZBwSY=
|
||||||
|
dependencies:
|
||||||
|
- aff
|
||||||
|
- lists
|
||||||
|
- mmorph
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
precise-datetime:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-F7tzZ7++Ihtg3xjumzwaHQvGQg61UtEAe5MWeOlTzRY=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- datetime
|
||||||
|
- decimals
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- foldable-traversable
|
||||||
|
- formatters
|
||||||
|
- integers
|
||||||
|
- js-date
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- numbers
|
||||||
|
- prelude
|
||||||
|
- strings
|
||||||
|
- tuples
|
||||||
|
- unicode
|
||||||
|
prelude:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.1
|
||||||
|
integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0=
|
||||||
|
dependencies: []
|
||||||
|
profunctor:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.1
|
||||||
|
integrity: sha256-E58hSYdJvF2Qjf9dnWLPlJKh2Z2fLfFLkQoYi16vsFk=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- distributive
|
||||||
|
- either
|
||||||
|
- exists
|
||||||
|
- invariant
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
quickcheck:
|
||||||
|
type: registry
|
||||||
|
version: 8.0.1
|
||||||
|
integrity: sha256-ZvpccKQCvgslTXZCNmpYW4bUsFzhZd/kQUr2WmxFTGY=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- console
|
||||||
|
- control
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- exceptions
|
||||||
|
- foldable-traversable
|
||||||
|
- gen
|
||||||
|
- identity
|
||||||
|
- integers
|
||||||
|
- lazy
|
||||||
|
- lcg
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nonempty
|
||||||
|
- numbers
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- record
|
||||||
|
- st
|
||||||
|
- strings
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
random:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-CJ611a35MPCE7XQMp0rdC6MCn76znlhisiCRgboAG+Q=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- integers
|
||||||
|
record:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.0
|
||||||
|
integrity: sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg=
|
||||||
|
dependencies:
|
||||||
|
- functions
|
||||||
|
- prelude
|
||||||
|
- unsafe-coerce
|
||||||
|
refs:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s=
|
||||||
|
dependencies:
|
||||||
|
- effect
|
||||||
|
- prelude
|
||||||
|
safe-coerce:
|
||||||
|
type: registry
|
||||||
|
version: 2.0.0
|
||||||
|
integrity: sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU=
|
||||||
|
dependencies:
|
||||||
|
- unsafe-coerce
|
||||||
|
spec:
|
||||||
|
type: registry
|
||||||
|
version: 7.6.0
|
||||||
|
integrity: sha256-+merGdQbL9zWONbnt8S8J9afGJ59MQqGtS0qSd3yu4I=
|
||||||
|
dependencies:
|
||||||
|
- aff
|
||||||
|
- ansi
|
||||||
|
- arrays
|
||||||
|
- avar
|
||||||
|
- bifunctors
|
||||||
|
- control
|
||||||
|
- datetime
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- exceptions
|
||||||
|
- foldable-traversable
|
||||||
|
- fork
|
||||||
|
- identity
|
||||||
|
- integers
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- now
|
||||||
|
- ordered-collections
|
||||||
|
- parallel
|
||||||
|
- pipes
|
||||||
|
- prelude
|
||||||
|
- refs
|
||||||
|
- strings
|
||||||
|
- tailrec
|
||||||
|
- transformers
|
||||||
|
- tuples
|
||||||
|
spec-quickcheck:
|
||||||
|
type: registry
|
||||||
|
version: 5.0.0
|
||||||
|
integrity: sha256-iE0iThqZCuDGe3pwg5RvqcL8E5cRQ4txDuloCclOsCs=
|
||||||
|
dependencies:
|
||||||
|
- aff
|
||||||
|
- prelude
|
||||||
|
- quickcheck
|
||||||
|
- random
|
||||||
|
- spec
|
||||||
|
st:
|
||||||
|
type: registry
|
||||||
|
version: 6.2.0
|
||||||
|
integrity: sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY=
|
||||||
|
dependencies:
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- unsafe-coerce
|
||||||
|
strings:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.1
|
||||||
|
integrity: sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k=
|
||||||
|
dependencies:
|
||||||
|
- arrays
|
||||||
|
- control
|
||||||
|
- either
|
||||||
|
- enums
|
||||||
|
- foldable-traversable
|
||||||
|
- gen
|
||||||
|
- integers
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- nonempty
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
- unsafe-coerce
|
||||||
|
tailrec:
|
||||||
|
type: registry
|
||||||
|
version: 6.1.0
|
||||||
|
integrity: sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk=
|
||||||
|
dependencies:
|
||||||
|
- bifunctors
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- identity
|
||||||
|
- maybe
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- refs
|
||||||
|
transformers:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-Pzw40HjthX77tdPAYzjx43LK3X5Bb7ZspYAp27wksFA=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- distributive
|
||||||
|
- effect
|
||||||
|
- either
|
||||||
|
- exceptions
|
||||||
|
- foldable-traversable
|
||||||
|
- identity
|
||||||
|
- lazy
|
||||||
|
- maybe
|
||||||
|
- newtype
|
||||||
|
- prelude
|
||||||
|
- tailrec
|
||||||
|
- tuples
|
||||||
|
- unfoldable
|
||||||
|
tuples:
|
||||||
|
type: registry
|
||||||
|
version: 7.0.0
|
||||||
|
integrity: sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M=
|
||||||
|
dependencies:
|
||||||
|
- control
|
||||||
|
- invariant
|
||||||
|
- prelude
|
||||||
|
type-equality:
|
||||||
|
type: registry
|
||||||
|
version: 4.0.1
|
||||||
|
integrity: sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw=
|
||||||
|
dependencies: []
|
||||||
|
unfoldable:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg=
|
||||||
|
dependencies:
|
||||||
|
- foldable-traversable
|
||||||
|
- maybe
|
||||||
|
- partial
|
||||||
|
- prelude
|
||||||
|
- tuples
|
||||||
|
unicode:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-QJnTVZpmihEAUiMeYrfkusVoziJWp2hJsgi9bMQLue8=
|
||||||
|
dependencies:
|
||||||
|
- foldable-traversable
|
||||||
|
- maybe
|
||||||
|
- strings
|
||||||
|
unsafe-coerce:
|
||||||
|
type: registry
|
||||||
|
version: 6.0.0
|
||||||
|
integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0=
|
||||||
|
dependencies: []
|
33
spago.yaml
33
spago.yaml
@ -1,24 +1,31 @@
|
|||||||
package:
|
package:
|
||||||
|
name: pg
|
||||||
build:
|
build:
|
||||||
strict: true
|
strict: true
|
||||||
pedantic_packages: true
|
pedantic_packages: true
|
||||||
dependencies:
|
dependencies:
|
||||||
- prelude
|
- bifunctors
|
||||||
- aff
|
- control
|
||||||
|
- datetime
|
||||||
- effect
|
- effect
|
||||||
- either
|
- exceptions
|
||||||
- maybe
|
|
||||||
- foldable-traversable
|
- foldable-traversable
|
||||||
- console
|
- foreign
|
||||||
|
- lists
|
||||||
|
- maybe
|
||||||
- newtype
|
- newtype
|
||||||
- strings
|
- node-buffer
|
||||||
- stringutils
|
- precise-datetime
|
||||||
|
- prelude
|
||||||
- transformers
|
- transformers
|
||||||
- tuples
|
- unsafe-coerce
|
||||||
- typelevel-prelude
|
test:
|
||||||
name: project
|
main: Test.Main
|
||||||
|
dependencies:
|
||||||
|
- quickcheck
|
||||||
|
- spec
|
||||||
|
- spec-quickcheck
|
||||||
workspace:
|
workspace:
|
||||||
extra_packages: {}
|
extra_packages: {}
|
||||||
package_set:
|
packageSet:
|
||||||
url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.10-20230930/packages.json
|
registry: 50.5.0
|
||||||
hash: sha256-nTsd44o7/hrTdk0c6dh0wyBqhFFDJJIeKdQU6L1zv/A=
|
|
||||||
|
23
src/Data.Postgres.Geometry.purs
Normal file
23
src/Data.Postgres.Geometry.purs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module Data.Postgres.Geometry where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Newtype (class Newtype)
|
||||||
|
import Data.Show.Generic (genericShow)
|
||||||
|
|
||||||
|
newtype Point = Point { x :: Number, y :: Number }
|
||||||
|
|
||||||
|
derive instance Newtype Point _
|
||||||
|
derive instance Generic Point _
|
||||||
|
derive instance Eq Point
|
||||||
|
instance Show Point where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
newtype Circle = Circle { center :: Point, radius :: Number }
|
||||||
|
|
||||||
|
derive instance Newtype Circle _
|
||||||
|
derive instance Generic Circle _
|
||||||
|
derive instance Eq Circle
|
||||||
|
instance Show Circle where
|
||||||
|
show = genericShow
|
71
src/Data.Postgres.Range.js
Normal file
71
src/Data.Postgres.Range.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import * as Range from 'postgres-range'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @typedef {{upper: T | undefined, lower: T | undefined, lowerIncl: boolean, upperIncl: boolean}} RangeRawRecord
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {<T>(_: Range.Range<T>) => RangeRawRecord<T>} */
|
||||||
|
export const rangeRawToRecord = r => {
|
||||||
|
if (r.hasMask(Range.RANGE_EMPTY)) {
|
||||||
|
return {
|
||||||
|
upper: undefined,
|
||||||
|
lower: undefined,
|
||||||
|
lowerIncl: false,
|
||||||
|
upperIncl: false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const upper = r.upper === null ? undefined : r.upper
|
||||||
|
const lower = r.lower === null ? undefined : r.lower
|
||||||
|
return {
|
||||||
|
upper: r.hasMask(Range.RANGE_UB_INF) ? undefined : upper,
|
||||||
|
lower: r.hasMask(Range.RANGE_LB_INF) ? undefined : lower,
|
||||||
|
lowerIncl: r.hasMask(Range.RANGE_LB_INC),
|
||||||
|
upperIncl: r.hasMask(Range.RANGE_UB_INC),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {<T>(_: RangeRawRecord<T>) => Range.Range<T>} */
|
||||||
|
export const rangeRawFromRecord = r => {
|
||||||
|
const upper = r.upper === undefined ? null : r.upper
|
||||||
|
const lower = r.lower === undefined ? null : r.lower
|
||||||
|
if (upper === null && lower === null) {
|
||||||
|
// @ts-ignore
|
||||||
|
return new Range.Range(lower, upper, Range.RANGE_EMPTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mask = 0
|
||||||
|
if (upper === null) {
|
||||||
|
mask |= Range.RANGE_UB_INF
|
||||||
|
} else if (r.upperIncl) {
|
||||||
|
mask |= Range.RANGE_UB_INC
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lower === null) {
|
||||||
|
mask |= Range.RANGE_LB_INF
|
||||||
|
} else if (r.lowerIncl) {
|
||||||
|
mask |= Range.RANGE_LB_INC
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Range.Range(lower, upper, mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {<T>(r: Range.Range<T>) => () => string} */
|
||||||
|
export const rangeRawSerialize = r => () => {
|
||||||
|
return Range.serialize(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {<T>(r: string) => (f: (s: string) => () => T) => () => Range.Range<T>} */
|
||||||
|
export const rangeRawParse = r => f => () => {
|
||||||
|
return Range.parse(r, s => f(s)())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {(r: unknown) => () => Range.Range<unknown>} */
|
||||||
|
export const readRangeRaw = r => () => {
|
||||||
|
if (r instanceof Range.Range) {
|
||||||
|
return r
|
||||||
|
} else {
|
||||||
|
throw new TypeError(`expected instance of Range, found ${r}`)
|
||||||
|
}
|
||||||
|
}
|
122
src/Data.Postgres.Range.purs
Normal file
122
src/Data.Postgres.Range.purs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
module Data.Postgres.Range where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Alt ((<|>))
|
||||||
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Maybe (Maybe(..), fromMaybe)
|
||||||
|
import Data.Newtype (class Newtype, unwrap)
|
||||||
|
import Data.Postgres (class Deserialize, class Rep, class Serialize, RepT, deserialize, serialize, smash)
|
||||||
|
import Data.Postgres.Raw (Raw)
|
||||||
|
import Data.Postgres.Raw as Raw
|
||||||
|
import Data.Show.Generic (genericShow)
|
||||||
|
import Effect (Effect)
|
||||||
|
import Foreign (unsafeToForeign)
|
||||||
|
|
||||||
|
type RangeRawRecord = { upper :: Raw, lower :: Raw, lowerIncl :: Boolean, upperIncl :: Boolean }
|
||||||
|
|
||||||
|
foreign import data RangeRaw :: Type
|
||||||
|
foreign import readRangeRaw :: Raw -> Effect RangeRaw
|
||||||
|
foreign import rangeRawToRecord :: RangeRaw -> RangeRawRecord
|
||||||
|
foreign import rangeRawFromRecord :: RangeRawRecord -> RangeRaw
|
||||||
|
foreign import rangeRawParse :: String -> (String -> Effect Raw) -> Effect RangeRaw
|
||||||
|
foreign import rangeRawSerialize :: RangeRaw -> Effect String
|
||||||
|
|
||||||
|
rangeFromRaw :: forall a. Deserialize a => RangeRawRecord -> RepT (Range a)
|
||||||
|
rangeFromRaw raw = do
|
||||||
|
upper' :: Maybe a <- deserialize raw.upper
|
||||||
|
lower' :: Maybe a <- deserialize raw.lower
|
||||||
|
pure $ Range { upper: makeBound raw.upperIncl <$> upper', lower: makeBound raw.lowerIncl <$> lower' }
|
||||||
|
|
||||||
|
rangeToRaw :: forall a. Serialize a => Range a -> RepT RangeRawRecord
|
||||||
|
rangeToRaw r = do
|
||||||
|
upper' <- serialize $ boundValue <$> upper r
|
||||||
|
lower' <- serialize $ boundValue <$> lower r
|
||||||
|
pure $ { upper: upper', lower: lower', upperIncl: fromMaybe false $ boundIsInclusive <$> upper r, lowerIncl: fromMaybe false $ boundIsInclusive <$> lower r }
|
||||||
|
|
||||||
|
data Bound a = BoundIncl a | BoundExcl a
|
||||||
|
|
||||||
|
derive instance Generic (Bound a) _
|
||||||
|
derive instance Eq a => Eq (Bound a)
|
||||||
|
instance Show a => Show (Bound a) where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
boundValue :: forall a. Bound a -> a
|
||||||
|
boundValue (BoundIncl a) = a
|
||||||
|
boundValue (BoundExcl a) = a
|
||||||
|
|
||||||
|
boundIsInclusive :: forall a. Bound a -> Boolean
|
||||||
|
boundIsInclusive (BoundIncl _) = true
|
||||||
|
boundIsInclusive (BoundExcl _) = false
|
||||||
|
|
||||||
|
upper :: forall a. Range a -> Maybe (Bound a)
|
||||||
|
upper = _.upper <<< unwrap
|
||||||
|
|
||||||
|
lower :: forall a. Range a -> Maybe (Bound a)
|
||||||
|
lower = _.lower <<< unwrap
|
||||||
|
|
||||||
|
makeBound :: forall a. Boolean -> a -> Bound a
|
||||||
|
makeBound i a
|
||||||
|
| i = BoundIncl a
|
||||||
|
| otherwise = BoundExcl a
|
||||||
|
|
||||||
|
newtype Range a = Range { upper :: Maybe (Bound a), lower :: Maybe (Bound a) }
|
||||||
|
|
||||||
|
derive instance Generic (Range a) _
|
||||||
|
derive instance Newtype (Range a) _
|
||||||
|
derive instance Eq a => Eq (Range a)
|
||||||
|
instance Show a => Show (Range a) where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
instance (Ord a, Rep a) => Serialize (Range a) where
|
||||||
|
serialize a = do
|
||||||
|
raw <- rangeToRaw a
|
||||||
|
pure $ Raw.unsafeFromForeign $ unsafeToForeign $ rangeRawFromRecord raw
|
||||||
|
|
||||||
|
instance (Ord a, Rep a) => Deserialize (Range a) where
|
||||||
|
deserialize raw = do
|
||||||
|
range :: RangeRaw <- lift $ readRangeRaw raw
|
||||||
|
rangeFromRaw $ rangeRawToRecord range
|
||||||
|
|
||||||
|
instance Monoid (Range a) where
|
||||||
|
mempty = Range { upper: Nothing, lower: Nothing }
|
||||||
|
|
||||||
|
instance Semigroup (Range a) where
|
||||||
|
append (Range { upper: au, lower: al }) (Range { upper: bu, lower: bl }) = Range ({ upper: bu <|> au, lower: bl <|> al })
|
||||||
|
|
||||||
|
parseSQL :: forall a. Rep a => (String -> RepT a) -> String -> RepT (Range a)
|
||||||
|
parseSQL fromString sql = do
|
||||||
|
range <- lift $ rangeRawParse sql $ smash <<< (serialize <=< fromString)
|
||||||
|
rangeFromRaw $ rangeRawToRecord range
|
||||||
|
|
||||||
|
printSQL :: forall a. Rep a => Range a -> RepT String
|
||||||
|
printSQL range = do
|
||||||
|
record <- rangeToRaw range
|
||||||
|
lift $ rangeRawSerialize $ rangeRawFromRecord record
|
||||||
|
|
||||||
|
contains :: forall a. Ord a => a -> Range a -> Boolean
|
||||||
|
contains a r =
|
||||||
|
let
|
||||||
|
upperOk
|
||||||
|
| Just (BoundIncl u) <- upper r = u >= a
|
||||||
|
| Just (BoundExcl u) <- upper r = u > a
|
||||||
|
| otherwise = true
|
||||||
|
lowerOk
|
||||||
|
| Just (BoundIncl u) <- lower r = u <= a
|
||||||
|
| Just (BoundExcl u) <- lower r = u < a
|
||||||
|
| otherwise = true
|
||||||
|
in
|
||||||
|
upperOk && lowerOk
|
||||||
|
|
||||||
|
gte :: forall a. Ord a => a -> Range a
|
||||||
|
gte a = Range { upper: Just $ BoundIncl a, lower: Nothing }
|
||||||
|
|
||||||
|
gt :: forall a. Ord a => a -> Range a
|
||||||
|
gt a = Range { upper: Just $ BoundExcl a, lower: Nothing }
|
||||||
|
|
||||||
|
lt :: forall a. Ord a => a -> Range a
|
||||||
|
lt a = Range { upper: Nothing, lower: Just $ BoundExcl a }
|
||||||
|
|
||||||
|
lte :: forall a. Ord a => a -> Range a
|
||||||
|
lte a = Range { upper: Nothing, lower: Just $ BoundIncl a }
|
30
src/Data.Postgres.Raw.js
Normal file
30
src/Data.Postgres.Raw.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/** @type {(raw: unknown) => string} */
|
||||||
|
export const rawToString = raw =>
|
||||||
|
typeof raw === 'undefined'
|
||||||
|
? 'undefined'
|
||||||
|
: typeof raw === 'string'
|
||||||
|
? raw
|
||||||
|
: typeof raw === 'number' ||
|
||||||
|
typeof raw === 'boolean' ||
|
||||||
|
typeof raw === 'symbol'
|
||||||
|
? raw.toString()
|
||||||
|
: typeof raw === 'object'
|
||||||
|
? raw === null
|
||||||
|
? 'null'
|
||||||
|
: `[${raw.constructor.name}]`
|
||||||
|
: 'unknown'
|
||||||
|
|
||||||
|
/** @type {(a: unknown) => (b: unknown) => boolean} */
|
||||||
|
export const rawEq = a => b =>
|
||||||
|
typeof a === 'undefined' && typeof b === 'undefined'
|
||||||
|
? true
|
||||||
|
: typeof a === typeof b &&
|
||||||
|
['number', 'boolean', 'symbol', 'string'].includes(typeof a)
|
||||||
|
? a === b
|
||||||
|
: typeof a === 'object' && typeof b === 'object'
|
||||||
|
? a === null && b === null
|
||||||
|
? true
|
||||||
|
: a instanceof Array && b instanceof Array
|
||||||
|
? a.every((a_, ix) => rawEq(a_)(b[ix]))
|
||||||
|
: false
|
||||||
|
: false
|
22
src/Data.Postgres.Raw.purs
Normal file
22
src/Data.Postgres.Raw.purs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
module Data.Postgres.Raw where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Foreign (Foreign)
|
||||||
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
|
||||||
|
foreign import data Raw :: Type
|
||||||
|
foreign import rawToString :: Raw -> String
|
||||||
|
foreign import rawEq :: Raw -> Raw -> Boolean
|
||||||
|
|
||||||
|
instance Show Raw where
|
||||||
|
show = rawToString
|
||||||
|
|
||||||
|
instance Eq Raw where
|
||||||
|
eq = rawEq
|
||||||
|
|
||||||
|
unsafeFromForeign :: Foreign -> Raw
|
||||||
|
unsafeFromForeign = unsafeCoerce
|
||||||
|
|
||||||
|
unsafeToForeign :: Raw -> Foreign
|
||||||
|
unsafeToForeign = unsafeCoerce
|
37
src/Data.Postgres.js
Normal file
37
src/Data.Postgres.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { getTypeParser, setTypeParser } from 'pg-types'
|
||||||
|
import * as Range from 'postgres-range'
|
||||||
|
|
||||||
|
export const null_ = null
|
||||||
|
|
||||||
|
export const modifyPgTypes = () => {
|
||||||
|
const oid = {
|
||||||
|
'text[]': 1009,
|
||||||
|
json: 114,
|
||||||
|
jsonb: 3802,
|
||||||
|
'json[]': 199,
|
||||||
|
'jsonb[]': 3807,
|
||||||
|
timestamp: 1114,
|
||||||
|
timestamptz: 1184,
|
||||||
|
'timestamp[]': 1115,
|
||||||
|
'timestamptz[]': 1185,
|
||||||
|
tsrange: 3908,
|
||||||
|
tstzrange: 3910,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const asString = a => a
|
||||||
|
const asStringArray = getTypeParser(oid['text[]'])
|
||||||
|
const asStringRange = Range.parse
|
||||||
|
|
||||||
|
setTypeParser(oid['json'], asString)
|
||||||
|
setTypeParser(oid['jsonb'], asString)
|
||||||
|
setTypeParser(oid['json[]'], asStringArray)
|
||||||
|
setTypeParser(oid['jsonb[]'], asStringArray)
|
||||||
|
|
||||||
|
setTypeParser(oid['timestamp'], asString)
|
||||||
|
setTypeParser(oid['timestamptz'], asString)
|
||||||
|
setTypeParser(oid['timestamp[]'], asStringArray)
|
||||||
|
setTypeParser(oid['timestamptz[]'], asStringArray)
|
||||||
|
setTypeParser(oid['tsrange'], asStringRange)
|
||||||
|
setTypeParser(oid['tstzrange'], asStringRange)
|
||||||
|
}
|
167
src/Data.Postgres.purs
Normal file
167
src/Data.Postgres.purs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
module Data.Postgres where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Alt ((<|>))
|
||||||
|
import Control.Monad.Error.Class (liftEither, liftMaybe)
|
||||||
|
import Control.Monad.Except (Except, ExceptT, except, runExcept, runExceptT, withExceptT)
|
||||||
|
import Data.Bifunctor (lmap)
|
||||||
|
import Data.DateTime (DateTime)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.List.NonEmpty (NonEmptyList)
|
||||||
|
import Data.Maybe (Maybe(..))
|
||||||
|
import Data.Newtype (unwrap, wrap)
|
||||||
|
import Data.Postgres.Raw (Raw)
|
||||||
|
import Data.Postgres.Raw (unsafeFromForeign, unsafeToForeign) as Raw
|
||||||
|
import Data.RFC3339String as DateTime.ISO
|
||||||
|
import Data.Show.Generic (genericShow)
|
||||||
|
import Data.Traversable (traverse)
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Exception (error)
|
||||||
|
import Foreign (ForeignError)
|
||||||
|
import Foreign as F
|
||||||
|
import Node.Buffer (Buffer)
|
||||||
|
|
||||||
|
newtype JSON = JSON String
|
||||||
|
|
||||||
|
foreign import null_ :: Raw
|
||||||
|
|
||||||
|
-- | Important! This effect MUST be evaluated to guarantee
|
||||||
|
-- | that (de)serialization will work for timestamp and JSON types.
|
||||||
|
-- |
|
||||||
|
-- | This mutates the `pg-types`, overriding the default deserialization
|
||||||
|
-- | behavior for JSON and timestamp types.
|
||||||
|
foreign import modifyPgTypes :: Effect Unit
|
||||||
|
|
||||||
|
-- | The SQL value NULL
|
||||||
|
data Null = Null
|
||||||
|
|
||||||
|
derive instance Generic Null _
|
||||||
|
derive instance Eq Null
|
||||||
|
derive instance Ord Null
|
||||||
|
instance Show Null where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
-- | The serialization & deserialization monad.
|
||||||
|
type RepT a = ExceptT RepError Effect a
|
||||||
|
|
||||||
|
-- | Errors encounterable while serializing & deserializing.
|
||||||
|
data RepError
|
||||||
|
= RepErrorTypeMismatch { expected :: String, found :: String }
|
||||||
|
| RepErrorInvalid String
|
||||||
|
| RepErrorForeign ForeignError
|
||||||
|
| RepErrorOther String
|
||||||
|
| RepErrorMultiple (NonEmptyList RepError)
|
||||||
|
|
||||||
|
derive instance Generic RepError _
|
||||||
|
derive instance Eq RepError
|
||||||
|
instance Show RepError where
|
||||||
|
show a = genericShow a
|
||||||
|
|
||||||
|
instance Semigroup RepError where
|
||||||
|
append (RepErrorMultiple as) (RepErrorMultiple bs) = RepErrorMultiple (as <> bs)
|
||||||
|
append (RepErrorMultiple as) b = RepErrorMultiple (as <> pure b)
|
||||||
|
append a (RepErrorMultiple bs) = RepErrorMultiple (pure a <> bs)
|
||||||
|
append a b = RepErrorMultiple (pure a <> pure b)
|
||||||
|
|
||||||
|
-- | Flatten to an Effect, rendering any `RepError`s to `String` using `Show`.
|
||||||
|
smash :: forall a. RepT a -> Effect a
|
||||||
|
smash = liftEither <=< map (lmap (error <<< show)) <<< runExceptT
|
||||||
|
|
||||||
|
-- | Lift an `Except` returned by functions in the `Foreign` module to `RepT`
|
||||||
|
liftForeign :: forall a. Except (NonEmptyList ForeignError) a -> RepT a
|
||||||
|
liftForeign = except <<< runExcept <<< withExceptT (RepErrorMultiple <<< map RepErrorForeign)
|
||||||
|
|
||||||
|
-- | Serialize data of type `a` to a `Raw` SQL value.
|
||||||
|
class Serialize a where
|
||||||
|
serialize :: a -> RepT Raw
|
||||||
|
|
||||||
|
-- | Deserialize data of type `a` from a `Raw` SQL value.
|
||||||
|
class Deserialize a where
|
||||||
|
deserialize :: Raw -> RepT a
|
||||||
|
|
||||||
|
-- | A type which is `Rep`resentable as a SQL value.
|
||||||
|
class (Serialize a, Deserialize a) <= Rep a
|
||||||
|
|
||||||
|
instance (Serialize a, Deserialize a) => Rep a
|
||||||
|
|
||||||
|
-- | Coerces the value to `Raw`
|
||||||
|
unsafeSerializeCoerce :: forall m a. Monad m => a -> m Raw
|
||||||
|
unsafeSerializeCoerce = pure <<< Raw.unsafeFromForeign <<< F.unsafeToForeign
|
||||||
|
|
||||||
|
instance Serialize Raw where
|
||||||
|
serialize = pure
|
||||||
|
|
||||||
|
instance Serialize Null where
|
||||||
|
serialize _ = unsafeSerializeCoerce null_
|
||||||
|
|
||||||
|
-- | `bytea`
|
||||||
|
instance Serialize Buffer where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize Int where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize Boolean where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize String where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize Number where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize Char where
|
||||||
|
serialize = unsafeSerializeCoerce
|
||||||
|
|
||||||
|
instance Serialize DateTime where
|
||||||
|
serialize = serialize <<< unwrap <<< DateTime.ISO.fromDateTime
|
||||||
|
|
||||||
|
instance Serialize a => Serialize (Maybe a) where
|
||||||
|
serialize (Just a) = serialize a
|
||||||
|
serialize Nothing = unsafeSerializeCoerce null_
|
||||||
|
|
||||||
|
instance Serialize a => Serialize (Array a) where
|
||||||
|
serialize = unsafeSerializeCoerce <=< traverse serialize
|
||||||
|
|
||||||
|
instance Deserialize Raw where
|
||||||
|
deserialize = pure
|
||||||
|
|
||||||
|
-- | `bytea`
|
||||||
|
instance Deserialize Buffer where
|
||||||
|
deserialize = liftForeign <<< (F.unsafeReadTagged "Buffer") <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize Null where
|
||||||
|
deserialize = map (const Null) <<< liftForeign <<< F.readNullOrUndefined <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize Int where
|
||||||
|
deserialize = liftForeign <<< F.readInt <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize Boolean where
|
||||||
|
deserialize = liftForeign <<< F.readBoolean <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize String where
|
||||||
|
deserialize = liftForeign <<< F.readString <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize Number where
|
||||||
|
deserialize = liftForeign <<< F.readNumber <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize Char where
|
||||||
|
deserialize = liftForeign <<< F.readChar <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize DateTime where
|
||||||
|
deserialize raw = do
|
||||||
|
s :: String <- deserialize raw
|
||||||
|
let invalid = RepErrorInvalid $ "Not a valid ISO8601 string: `" <> s <> "`"
|
||||||
|
liftMaybe invalid $ DateTime.ISO.toDateTime $ wrap s
|
||||||
|
|
||||||
|
instance Deserialize a => Deserialize (Array a) where
|
||||||
|
deserialize = traverse (deserialize <<< Raw.unsafeFromForeign) <=< liftForeign <<< F.readArray <<< Raw.unsafeToForeign
|
||||||
|
|
||||||
|
instance Deserialize a => Deserialize (Maybe a) where
|
||||||
|
deserialize raw =
|
||||||
|
let
|
||||||
|
nothing = const Nothing <$> deserialize @Null raw
|
||||||
|
just = Just <$> deserialize raw
|
||||||
|
in
|
||||||
|
just <|> nothing
|
4
src/Effect.Postgres.purs
Normal file
4
src/Effect.Postgres.purs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Effect.Pg where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
module Main where
|
|
||||||
|
|
||||||
import Prelude
|
|
||||||
import Effect (Effect)
|
|
||||||
|
|
||||||
main :: Effect Unit
|
|
||||||
main = pure unit
|
|
74
test/Test.Data.Postgres.purs
Normal file
74
test/Test.Data.Postgres.purs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
module Test.Data.Postgres where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.Error.Class (liftEither)
|
||||||
|
import Control.Monad.Except (runExceptT)
|
||||||
|
import Data.DateTime (DateTime(..))
|
||||||
|
import Data.DateTime.Instant as Instant
|
||||||
|
import Data.Int as Int
|
||||||
|
import Data.Maybe (Maybe, fromJust, fromMaybe, maybe)
|
||||||
|
import Data.Newtype (wrap)
|
||||||
|
import Data.Postgres (class Rep, Null(..), deserialize, null_, serialize, smash)
|
||||||
|
import Data.Postgres.Range as Range
|
||||||
|
import Data.Postgres.Raw (Raw)
|
||||||
|
import Data.Postgres.Raw as Raw
|
||||||
|
import Data.RFC3339String as DateTime.ISO
|
||||||
|
import Data.Tuple.Nested (type (/\), (/\))
|
||||||
|
import Effect.Class (liftEffect)
|
||||||
|
import Effect.Console (log)
|
||||||
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
|
import Foreign (unsafeToForeign)
|
||||||
|
import Partial.Unsafe (unsafePartial)
|
||||||
|
import Test.QuickCheck (class Arbitrary, (==?))
|
||||||
|
import Test.Spec (Spec, describe, it)
|
||||||
|
import Test.Spec.Assertions (shouldEqual)
|
||||||
|
import Test.Spec.QuickCheck (quickCheck)
|
||||||
|
|
||||||
|
asRaw :: forall a. a -> Raw
|
||||||
|
asRaw = Raw.unsafeFromForeign <<< unsafeToForeign
|
||||||
|
|
||||||
|
spec :: Spec Unit
|
||||||
|
spec =
|
||||||
|
let
|
||||||
|
check :: forall @a @x. Eq a => Show a => Arbitrary x => Rep a => String -> (x -> a) -> (a -> Raw) -> Spec Unit
|
||||||
|
check s xa asRaw_ =
|
||||||
|
describe s do
|
||||||
|
it "serialize" $ quickCheck \(x :: x) -> (unsafePerformEffect $ runExceptT $ serialize $ xa x) ==? pure (asRaw_ $ xa x)
|
||||||
|
it "deserialize" $ quickCheck \(x :: x) -> (unsafePerformEffect $ runExceptT $ deserialize $ asRaw_ $ xa x) ==? pure (xa x)
|
||||||
|
|
||||||
|
check_ :: forall @a. Eq a => Show a => Arbitrary a => Rep a => String -> Spec Unit
|
||||||
|
check_ s = check @a @a s identity asRaw
|
||||||
|
|
||||||
|
dateTimeFromArbitrary :: Int -> DateTime
|
||||||
|
dateTimeFromArbitrary = Instant.toDateTime <<< unsafePartial fromJust <<< Instant.instant <<< wrap <<< Int.toNumber
|
||||||
|
in
|
||||||
|
describe "Data.Postgres" do
|
||||||
|
check_ @Int "Int"
|
||||||
|
check_ @String "String"
|
||||||
|
check_ @Boolean "Boolean"
|
||||||
|
check_ @Number "Number"
|
||||||
|
check_ @Char "Char"
|
||||||
|
|
||||||
|
check @(Maybe String) "Maybe String" identity (maybe null_ asRaw)
|
||||||
|
check @(Array String) "Array String" identity asRaw
|
||||||
|
check @DateTime "DateTime" dateTimeFromArbitrary (asRaw <<< DateTime.ISO.fromDateTime)
|
||||||
|
|
||||||
|
describe "Null" do
|
||||||
|
it "serialize" $ liftEffect $ shouldEqual null_ =<< (smash $ serialize Null)
|
||||||
|
it "deserialize" $ liftEffect $ shouldEqual Null =<< (smash $ deserialize null_)
|
||||||
|
|
||||||
|
describe "Range" do
|
||||||
|
it "deserialize" do
|
||||||
|
quickCheck \(up /\ lo /\ uinc /\ linc :: Int /\ Int /\ Boolean /\ Boolean) -> unsafePerformEffect do
|
||||||
|
let
|
||||||
|
record =
|
||||||
|
{ upper: unsafePerformEffect $ smash $ serialize up
|
||||||
|
, lower: unsafePerformEffect $ smash $ serialize lo
|
||||||
|
, upperIncl: uinc
|
||||||
|
, lowerIncl: linc
|
||||||
|
}
|
||||||
|
raw = asRaw $ Range.rangeRawFromRecord record
|
||||||
|
exp :: Range.Range Int <- smash $ Range.rangeFromRaw record
|
||||||
|
act :: Range.Range Int <- smash $ deserialize raw
|
||||||
|
pure $ exp ==? act
|
13
test/Test.Main.purs
Normal file
13
test/Test.Main.purs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module Test.Main where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Aff (launchAff_)
|
||||||
|
import Test.Data.Postgres as Test.Data.Postgres
|
||||||
|
import Test.Spec.Reporter (consoleReporter)
|
||||||
|
import Test.Spec.Runner (runSpec)
|
||||||
|
|
||||||
|
main :: Effect Unit
|
||||||
|
main = launchAff_ $ runSpec [ consoleReporter ] do
|
||||||
|
Test.Data.Postgres.spec
|
Loading…
Reference in New Issue
Block a user