fmt
This commit is contained in:
parent
e2018dbbef
commit
3c4f732f2c
8
.prettierrc.cjs
Normal file
8
.prettierrc.cjs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
tabWidth: 2,
|
||||||
|
trailingComma: 'all',
|
||||||
|
singleQuote: true,
|
||||||
|
semi: false,
|
||||||
|
arrowParens: 'avoid',
|
||||||
|
plugins: [],
|
||||||
|
}
|
121
.spec-results
Normal file
121
.spec-results
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
"Axon Request Parts Body extracts a JSON body",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Body extracts a string body from a buffer",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Body extracts a string body from a cached string",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Body extracts a string body from a readable stream",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path ... but does if ends in IgnoreRest",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path does not partially match a route ...",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path extracts an int",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path extracts an int and a string",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path matches a route matching literal",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts Path matches a route matching multiple literals",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts a string body",
|
||||||
|
{
|
||||||
|
"timestamp": "1733092879598.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts a string body from a buffer",
|
||||||
|
{
|
||||||
|
"timestamp": "1733093315868.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts a string body from a cached string",
|
||||||
|
{
|
||||||
|
"timestamp": "1733093315868.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts a string body from a readable stream",
|
||||||
|
{
|
||||||
|
"timestamp": "1733093315868.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts method, path, JSON body",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Axon Request Parts extracts the whole request",
|
||||||
|
{
|
||||||
|
"timestamp": "1733094319834.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Parts extracts the whole request",
|
||||||
|
{
|
||||||
|
"timestamp": "1733092816548.0",
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
@ -12,8 +12,5 @@
|
|||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"strict": true
|
"strict": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["./scripts/*.js", "src/**/*.js"]
|
||||||
"./scripts/*.js",
|
|
||||||
"src/**/*.js"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
20
scripts/common.js
Normal file
20
scripts/common.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import Fs from 'fs/promises'
|
||||||
|
import Path from 'path'
|
||||||
|
|
||||||
|
export const rootDir = Path.resolve(__dirname, '..')
|
||||||
|
|
||||||
|
export const packageDirs = async () => ['./src']
|
||||||
|
|
||||||
|
export const packageSources = async () => {
|
||||||
|
const packages = await packageDirs()
|
||||||
|
const sources = []
|
||||||
|
for (const p of packages) {
|
||||||
|
const files = await Fs.readdir(p, { recursive: true, withFileTypes: true })
|
||||||
|
sources.push(
|
||||||
|
...files.flatMap(e =>
|
||||||
|
e.isFile() ? [Path.resolve(rootDir, e.path, e.name)] : [],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return sources
|
||||||
|
}
|
38
scripts/fmt.js
Normal file
38
scripts/fmt.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { $ } from 'bun'
|
||||||
|
import { packageSources } from './common.js'
|
||||||
|
|
||||||
|
const check = process.argv.includes('--check')
|
||||||
|
|
||||||
|
const sources = await packageSources()
|
||||||
|
const purs = sources.filter(f => f.endsWith('.purs'))
|
||||||
|
const js = sources
|
||||||
|
.filter(f => f.endsWith('.js'))
|
||||||
|
.concat(['./scripts/**/*.js', '.prettierrc.cjs'])
|
||||||
|
const json = ['package.json', 'jsconfig.json']
|
||||||
|
const yml = sources.filter(f => f.endsWith('.yaml')).concat(['spago.yaml'])
|
||||||
|
|
||||||
|
/** @type {(parser: string, ps: string[]) => import("bun").ShellPromise} */
|
||||||
|
const prettier = (parser, ps) =>
|
||||||
|
$`bun x prettier ${check ? '--check' : '--write'} '--parser' ${parser} ${ps}`
|
||||||
|
|
||||||
|
const procs = [
|
||||||
|
() => prettier('babel', js),
|
||||||
|
() => prettier('json', json),
|
||||||
|
() => prettier('yaml', yml),
|
||||||
|
() =>
|
||||||
|
prettier(
|
||||||
|
'markdown',
|
||||||
|
sources.filter(f => f.endsWith('.md')).concat(['README.md']),
|
||||||
|
),
|
||||||
|
() => $`bun x purs-tidy ${check ? 'check' : 'format-in-place'} ${purs}`,
|
||||||
|
]
|
||||||
|
.map(go => async () => {
|
||||||
|
const p = await go().nothrow().quiet()
|
||||||
|
if (p.exitCode === 0) return
|
||||||
|
process.stdout.write(p.stdout)
|
||||||
|
process.stderr.write(p.stderr)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
.reduce((acc, go) => acc.then(() => go()), Promise.resolve())
|
||||||
|
|
||||||
|
await procs
|
324
spago.lock
324
spago.lock
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"tower": {
|
"axon": {
|
||||||
"path": "./",
|
"path": "./",
|
||||||
"core": {
|
"core": {
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
@ -101,8 +101,84 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"dependencies": [],
|
"dependencies": [
|
||||||
"build_plan": []
|
"spec",
|
||||||
|
"spec-node"
|
||||||
|
],
|
||||||
|
"build_plan": [
|
||||||
|
"aff",
|
||||||
|
"ansi",
|
||||||
|
"argonaut-codecs",
|
||||||
|
"argonaut-core",
|
||||||
|
"arraybuffer-types",
|
||||||
|
"arrays",
|
||||||
|
"avar",
|
||||||
|
"bifunctors",
|
||||||
|
"catenable-lists",
|
||||||
|
"console",
|
||||||
|
"const",
|
||||||
|
"contravariant",
|
||||||
|
"control",
|
||||||
|
"datetime",
|
||||||
|
"distributive",
|
||||||
|
"effect",
|
||||||
|
"either",
|
||||||
|
"enums",
|
||||||
|
"exceptions",
|
||||||
|
"exists",
|
||||||
|
"exitcodes",
|
||||||
|
"foldable-traversable",
|
||||||
|
"foreign",
|
||||||
|
"foreign-object",
|
||||||
|
"fork",
|
||||||
|
"free",
|
||||||
|
"functions",
|
||||||
|
"functors",
|
||||||
|
"gen",
|
||||||
|
"identity",
|
||||||
|
"integers",
|
||||||
|
"invariant",
|
||||||
|
"js-date",
|
||||||
|
"lazy",
|
||||||
|
"lists",
|
||||||
|
"maybe",
|
||||||
|
"mmorph",
|
||||||
|
"newtype",
|
||||||
|
"node-buffer",
|
||||||
|
"node-event-emitter",
|
||||||
|
"node-fs",
|
||||||
|
"node-path",
|
||||||
|
"node-process",
|
||||||
|
"node-streams",
|
||||||
|
"nonempty",
|
||||||
|
"now",
|
||||||
|
"nullable",
|
||||||
|
"numbers",
|
||||||
|
"open-memoize",
|
||||||
|
"optparse",
|
||||||
|
"ordered-collections",
|
||||||
|
"orders",
|
||||||
|
"parallel",
|
||||||
|
"partial",
|
||||||
|
"pipes",
|
||||||
|
"posix-types",
|
||||||
|
"prelude",
|
||||||
|
"profunctor",
|
||||||
|
"record",
|
||||||
|
"refs",
|
||||||
|
"safe-coerce",
|
||||||
|
"spec",
|
||||||
|
"spec-node",
|
||||||
|
"st",
|
||||||
|
"strings",
|
||||||
|
"tailrec",
|
||||||
|
"transformers",
|
||||||
|
"tuples",
|
||||||
|
"type-equality",
|
||||||
|
"typelevel-prelude",
|
||||||
|
"unfoldable",
|
||||||
|
"unsafe-coerce"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -658,6 +734,16 @@
|
|||||||
"foreign"
|
"foreign"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"ansi": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "7.0.0",
|
||||||
|
"integrity": "sha256-ZMB6HD+q9CXvn9fRCmJ8dvuDrOVHcjombL3oNOerVnE=",
|
||||||
|
"dependencies": [
|
||||||
|
"foldable-traversable",
|
||||||
|
"lists",
|
||||||
|
"strings"
|
||||||
|
]
|
||||||
|
},
|
||||||
"argonaut-codecs": {
|
"argonaut-codecs": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
@ -721,6 +807,19 @@
|
|||||||
"unsafe-coerce"
|
"unsafe-coerce"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"avar": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "5.0.0",
|
||||||
|
"integrity": "sha256-e7hf0x4hEpcygXP0LtvfvAQ49Bbj2aWtZT3gqM///0A=",
|
||||||
|
"dependencies": [
|
||||||
|
"aff",
|
||||||
|
"effect",
|
||||||
|
"either",
|
||||||
|
"exceptions",
|
||||||
|
"functions",
|
||||||
|
"maybe"
|
||||||
|
]
|
||||||
|
},
|
||||||
"b64": {
|
"b64": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
@ -749,6 +848,20 @@
|
|||||||
"tuples"
|
"tuples"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"catenable-lists": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "7.0.0",
|
||||||
|
"integrity": "sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA=",
|
||||||
|
"dependencies": [
|
||||||
|
"control",
|
||||||
|
"foldable-traversable",
|
||||||
|
"lists",
|
||||||
|
"maybe",
|
||||||
|
"prelude",
|
||||||
|
"tuples",
|
||||||
|
"unfoldable"
|
||||||
|
]
|
||||||
|
},
|
||||||
"console": {
|
"console": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
@ -892,6 +1005,14 @@
|
|||||||
"unsafe-coerce"
|
"unsafe-coerce"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"exitcodes": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"integrity": "sha256-4wxViTbyOoyKJ/WaRGI6+hZmgMKI5Miv16lSwefiLSM=",
|
||||||
|
"dependencies": [
|
||||||
|
"enums"
|
||||||
|
]
|
||||||
|
},
|
||||||
"ezfetch": {
|
"ezfetch": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@ -994,6 +1115,35 @@
|
|||||||
"unfoldable"
|
"unfoldable"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"fork": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "6.0.0",
|
||||||
|
"integrity": "sha256-X7u0SuCvFbLbzuNEKLBNuWjmcroqMqit4xEzpQwAP7E=",
|
||||||
|
"dependencies": [
|
||||||
|
"aff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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": {
|
"functions": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
@ -1145,6 +1295,16 @@
|
|||||||
"prelude"
|
"prelude"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"mmorph": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "7.0.0",
|
||||||
|
"integrity": "sha256-urZlZNNqGeQFe5D/ClHlR8QgGBNHTMFPtJ5S5IpflTQ=",
|
||||||
|
"dependencies": [
|
||||||
|
"free",
|
||||||
|
"functors",
|
||||||
|
"transformers"
|
||||||
|
]
|
||||||
|
},
|
||||||
"newtype": {
|
"newtype": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
@ -1232,6 +1392,22 @@
|
|||||||
"effect"
|
"effect"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node-process": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "11.2.0",
|
||||||
|
"integrity": "sha256-+2MQDYChjGbVbapCyJtuWYwD41jk+BntF/kcOTKBMVs=",
|
||||||
|
"dependencies": [
|
||||||
|
"effect",
|
||||||
|
"foreign",
|
||||||
|
"foreign-object",
|
||||||
|
"maybe",
|
||||||
|
"node-event-emitter",
|
||||||
|
"node-streams",
|
||||||
|
"posix-types",
|
||||||
|
"prelude",
|
||||||
|
"unsafe-coerce"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node-streams": {
|
"node-streams": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
@ -1288,6 +1464,22 @@
|
|||||||
"maybe"
|
"maybe"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"open-memoize": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "6.2.0",
|
||||||
|
"integrity": "sha256-p1m7wF3aHQ80yUvqMs20OTMl496WS6YpKlmI2Nkg9j0=",
|
||||||
|
"dependencies": [
|
||||||
|
"either",
|
||||||
|
"integers",
|
||||||
|
"lazy",
|
||||||
|
"lists",
|
||||||
|
"maybe",
|
||||||
|
"partial",
|
||||||
|
"prelude",
|
||||||
|
"strings",
|
||||||
|
"tuples"
|
||||||
|
]
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
@ -1300,6 +1492,43 @@
|
|||||||
"tuples"
|
"tuples"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"optparse": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "5.0.1",
|
||||||
|
"integrity": "sha256-cEzEkNW4q0gZlXl4z0zn+H2vs6l2UAp7NPHCsois73k=",
|
||||||
|
"dependencies": [
|
||||||
|
"aff",
|
||||||
|
"arrays",
|
||||||
|
"bifunctors",
|
||||||
|
"console",
|
||||||
|
"control",
|
||||||
|
"effect",
|
||||||
|
"either",
|
||||||
|
"enums",
|
||||||
|
"exists",
|
||||||
|
"exitcodes",
|
||||||
|
"foldable-traversable",
|
||||||
|
"free",
|
||||||
|
"gen",
|
||||||
|
"integers",
|
||||||
|
"lazy",
|
||||||
|
"lists",
|
||||||
|
"maybe",
|
||||||
|
"newtype",
|
||||||
|
"node-buffer",
|
||||||
|
"node-process",
|
||||||
|
"node-streams",
|
||||||
|
"nonempty",
|
||||||
|
"numbers",
|
||||||
|
"open-memoize",
|
||||||
|
"partial",
|
||||||
|
"prelude",
|
||||||
|
"strings",
|
||||||
|
"tailrec",
|
||||||
|
"transformers",
|
||||||
|
"tuples"
|
||||||
|
]
|
||||||
|
},
|
||||||
"ordered-collections": {
|
"ordered-collections": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
@ -1351,6 +1580,29 @@
|
|||||||
"integrity": "sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=",
|
"integrity": "sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=",
|
||||||
"dependencies": []
|
"dependencies": []
|
||||||
},
|
},
|
||||||
|
"pipes": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "8.0.0",
|
||||||
|
"integrity": "sha256-kvfqGM4cPA/wCcBHbp5psouFw5dZGvku2462x7ZBwSY=",
|
||||||
|
"dependencies": [
|
||||||
|
"aff",
|
||||||
|
"lists",
|
||||||
|
"mmorph",
|
||||||
|
"prelude",
|
||||||
|
"tailrec",
|
||||||
|
"transformers",
|
||||||
|
"tuples"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"posix-types": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "6.0.0",
|
||||||
|
"integrity": "sha256-ZfFz8RR1lee/o/Prccyeut3Q+9tYd08mlR72sIh6GzA=",
|
||||||
|
"dependencies": [
|
||||||
|
"maybe",
|
||||||
|
"prelude"
|
||||||
|
]
|
||||||
|
},
|
||||||
"prelude": {
|
"prelude": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
@ -1415,6 +1667,72 @@
|
|||||||
"variant"
|
"variant"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"spec": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "8.1.1",
|
||||||
|
"integrity": "sha256-EM7UfQIaSgiw13LJ4ZASkfYmmRDKIlec3nYbGKFqGhk=",
|
||||||
|
"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-node": {
|
||||||
|
"type": "registry",
|
||||||
|
"version": "0.0.3",
|
||||||
|
"integrity": "sha256-Bjzg6l4uOfMN/FV0SKuT1Mm8eMP9sloLGVcY/0MeMnI=",
|
||||||
|
"dependencies": [
|
||||||
|
"aff",
|
||||||
|
"argonaut-codecs",
|
||||||
|
"argonaut-core",
|
||||||
|
"arrays",
|
||||||
|
"control",
|
||||||
|
"datetime",
|
||||||
|
"effect",
|
||||||
|
"either",
|
||||||
|
"foldable-traversable",
|
||||||
|
"identity",
|
||||||
|
"integers",
|
||||||
|
"maybe",
|
||||||
|
"newtype",
|
||||||
|
"node-buffer",
|
||||||
|
"node-fs",
|
||||||
|
"node-process",
|
||||||
|
"now",
|
||||||
|
"numbers",
|
||||||
|
"optparse",
|
||||||
|
"ordered-collections",
|
||||||
|
"partial",
|
||||||
|
"prelude",
|
||||||
|
"spec",
|
||||||
|
"strings",
|
||||||
|
"tuples"
|
||||||
|
]
|
||||||
|
},
|
||||||
"st": {
|
"st": {
|
||||||
"type": "registry",
|
"type": "registry",
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
|
@ -19,7 +19,9 @@ package:
|
|||||||
- web-streams
|
- web-streams
|
||||||
test:
|
test:
|
||||||
main: Test.Main
|
main: Test.Main
|
||||||
dependencies: []
|
dependencies:
|
||||||
|
- spec
|
||||||
|
- spec-node
|
||||||
workspace:
|
workspace:
|
||||||
packageSet:
|
packageSet:
|
||||||
registry: 61.2.0
|
registry: 61.2.0
|
||||||
|
@ -8,9 +8,11 @@ import Data.Show.Generic (genericShow)
|
|||||||
import Data.String as String
|
import Data.String as String
|
||||||
|
|
||||||
data Method = GET | POST | PUT | PATCH | DELETE | OPTIONS | TRACE | CONNECT
|
data Method = GET | POST | PUT | PATCH | DELETE | OPTIONS | TRACE | CONNECT
|
||||||
|
|
||||||
derive instance Generic Method _
|
derive instance Generic Method _
|
||||||
derive instance Eq Method
|
derive instance Eq Method
|
||||||
instance Show Method where show = genericShow
|
instance Show Method where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
methodToString :: Method -> String
|
methodToString :: Method -> String
|
||||||
methodToString GET = "GET"
|
methodToString GET = "GET"
|
||||||
|
@ -7,6 +7,7 @@ import Data.Newtype (class Newtype)
|
|||||||
import Node.Stream as Stream
|
import Node.Stream as Stream
|
||||||
|
|
||||||
newtype Json a = Json a
|
newtype Json a = Json a
|
||||||
|
|
||||||
derive instance Generic (Json a) _
|
derive instance Generic (Json a) _
|
||||||
derive instance Newtype (Json a) _
|
derive instance Newtype (Json a) _
|
||||||
derive newtype instance (Eq a) => Eq (Json a)
|
derive newtype instance (Eq a) => Eq (Json a)
|
||||||
@ -14,5 +15,6 @@ derive newtype instance (Ord a) => Ord (Json a)
|
|||||||
derive newtype instance (Show a) => Show (Json a)
|
derive newtype instance (Show a) => Show (Json a)
|
||||||
|
|
||||||
newtype Stream = Stream (Stream.Readable ())
|
newtype Stream = Stream (Stream.Readable ())
|
||||||
|
|
||||||
derive instance Generic Stream _
|
derive instance Generic Stream _
|
||||||
derive instance Newtype Stream _
|
derive instance Newtype Stream _
|
||||||
|
@ -2,6 +2,18 @@ module Axon.Request.Parts.Class (class RequestParts, extractRequestParts, module
|
|||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
|
import Axon.Request (Request)
|
||||||
|
import Axon.Request as Request
|
||||||
|
import Axon.Request.Method (Method)
|
||||||
|
import Axon.Request.Method as Method
|
||||||
|
import Axon.Request.Parts.Body (Json(..), Stream(..))
|
||||||
|
import Axon.Request.Parts.Body (Json(..), Stream(..)) as Parts.Body
|
||||||
|
import Axon.Request.Parts.Method (Connect, Delete, Get, Options, Patch, Post, Put, Trace)
|
||||||
|
import Axon.Request.Parts.Method (Get(..), Post(..), Put(..), Patch(..), Delete(..), Trace(..), Options(..), Connect(..)) as Parts.Method
|
||||||
|
import Axon.Request.Parts.Path (Path(..)) as Path.Parts
|
||||||
|
import Axon.Request.Parts.Path (class DiscardTupledUnits, class PathParts, Path(..), discardTupledUnits, extractPathParts)
|
||||||
|
import Axon.Response (Response)
|
||||||
|
import Axon.Response as Response
|
||||||
import Control.Alternative (guard)
|
import Control.Alternative (guard)
|
||||||
import Control.Monad.Except (ExceptT(..), runExceptT)
|
import Control.Monad.Except (ExceptT(..), runExceptT)
|
||||||
import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT)
|
import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT)
|
||||||
@ -17,18 +29,6 @@ import Data.URL as URL
|
|||||||
import Effect.Aff (Aff)
|
import Effect.Aff (Aff)
|
||||||
import Effect.Class (liftEffect)
|
import Effect.Class (liftEffect)
|
||||||
import Node.Buffer (Buffer)
|
import Node.Buffer (Buffer)
|
||||||
import Axon.Request (Request)
|
|
||||||
import Axon.Request as Request
|
|
||||||
import Axon.Request.Method (Method)
|
|
||||||
import Axon.Request.Method as Method
|
|
||||||
import Axon.Request.Parts.Body (Json(..), Stream(..))
|
|
||||||
import Axon.Request.Parts.Body (Json(..), Stream(..)) as Parts.Body
|
|
||||||
import Axon.Request.Parts.Method (Connect, Delete, Get, Options, Patch, Post, Put, Trace)
|
|
||||||
import Axon.Request.Parts.Method (Get(..), Post(..), Put(..), Patch(..), Delete(..), Trace(..), Options(..), Connect(..)) as Parts.Method
|
|
||||||
import Axon.Request.Parts.Path (Path(..)) as Path.Parts
|
|
||||||
import Axon.Request.Parts.Path (class PathParts, Path(..), extractPathParts)
|
|
||||||
import Axon.Response (Response)
|
|
||||||
import Axon.Response as Response
|
|
||||||
|
|
||||||
extractMethod :: forall @t a. RequestParts a => Newtype t a => Method -> Request -> Aff (Either Response (Maybe t))
|
extractMethod :: forall @t a. RequestParts a => Newtype t a => Method -> Request -> Aff (Either Response (Maybe t))
|
||||||
extractMethod method r =
|
extractMethod method r =
|
||||||
@ -54,13 +54,19 @@ instance RequestParts Request where
|
|||||||
instance RequestParts String where
|
instance RequestParts String where
|
||||||
extractRequestParts r =
|
extractRequestParts r =
|
||||||
Request.bodyString r
|
Request.bodyString r
|
||||||
<#> lmap (const $ Response.fromStatus 500)
|
<#> lmap (const $ Response.fromStatus 500)
|
||||||
# ExceptT
|
# ExceptT
|
||||||
# lift
|
# lift
|
||||||
# runMaybeT
|
# runMaybeT
|
||||||
# runExceptT
|
# runExceptT
|
||||||
|
|
||||||
instance PathParts a b => RequestParts (Path a b) where
|
instance RequestParts (Either Request.BodyStringError String) where
|
||||||
|
extractRequestParts r =
|
||||||
|
Request.bodyString r
|
||||||
|
<#> Just
|
||||||
|
<#> Right
|
||||||
|
|
||||||
|
instance (PathParts a b, DiscardTupledUnits b c) => RequestParts (Path a c) where
|
||||||
extractRequestParts r =
|
extractRequestParts r =
|
||||||
let
|
let
|
||||||
segments = Request.url r # URL.path # case _ of
|
segments = Request.url r # URL.path # case _ of
|
||||||
@ -75,6 +81,7 @@ instance PathParts a b => RequestParts (Path a b) where
|
|||||||
# Right
|
# Right
|
||||||
# MaybeT
|
# MaybeT
|
||||||
>>= ensureConsumed
|
>>= ensureConsumed
|
||||||
|
<#> discardTupledUnits
|
||||||
<#> Path
|
<#> Path
|
||||||
# runMaybeT
|
# runMaybeT
|
||||||
# pure
|
# pure
|
||||||
|
@ -6,6 +6,7 @@ import Data.Generic.Rep (class Generic)
|
|||||||
import Data.Newtype (class Newtype)
|
import Data.Newtype (class Newtype)
|
||||||
|
|
||||||
newtype Get a = Get a
|
newtype Get a = Get a
|
||||||
|
|
||||||
derive instance Generic (Get a) _
|
derive instance Generic (Get a) _
|
||||||
derive instance Newtype (Get a) _
|
derive instance Newtype (Get a) _
|
||||||
derive newtype instance (Eq a) => Eq (Get a)
|
derive newtype instance (Eq a) => Eq (Get a)
|
||||||
@ -13,6 +14,7 @@ derive newtype instance (Ord a) => Ord (Get a)
|
|||||||
derive newtype instance (Show a) => Show (Get a)
|
derive newtype instance (Show a) => Show (Get a)
|
||||||
|
|
||||||
newtype Post a = Post a
|
newtype Post a = Post a
|
||||||
|
|
||||||
derive instance Generic (Post a) _
|
derive instance Generic (Post a) _
|
||||||
derive instance Newtype (Post a) _
|
derive instance Newtype (Post a) _
|
||||||
derive newtype instance (Eq a) => Eq (Post a)
|
derive newtype instance (Eq a) => Eq (Post a)
|
||||||
@ -20,6 +22,7 @@ derive newtype instance (Ord a) => Ord (Post a)
|
|||||||
derive newtype instance (Show a) => Show (Post a)
|
derive newtype instance (Show a) => Show (Post a)
|
||||||
|
|
||||||
newtype Put a = Put a
|
newtype Put a = Put a
|
||||||
|
|
||||||
derive instance Generic (Put a) _
|
derive instance Generic (Put a) _
|
||||||
derive instance Newtype (Put a) _
|
derive instance Newtype (Put a) _
|
||||||
derive newtype instance (Eq a) => Eq (Put a)
|
derive newtype instance (Eq a) => Eq (Put a)
|
||||||
@ -27,6 +30,7 @@ derive newtype instance (Ord a) => Ord (Put a)
|
|||||||
derive newtype instance (Show a) => Show (Put a)
|
derive newtype instance (Show a) => Show (Put a)
|
||||||
|
|
||||||
newtype Patch a = Patch a
|
newtype Patch a = Patch a
|
||||||
|
|
||||||
derive instance Generic (Patch a) _
|
derive instance Generic (Patch a) _
|
||||||
derive instance Newtype (Patch a) _
|
derive instance Newtype (Patch a) _
|
||||||
derive newtype instance (Eq a) => Eq (Patch a)
|
derive newtype instance (Eq a) => Eq (Patch a)
|
||||||
@ -34,6 +38,7 @@ derive newtype instance (Ord a) => Ord (Patch a)
|
|||||||
derive newtype instance (Show a) => Show (Patch a)
|
derive newtype instance (Show a) => Show (Patch a)
|
||||||
|
|
||||||
newtype Delete a = Delete a
|
newtype Delete a = Delete a
|
||||||
|
|
||||||
derive instance Generic (Delete a) _
|
derive instance Generic (Delete a) _
|
||||||
derive instance Newtype (Delete a) _
|
derive instance Newtype (Delete a) _
|
||||||
derive newtype instance (Eq a) => Eq (Delete a)
|
derive newtype instance (Eq a) => Eq (Delete a)
|
||||||
@ -41,6 +46,7 @@ derive newtype instance (Ord a) => Ord (Delete a)
|
|||||||
derive newtype instance (Show a) => Show (Delete a)
|
derive newtype instance (Show a) => Show (Delete a)
|
||||||
|
|
||||||
newtype Options a = Options a
|
newtype Options a = Options a
|
||||||
|
|
||||||
derive instance Generic (Options a) _
|
derive instance Generic (Options a) _
|
||||||
derive instance Newtype (Options a) _
|
derive instance Newtype (Options a) _
|
||||||
derive newtype instance (Eq a) => Eq (Options a)
|
derive newtype instance (Eq a) => Eq (Options a)
|
||||||
@ -48,6 +54,7 @@ derive newtype instance (Ord a) => Ord (Options a)
|
|||||||
derive newtype instance (Show a) => Show (Options a)
|
derive newtype instance (Show a) => Show (Options a)
|
||||||
|
|
||||||
newtype Trace a = Trace a
|
newtype Trace a = Trace a
|
||||||
|
|
||||||
derive instance Generic (Trace a) _
|
derive instance Generic (Trace a) _
|
||||||
derive instance Newtype (Trace a) _
|
derive instance Newtype (Trace a) _
|
||||||
derive newtype instance (Eq a) => Eq (Trace a)
|
derive newtype instance (Eq a) => Eq (Trace a)
|
||||||
@ -55,6 +62,7 @@ derive newtype instance (Ord a) => Ord (Trace a)
|
|||||||
derive newtype instance (Show a) => Show (Trace a)
|
derive newtype instance (Show a) => Show (Trace a)
|
||||||
|
|
||||||
newtype Connect a = Connect a
|
newtype Connect a = Connect a
|
||||||
|
|
||||||
derive instance Generic (Connect a) _
|
derive instance Generic (Connect a) _
|
||||||
derive instance Newtype (Connect a) _
|
derive instance Newtype (Connect a) _
|
||||||
derive newtype instance (Eq a) => Eq (Connect a)
|
derive newtype instance (Eq a) => Eq (Connect a)
|
||||||
|
@ -4,26 +4,46 @@ import Prelude
|
|||||||
|
|
||||||
import Control.Alternative (guard)
|
import Control.Alternative (guard)
|
||||||
import Data.Array as Array
|
import Data.Array as Array
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
import Data.Int as Int
|
import Data.Int as Int
|
||||||
import Data.Maybe (Maybe(..), fromMaybe)
|
import Data.Maybe (Maybe(..), fromMaybe)
|
||||||
|
import Data.Show.Generic (genericShow)
|
||||||
import Data.Symbol (class IsSymbol, reflectSymbol)
|
import Data.Symbol (class IsSymbol, reflectSymbol)
|
||||||
import Data.Tuple.Nested (type (/\), (/\))
|
import Data.Tuple.Nested (type (/\), (/\))
|
||||||
import Data.URL (URL)
|
import Data.URL (URL)
|
||||||
import Type.Prelude (Proxy(..))
|
import Type.Prelude (Proxy(..))
|
||||||
|
|
||||||
newtype Path :: Type -> Type -> Type
|
data Path :: forall k. k -> Type -> Type
|
||||||
newtype Path a b = Path b
|
data Path a b = Path b
|
||||||
|
|
||||||
data Sep :: Type -> Type -> Type
|
derive instance Generic (Path a b) _
|
||||||
|
derive instance Eq b => Eq (Path a b)
|
||||||
|
instance Show b => Show (Path a b) where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
|
data Sep :: forall ka kb. ka -> kb -> Type
|
||||||
data Sep a b
|
data Sep a b
|
||||||
|
|
||||||
data IgnoreRest :: Type
|
data IgnoreRest :: Type
|
||||||
data IgnoreRest
|
data IgnoreRest
|
||||||
|
|
||||||
infixl 9 type Sep as /
|
infixr 9 type Sep as /
|
||||||
infixl 9 type IgnoreRest as ...
|
infixl 9 type IgnoreRest as ...
|
||||||
|
|
||||||
class PathParts :: forall a. a -> Type -> Constraint
|
class DiscardTupledUnits :: Type -> Type -> Constraint
|
||||||
|
class DiscardTupledUnits a b | a -> b where
|
||||||
|
discardTupledUnits :: a -> b
|
||||||
|
|
||||||
|
instance (DiscardTupledUnits a b) => DiscardTupledUnits (Unit /\ a) b where
|
||||||
|
discardTupledUnits (_ /\ a) = discardTupledUnits a
|
||||||
|
else instance (DiscardTupledUnits a b) => DiscardTupledUnits (a /\ Unit) b where
|
||||||
|
discardTupledUnits (a /\ _) = discardTupledUnits a
|
||||||
|
else instance (DiscardTupledUnits aa ab, DiscardTupledUnits ba bb) => DiscardTupledUnits (aa /\ ba) (ab /\ bb) where
|
||||||
|
discardTupledUnits (a /\ b) = discardTupledUnits a /\ discardTupledUnits b
|
||||||
|
else instance DiscardTupledUnits a a where
|
||||||
|
discardTupledUnits = identity
|
||||||
|
|
||||||
|
class PathParts :: forall k. k -> Type -> Constraint
|
||||||
class PathParts a b | a -> b where
|
class PathParts a b | a -> b where
|
||||||
extractPathParts :: URL -> Array String -> Maybe (Array String /\ b)
|
extractPathParts :: URL -> Array String -> Maybe (Array String /\ b)
|
||||||
|
|
||||||
@ -32,7 +52,7 @@ instance (PathParts aa ab, PathParts ba bb) => PathParts (aa / ba) (ab /\ bb) wh
|
|||||||
segments' /\ ab <- extractPathParts @aa u segments
|
segments' /\ ab <- extractPathParts @aa u segments
|
||||||
segments'' /\ bb <- extractPathParts @ba u segments'
|
segments'' /\ bb <- extractPathParts @ba u segments'
|
||||||
pure $ segments'' /\ ab /\ bb
|
pure $ segments'' /\ ab /\ bb
|
||||||
else instance PathParts (...) Unit where
|
else instance PathParts IgnoreRest Unit where
|
||||||
extractPathParts _ _ = Just $ [] /\ unit
|
extractPathParts _ _ = Just $ [] /\ unit
|
||||||
else instance PathParts String String where
|
else instance PathParts String String where
|
||||||
extractPathParts _ segments = do
|
extractPathParts _ segments = do
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
module Axon.Request (Request, BodyReadableError(..), BodyStringError(..), BodyJSONError(..), BodyBufferError(..), bodyReadable, bodyString, bodyJSON, bodyBuffer, headers, method, address, url, contentType, accept, contentLength, lookupHeader) where
|
module Axon.Request (Request, Body(..), BodyReadableError(..), BodyStringError(..), BodyJSONError(..), BodyBufferError(..), bodyReadable, bodyString, bodyJSON, bodyBuffer, headers, method, address, url, contentType, accept, contentLength, lookupHeader, make) where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
|
import Axon.Request.Method (Method)
|
||||||
import Control.Monad.Error.Class (throwError, try)
|
import Control.Monad.Error.Class (throwError, try)
|
||||||
import Control.Monad.Except (ExceptT(..), runExceptT)
|
import Control.Monad.Except (ExceptT(..), runExceptT)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
@ -9,14 +10,15 @@ import Data.Argonaut.Core (Json)
|
|||||||
import Data.Argonaut.Core (stringify) as JSON
|
import Data.Argonaut.Core (stringify) as JSON
|
||||||
import Data.Argonaut.Parser (jsonParser) as JSON
|
import Data.Argonaut.Parser (jsonParser) as JSON
|
||||||
import Data.Bifunctor (lmap)
|
import Data.Bifunctor (lmap)
|
||||||
import Data.Either (Either, note)
|
import Data.Either (Either)
|
||||||
|
import Data.FoldableWithIndex (foldlWithIndex)
|
||||||
import Data.Generic.Rep (class Generic)
|
import Data.Generic.Rep (class Generic)
|
||||||
import Data.Int as Int
|
import Data.Int as Int
|
||||||
import Data.MIME (MIME)
|
import Data.MIME (MIME)
|
||||||
import Data.MIME as MIME
|
import Data.MIME as MIME
|
||||||
import Data.Map (Map)
|
import Data.Map (Map)
|
||||||
import Data.Map as Map
|
import Data.Map as Map
|
||||||
import Data.Maybe (Maybe(..))
|
import Data.Maybe (Maybe)
|
||||||
import Data.Show.Generic (genericShow)
|
import Data.Show.Generic (genericShow)
|
||||||
import Data.String.Lower (StringLower)
|
import Data.String.Lower (StringLower)
|
||||||
import Data.String.Lower as String.Lower
|
import Data.String.Lower as String.Lower
|
||||||
@ -35,7 +37,6 @@ import Node.Encoding (Encoding(..))
|
|||||||
import Node.Net.Types (IPv4, IPv6, SocketAddress)
|
import Node.Net.Types (IPv4, IPv6, SocketAddress)
|
||||||
import Node.Stream as Stream
|
import Node.Stream as Stream
|
||||||
import Node.Stream.Aff as Stream.Aff
|
import Node.Stream.Aff as Stream.Aff
|
||||||
import Axon.Request.Method (Method)
|
|
||||||
|
|
||||||
data BodyReadableError
|
data BodyReadableError
|
||||||
= BodyReadableErrorHasBeenConsumed
|
= BodyReadableErrorHasBeenConsumed
|
||||||
@ -55,6 +56,7 @@ instance Eq BodyBufferError where
|
|||||||
eq (BodyBufferErrorReadable a) (BodyBufferErrorReadable b) = a == b
|
eq (BodyBufferErrorReadable a) (BodyBufferErrorReadable b) = a == b
|
||||||
eq (BodyBufferErrorReading a) (BodyBufferErrorReading b) = Error.message a == Error.message b
|
eq (BodyBufferErrorReading a) (BodyBufferErrorReading b) = Error.message a == Error.message b
|
||||||
eq _ _ = false
|
eq _ _ = false
|
||||||
|
|
||||||
instance Show BodyBufferError where
|
instance Show BodyBufferError where
|
||||||
show = genericShow
|
show = genericShow
|
||||||
|
|
||||||
@ -93,6 +95,18 @@ data Request =
|
|||||||
, bodyRef :: Effect.Ref Body
|
, bodyRef :: Effect.Ref Body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
make
|
||||||
|
:: { headers :: Map String String
|
||||||
|
, address :: Either (SocketAddress IPv4) (SocketAddress IPv6)
|
||||||
|
, url :: URL
|
||||||
|
, method :: Method
|
||||||
|
, body :: Body
|
||||||
|
}
|
||||||
|
-> Effect Request
|
||||||
|
make a = do
|
||||||
|
bodyRef <- Ref.new a.body
|
||||||
|
pure $ Request { bodyRef: bodyRef, headers: foldlWithIndex (\k m v -> Map.insert (String.Lower.fromString k) v m) Map.empty a.headers, address: a.address, url: a.url, method: a.method }
|
||||||
|
|
||||||
headers :: Request -> Map StringLower String
|
headers :: Request -> Map StringLower String
|
||||||
headers (Request a) = a.headers
|
headers (Request a) = a.headers
|
||||||
|
|
||||||
@ -118,7 +132,7 @@ url :: Request -> URL
|
|||||||
url (Request a) = a.url
|
url (Request a) = a.url
|
||||||
|
|
||||||
bodyReadable :: Request -> Effect (Either BodyReadableError (Stream.Readable ()))
|
bodyReadable :: Request -> Effect (Either BodyReadableError (Stream.Readable ()))
|
||||||
bodyReadable (Request {bodyRef}) = runExceptT do
|
bodyReadable (Request { bodyRef }) = runExceptT do
|
||||||
body <- liftEffect $ Ref.read bodyRef
|
body <- liftEffect $ Ref.read bodyRef
|
||||||
case body of
|
case body of
|
||||||
BodyEmpty -> throwError BodyReadableErrorEmpty
|
BodyEmpty -> throwError BodyReadableErrorEmpty
|
||||||
@ -130,38 +144,38 @@ bodyReadable (Request {bodyRef}) = runExceptT do
|
|||||||
BodyCachedJSON json -> json # JSON.stringify # flip Buffer.fromString UTF8 >>= Stream.readableFromBuffer # lift
|
BodyCachedJSON json -> json # JSON.stringify # flip Buffer.fromString UTF8 >>= Stream.readableFromBuffer # lift
|
||||||
|
|
||||||
bodyBuffer :: Request -> Aff (Either BodyBufferError Buffer)
|
bodyBuffer :: Request -> Aff (Either BodyBufferError Buffer)
|
||||||
bodyBuffer r@(Request {bodyRef}) =
|
bodyBuffer r@(Request { bodyRef }) =
|
||||||
let
|
let
|
||||||
stream =
|
stream =
|
||||||
bodyReadable r
|
bodyReadable r
|
||||||
# liftEffect
|
# liftEffect
|
||||||
<#> lmap BodyBufferErrorReadable
|
<#> lmap BodyBufferErrorReadable
|
||||||
# ExceptT
|
# ExceptT
|
||||||
readAll s =
|
readAll s =
|
||||||
Stream.Aff.readAll s
|
Stream.Aff.readAll s
|
||||||
# liftAff
|
# liftAff
|
||||||
# try
|
# try
|
||||||
<#> lmap BodyBufferErrorReading
|
<#> lmap BodyBufferErrorReading
|
||||||
# ExceptT
|
# ExceptT
|
||||||
>>= (liftEffect <<< Buffer.concat)
|
>>= (liftEffect <<< Buffer.concat)
|
||||||
in
|
in
|
||||||
runExceptT do
|
runExceptT do
|
||||||
body <- Ref.read bodyRef # liftEffect
|
body <- Ref.read bodyRef # liftEffect
|
||||||
case body of
|
case body of
|
||||||
BodyCached buf -> pure buf
|
BodyCached buf -> pure buf
|
||||||
BodyCachedString str -> Buffer.fromString str UTF8 # liftEffect
|
BodyCachedString str -> Buffer.fromString str UTF8 # liftEffect
|
||||||
BodyCachedJSON json -> Buffer.fromString (JSON.stringify json) UTF8 # liftEffect
|
BodyCachedJSON json -> Buffer.fromString (JSON.stringify json) UTF8 # liftEffect
|
||||||
_ -> do
|
_ -> do
|
||||||
buf <- stream >>= readAll
|
buf <- stream >>= readAll
|
||||||
Ref.write (BodyCached buf) bodyRef $> buf # liftEffect
|
Ref.write (BodyCached buf) bodyRef $> buf # liftEffect
|
||||||
|
|
||||||
bodyString :: Request -> Aff (Either BodyStringError String)
|
bodyString :: Request -> Aff (Either BodyStringError String)
|
||||||
bodyString r@(Request {bodyRef}) =
|
bodyString r@(Request { bodyRef }) =
|
||||||
let
|
let
|
||||||
buf =
|
buf =
|
||||||
bodyBuffer r
|
bodyBuffer r
|
||||||
<#> lmap BodyStringErrorBuffer
|
<#> lmap BodyStringErrorBuffer
|
||||||
# ExceptT
|
# ExceptT
|
||||||
bufString b =
|
bufString b =
|
||||||
Buffer.toString UTF8 b
|
Buffer.toString UTF8 b
|
||||||
# liftEffect
|
# liftEffect
|
||||||
@ -169,32 +183,32 @@ bodyString r@(Request {bodyRef}) =
|
|||||||
<#> lmap (const BodyStringErrorNotUTF8)
|
<#> lmap (const BodyStringErrorNotUTF8)
|
||||||
# ExceptT
|
# ExceptT
|
||||||
in
|
in
|
||||||
runExceptT do
|
runExceptT do
|
||||||
body <- Ref.read bodyRef # liftEffect
|
body <- Ref.read bodyRef # liftEffect
|
||||||
case body of
|
case body of
|
||||||
BodyCachedString str -> pure str
|
BodyCachedString str -> pure str
|
||||||
BodyCachedJSON json -> JSON.stringify json # pure
|
BodyCachedJSON json -> JSON.stringify json # pure
|
||||||
_ -> do
|
_ -> do
|
||||||
str <- buf >>= bufString
|
str <- buf >>= bufString
|
||||||
Ref.write (BodyCachedString str) bodyRef $> str # liftEffect
|
Ref.write (BodyCachedString str) bodyRef $> str # liftEffect
|
||||||
|
|
||||||
bodyJSON :: Request -> Aff (Either BodyJSONError Json)
|
bodyJSON :: Request -> Aff (Either BodyJSONError Json)
|
||||||
bodyJSON r@(Request {bodyRef}) =
|
bodyJSON r@(Request { bodyRef }) =
|
||||||
let
|
let
|
||||||
str =
|
str =
|
||||||
bodyString r
|
bodyString r
|
||||||
<#> lmap BodyJSONErrorString
|
<#> lmap BodyJSONErrorString
|
||||||
# ExceptT
|
# ExceptT
|
||||||
parse s =
|
parse s =
|
||||||
JSON.jsonParser s
|
JSON.jsonParser s
|
||||||
# lmap BodyJSONErrorParsing
|
# lmap BodyJSONErrorParsing
|
||||||
# pure
|
# pure
|
||||||
# ExceptT
|
# ExceptT
|
||||||
in
|
in
|
||||||
runExceptT do
|
runExceptT do
|
||||||
body <- Ref.read bodyRef # liftEffect
|
body <- Ref.read bodyRef # liftEffect
|
||||||
case body of
|
case body of
|
||||||
BodyCachedJSON j -> pure j
|
BodyCachedJSON j -> pure j
|
||||||
_ -> do
|
_ -> do
|
||||||
j <- str >>= parse
|
j <- str >>= parse
|
||||||
Ref.write (BodyCachedJSON j) bodyRef $> j # liftEffect
|
Ref.write (BodyCachedJSON j) bodyRef $> j # liftEffect
|
||||||
|
@ -16,6 +16,13 @@ data Body
|
|||||||
| BodyFormData HTTP.RawFormData
|
| BodyFormData HTTP.RawFormData
|
||||||
| BodyReadable (Stream.Readable ())
|
| BodyReadable (Stream.Readable ())
|
||||||
|
|
||||||
|
instance Show Body where
|
||||||
|
show BodyEmpty = "BodyEmpty"
|
||||||
|
show (BodyString s) = "BodyString " <> show s
|
||||||
|
show (BodyBuffer _) = "BodyBuffer _"
|
||||||
|
show (BodyFormData _) = "BodyFormData _"
|
||||||
|
show (BodyReadable _) = "BodyReadable _"
|
||||||
|
|
||||||
formBody :: HTTP.Form -> Effect Body
|
formBody :: HTTP.Form -> Effect Body
|
||||||
formBody f = HTTP.Form.toRawFormData f <#> BodyFormData
|
formBody f = HTTP.Form.toRawFormData f <#> BodyFormData
|
||||||
|
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
module Axon.Response (Response, response, body, status, headers, withHeader, withBody, withStatus, fromStatus, ok, module Body) where
|
module Axon.Response (Response(..), response, body, status, headers, withHeader, withBody, withStatus, fromStatus, ok, module Body) where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Data.FoldableWithIndex (foldlWithIndex)
|
|
||||||
import Data.Map (Map)
|
|
||||||
import Data.Map as Map
|
|
||||||
import Data.String.Lower (StringLower)
|
|
||||||
import Data.String.Lower as String.Lower
|
|
||||||
import Axon.Response.Body (Body(..))
|
import Axon.Response.Body (Body(..))
|
||||||
import Axon.Response.Body (Body(..), formBody) as Body
|
import Axon.Response.Body (Body(..), formBody) as Body
|
||||||
|
import Data.FoldableWithIndex (foldlWithIndex)
|
||||||
|
import Data.Generic.Rep (class Generic)
|
||||||
|
import Data.Map (Map)
|
||||||
|
import Data.Map as Map
|
||||||
|
import Data.Show.Generic (genericShow)
|
||||||
|
import Data.String.Lower (StringLower)
|
||||||
|
import Data.String.Lower as String.Lower
|
||||||
|
|
||||||
data Response = Response {body :: Body, headers :: Map StringLower String, status :: Int}
|
data Response = Response { body :: Body, headers :: Map StringLower String, status :: Int }
|
||||||
|
|
||||||
|
derive instance Generic Response _
|
||||||
|
instance Show Response where
|
||||||
|
show = genericShow
|
||||||
|
|
||||||
response :: Int -> Body -> Map String String -> Response
|
response :: Int -> Body -> Map String String -> Response
|
||||||
response s b h = Response {status: s, body: b, headers: h # foldlWithIndex (\k m v -> Map.insert (String.Lower.fromString k) v m) Map.empty}
|
response s b h = Response { status: s, body: b, headers: h # foldlWithIndex (\k m v -> Map.insert (String.Lower.fromString k) v m) Map.empty }
|
||||||
|
|
||||||
status :: Response -> Int
|
status :: Response -> Int
|
||||||
status (Response a) = a.status
|
status (Response a) = a.status
|
||||||
@ -25,16 +31,16 @@ headers :: Response -> Map StringLower String
|
|||||||
headers (Response a) = a.headers
|
headers (Response a) = a.headers
|
||||||
|
|
||||||
withHeader :: String -> String -> Response -> Response
|
withHeader :: String -> String -> Response -> Response
|
||||||
withHeader k v (Response a) = Response $ a {headers = Map.insert (String.Lower.fromString k) v a.headers}
|
withHeader k v (Response a) = Response $ a { headers = Map.insert (String.Lower.fromString k) v a.headers }
|
||||||
|
|
||||||
withStatus :: Int -> Response -> Response
|
withStatus :: Int -> Response -> Response
|
||||||
withStatus s (Response a) = Response $ a {status = s}
|
withStatus s (Response a) = Response $ a { status = s }
|
||||||
|
|
||||||
withBody :: Body -> Response -> Response
|
withBody :: Body -> Response -> Response
|
||||||
withBody b (Response a) = Response $ a {body = b}
|
withBody b (Response a) = Response $ a { body = b }
|
||||||
|
|
||||||
fromStatus :: Int -> Response
|
fromStatus :: Int -> Response
|
||||||
fromStatus s = Response {body: BodyEmpty, headers: Map.empty, status: s}
|
fromStatus s = Response { body: BodyEmpty, headers: Map.empty, status: s }
|
||||||
|
|
||||||
ok :: Response
|
ok :: Response
|
||||||
ok = fromStatus 200
|
ok = fromStatus 200
|
||||||
|
@ -2,4 +2,8 @@
|
|||||||
/// <reference lib="dom.iterable" />
|
/// <reference lib="dom.iterable" />
|
||||||
|
|
||||||
/** @type {(_: {tuple: <A, B>(a: A) => (b: B) => unknown}) => (h: Headers) => () => Array<unknown>} */
|
/** @type {(_: {tuple: <A, B>(a: A) => (b: B) => unknown}) => (h: Headers) => () => Array<unknown>} */
|
||||||
export const headerEntries = ({tuple}) => hs => () => Array.from(hs.entries()).map(([a, b]) => tuple(a)(b))
|
export const headerEntries =
|
||||||
|
({ tuple }) =>
|
||||||
|
hs =>
|
||||||
|
() =>
|
||||||
|
Array.from(hs.entries()).map(([a, b]) => tuple(a)(b))
|
||||||
|
@ -4,4 +4,4 @@ import Data.Tuple.Nested (type (/\))
|
|||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
|
|
||||||
foreign import data WebHeaders :: Type
|
foreign import data WebHeaders :: Type
|
||||||
foreign import headerEntries :: {tuple :: forall a b. a -> b -> a /\ b} -> WebHeaders -> Effect (Array (String /\ String))
|
foreign import headerEntries :: { tuple :: forall a b. a -> b -> a /\ b } -> WebHeaders -> Effect (Array (String /\ String))
|
||||||
|
@ -20,15 +20,15 @@ export const headers = r => () => r.headers
|
|||||||
|
|
||||||
/** @type {(r: ReadableStream<Uint8Array>) => () => Stream.Readable} */
|
/** @type {(r: ReadableStream<Uint8Array>) => () => Stream.Readable} */
|
||||||
export const readableFromWeb = r => () => {
|
export const readableFromWeb = r => () => {
|
||||||
const reader = r.getReader();
|
const reader = r.getReader()
|
||||||
return new Stream.Readable({
|
return new Stream.Readable({
|
||||||
read: function() {
|
read: function () {
|
||||||
(async () => {
|
;(async () => {
|
||||||
/** @type {ReadableStreamReadResult<Uint8Array> | undefined} */
|
/** @type {ReadableStreamReadResult<Uint8Array> | undefined} */
|
||||||
let res = undefined;
|
let res = undefined
|
||||||
try {
|
try {
|
||||||
res = await reader.read()
|
res = await reader.read()
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
if (typeof e === 'undefined' || e instanceof Error) {
|
if (typeof e === 'undefined' || e instanceof Error) {
|
||||||
this.destroy(e)
|
this.destroy(e)
|
||||||
return
|
return
|
||||||
@ -37,8 +37,8 @@ export const readableFromWeb = r => () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.value) this.push(res.value);
|
if (res.value) this.push(res.value)
|
||||||
if (res.done) this.push(null);
|
if (res.done) this.push(null)
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
module Axon.Web.Request where
|
module Axon.Web.Request where
|
||||||
|
|
||||||
import Data.ArrayBuffer.Types (Uint8Array)
|
import Data.ArrayBuffer.Types (Uint8Array)
|
||||||
|
import Axon.Web.Headers (WebHeaders)
|
||||||
import Data.Nullable (Nullable)
|
import Data.Nullable (Nullable)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Node.Stream as Stream
|
import Node.Stream as Stream
|
||||||
import Axon.Request.Web (WebHeaders)
|
|
||||||
import Web.Streams.ReadableStream (ReadableStream)
|
import Web.Streams.ReadableStream (ReadableStream)
|
||||||
|
|
||||||
foreign import data WebRequest :: Type
|
foreign import data WebRequest :: Type
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
module Main where
|
|
||||||
|
|
||||||
import Prelude
|
|
||||||
|
|
||||||
import Effect (Effect)
|
|
||||||
import Effect.Console (log)
|
|
||||||
|
|
||||||
main :: Effect Unit
|
|
||||||
main = do
|
|
||||||
log "🍝"
|
|
123
test/Test/Axon.Request.Parts.purs
Normal file
123
test/Test/Axon.Request.Parts.purs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
module Test.Axon.Request.Parts where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Axon.Request (Request)
|
||||||
|
import Axon.Request as Request
|
||||||
|
import Axon.Request.Method (Method(..))
|
||||||
|
import Axon.Request.Parts.Class (Json(..), Patch(..), Path(..), Post(..), extractRequestParts)
|
||||||
|
import Axon.Request.Parts.Path (type (...), type (/), IgnoreRest)
|
||||||
|
import Control.Monad.Error.Class (liftEither, liftMaybe)
|
||||||
|
import Data.Bifunctor (lmap)
|
||||||
|
import Data.Either (Either(..))
|
||||||
|
import Data.Map as Map
|
||||||
|
import Data.Maybe (Maybe(..), fromJust)
|
||||||
|
import Data.Tuple.Nested (type (/\), (/\))
|
||||||
|
import Data.URL as URL
|
||||||
|
import Effect.Class (liftEffect)
|
||||||
|
import Effect.Exception (error)
|
||||||
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
|
import Node.Buffer as Buffer
|
||||||
|
import Node.Encoding (Encoding(..))
|
||||||
|
import Node.Net.SocketAddress as SocketAddress
|
||||||
|
import Node.Stream as Stream
|
||||||
|
import Partial.Unsafe (unsafePartial)
|
||||||
|
import Test.Spec (Spec, describe, it)
|
||||||
|
import Test.Spec.Assertions (shouldEqual)
|
||||||
|
|
||||||
|
spec :: Spec Unit
|
||||||
|
spec = describe "Parts" do
|
||||||
|
it "extracts the whole request" do
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyEmpty, url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
void $ extractRequestParts @Request req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
|
||||||
|
it "extracts method, path, JSON body" do
|
||||||
|
stream <- Buffer.fromString """{"firstName": "henry"}""" UTF8 >>= Stream.readableFromBuffer # liftEffect
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyReadable stream, url: URL.fromString "http://localhost:80/users/12" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: PATCH}
|
||||||
|
a <- extractRequestParts @(Patch ((Path ("users" / Int) _) /\ Json {firstName :: String})) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` Patch (Path 12 /\ Json {firstName: "henry"})
|
||||||
|
|
||||||
|
describe "Path" do
|
||||||
|
it "matches a route matching literal" do
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyCachedString "foo", url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
a <- extractRequestParts @(Path "foo" _) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Path unit)
|
||||||
|
|
||||||
|
it "matches a route matching multiple literals" do
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyCachedString "foo", url: URL.fromString "http://localhost:80/foo/bar/baz" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
a <- extractRequestParts @(Path ("foo" / "bar" / "baz") _) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Path unit)
|
||||||
|
|
||||||
|
it "does not partially match a route ..." do
|
||||||
|
req <- liftEffect $ Request.make
|
||||||
|
{ body: Request.BodyCachedString "foo"
|
||||||
|
, url: URL.fromString "http://localhost:80/foo/bar/baz" # unsafePartial fromJust
|
||||||
|
, headers: Map.empty
|
||||||
|
, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}
|
||||||
|
, method: GET
|
||||||
|
}
|
||||||
|
a <- extractRequestParts @(Path ("foo" / "bar") _) req <#> lmap (error <<< show) >>= liftEither
|
||||||
|
a `shouldEqual` Nothing
|
||||||
|
|
||||||
|
it "... but does if ends in IgnoreRest" do
|
||||||
|
req <- liftEffect $ Request.make
|
||||||
|
{ body: Request.BodyCachedString "foo"
|
||||||
|
, url: URL.fromString "http://localhost:80/foo/bar/baz" # unsafePartial fromJust
|
||||||
|
, headers: Map.empty
|
||||||
|
, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}
|
||||||
|
, method: GET
|
||||||
|
}
|
||||||
|
a <- extractRequestParts @(Path ("foo" / "bar" / IgnoreRest) _) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Path unit)
|
||||||
|
|
||||||
|
it "extracts an int" do
|
||||||
|
req <- liftEffect $ Request.make
|
||||||
|
{ body: Request.BodyCachedString "foo"
|
||||||
|
, url: URL.fromString "http://localhost:80/foo/123/bar" # unsafePartial fromJust
|
||||||
|
, headers: Map.empty
|
||||||
|
, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}
|
||||||
|
, method: GET
|
||||||
|
}
|
||||||
|
a <- extractRequestParts @(Path ("foo" / Int / "bar") _) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Path 123)
|
||||||
|
|
||||||
|
it "extracts an int and a string" do
|
||||||
|
req <- liftEffect $ Request.make
|
||||||
|
{ body: Request.BodyCachedString "foo"
|
||||||
|
, url: URL.fromString "http://localhost:80/foo/123/bar/baz" # unsafePartial fromJust
|
||||||
|
, headers: Map.empty
|
||||||
|
, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}
|
||||||
|
, method: GET
|
||||||
|
}
|
||||||
|
a <- extractRequestParts @(Path ("foo" / Int / "bar" / String) _) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Path $ 123 /\ "baz")
|
||||||
|
|
||||||
|
describe "Body" do
|
||||||
|
it "extracts a string body from a cached string" do
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyCachedString "foo", url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
a <- extractRequestParts @(Either Request.BodyStringError String) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Right "foo")
|
||||||
|
|
||||||
|
it "extracts a string body from a readable stream" do
|
||||||
|
stream <- Buffer.fromString "foo" UTF8 >>= Stream.readableFromBuffer # liftEffect
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyReadable stream, url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
a <- extractRequestParts @(Either Request.BodyStringError String) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Right "foo")
|
||||||
|
|
||||||
|
a' <- extractRequestParts @String req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a' `shouldEqual` "foo"
|
||||||
|
|
||||||
|
it "extracts a string body from a buffer" do
|
||||||
|
buf <- Buffer.fromString "foo" UTF8 # liftEffect
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyCached buf, url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: GET}
|
||||||
|
a <- extractRequestParts @(Either Request.BodyStringError String) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` (Right "foo")
|
||||||
|
|
||||||
|
a' <- extractRequestParts @String req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a' `shouldEqual` "foo"
|
||||||
|
|
||||||
|
it "extracts a JSON body" do
|
||||||
|
stream <- Buffer.fromString """{"foo": 123, "bar": "abc"}""" UTF8 >>= Stream.readableFromBuffer # liftEffect
|
||||||
|
req <- liftEffect $ Request.make {body: Request.BodyReadable stream, url: URL.fromString "http://localhost:80/foo" # unsafePartial fromJust, headers: Map.empty, address: Left $ unsafePerformEffect $ SocketAddress.newIpv4 {address: "127.0.0.1", port: 81}, method: POST}
|
||||||
|
a <- extractRequestParts @(Post (Json {foo :: Int, bar :: String})) req <#> lmap (error <<< show) >>= liftEither >>= liftMaybe (error "was nothing")
|
||||||
|
a `shouldEqual` Post (Json {foo: 123, bar: "abc"})
|
10
test/Test/Axon.Request.purs
Normal file
10
test/Test/Axon.Request.purs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module Test.Axon.Request where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Test.Axon.Request.Parts as Parts
|
||||||
|
import Test.Spec (Spec, describe)
|
||||||
|
|
||||||
|
spec :: Spec Unit
|
||||||
|
spec = describe "Request" do
|
||||||
|
Parts.spec
|
@ -3,10 +3,11 @@ module Test.Main where
|
|||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Class.Console (log)
|
import Test.Axon.Request as Test.Request
|
||||||
|
import Test.Spec (describe)
|
||||||
|
import Test.Spec.Reporter (specReporter)
|
||||||
|
import Test.Spec.Runner.Node (runSpecAndExitProcess)
|
||||||
|
|
||||||
main :: Effect Unit
|
main :: Effect Unit
|
||||||
main = do
|
main = runSpecAndExitProcess [ specReporter ] $ describe "Axon" do
|
||||||
log "🍕"
|
Test.Request.spec
|
||||||
log "You should add some tests."
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user