Skip to content

Commit 76f4d42

Browse files
committed
fix(core): pass specific status to HyperErr on known errors and bubble as non fatal #621
1 parent bcba779 commit 76f4d42

File tree

10 files changed

+455
-196
lines changed

10 files changed

+455
-196
lines changed

packages/core/deno.lock

Lines changed: 330 additions & 90 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/lib/cache/doc.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function checkKeyIsValid<T extends { key: string }>(input: T) {
3636
* or any of these characters - _ $ +
3737
*/
3838
return /^[a-z]+$/.test(key[0]) && /^[a-z0-9-~_/$/+]+$/.test(key)
39-
}, 'key is not valid')(input)
39+
}, { status: 422, msg: 'key is not valid' })(input)
4040
}
4141

4242
/**
@@ -52,12 +52,12 @@ export const create = (
5252
ttl?: string,
5353
) =>
5454
of({ store, key, value, ttl })
55-
.map(convertTTL)
56-
.map(removeTTL)
57-
.chain(checkKeyIsValid)
5855
.chain((input) =>
5956
ask(({ svc }: ReaderEnvironment<CachePort>) => {
6057
return Async.of(input)
58+
.map(convertTTL)
59+
.map(removeTTL)
60+
.chain(checkKeyIsValid)
6161
.chain(Async.fromPromise((input) => svc.createDoc(input)))
6262
.bichain($resolveHyperErr, $logHyperErr)
6363
}).chain(lift)
@@ -70,10 +70,10 @@ export const create = (
7070
*/
7171
export const get = (store: string, key: string) =>
7272
of({ store, key })
73-
.chain(checkKeyIsValid)
7473
.chain((input) =>
7574
ask(({ svc }: ReaderEnvironment<CachePort>) => {
7675
return Async.of(input)
76+
.chain(checkKeyIsValid)
7777
.chain(Async.fromPromise((input) => svc.getDoc(input)))
7878
.bichain($resolveHyperErr, $logHyperErr)
7979
}).chain(lift)
@@ -94,12 +94,12 @@ export const update = (
9494
ttl?: string,
9595
) =>
9696
of({ store, key, value, ttl })
97-
.map(convertTTL)
98-
.map(removeTTL)
99-
.chain(checkKeyIsValid)
10097
.chain((input) =>
10198
ask(({ svc }: ReaderEnvironment<CachePort>) => {
10299
return Async.of(input)
100+
.map(convertTTL)
101+
.map(removeTTL)
102+
.chain(checkKeyIsValid)
103103
.chain(Async.fromPromise((input) => svc.updateDoc(input)))
104104
.bichain($resolveHyperErr, $logHyperErr)
105105
}).chain(lift)
@@ -112,10 +112,10 @@ export const update = (
112112
*/
113113
export const del = (store: string, key: string) =>
114114
of({ store, key })
115-
.chain(checkKeyIsValid)
116115
.chain((input) =>
117116
ask(({ svc }: ReaderEnvironment<CachePort>) => {
118117
return Async.of(input)
118+
.chain(checkKeyIsValid)
119119
.chain(Async.fromPromise((input) => svc.deleteDoc(input)))
120120
.bichain($resolveHyperErr, $logHyperErr)
121121
}).chain(lift)

packages/core/lib/cache/mod.test.ts

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,37 +62,41 @@ Deno.test('cache', async (t) => {
6262
},
6363
)
6464

65-
await t.step('should reject if the name is invalid', async (t) => {
65+
await t.step('should resolve HyperErr if the name is invalid', async (t) => {
6666
await t.step('does not start with alphanumeric', async () => {
6767
await cache
6868
.createStore('_foo')
6969
.toPromise()
70-
.then(() => assert(false))
71-
.catch(() => assert(true))
70+
.then((err: any) => {
71+
assertEquals(err.status, 422)
72+
})
7273
})
7374

7475
await t.step('contains a space', async () => {
7576
await cache
7677
.createStore('foo bar')
7778
.toPromise()
78-
.then(() => assert(false))
79-
.catch(() => assert(true))
79+
.then((err: any) => {
80+
assertEquals(err.status, 422)
81+
})
8082
})
8183

8284
await t.step('contains a slash', async () => {
8385
await cache
8486
.createStore('foo/bar')
8587
.toPromise()
86-
.then(() => assert(false))
87-
.catch(() => assert(true))
88+
.then((err: any) => {
89+
assertEquals(err.status, 422)
90+
})
8891
})
8992

9093
await t.step('contains non URI friendly character', async () => {
9194
await cache
9295
.createStore('foo?bar')
9396
.toPromise()
94-
.then(() => assert(false))
95-
.catch(() => assert(true))
97+
.then((err: any) => {
98+
assertEquals(err.status, 422)
99+
})
96100
})
97101
})
98102
})
@@ -108,37 +112,41 @@ Deno.test('cache', async (t) => {
108112
.toPromise()
109113
})
110114

111-
await t.step('should reject if the name is invalid', async (t) => {
115+
await t.step('should resolve HyperErr if the name is invalid', async (t) => {
112116
await t.step('does not start with alphanumeric', async () => {
113117
await cache
114118
.deleteStore('_foo')
115119
.toPromise()
116-
.then(() => assert(false))
117-
.catch(() => assert(true))
120+
.then((err: any) => {
121+
assertEquals(err.status, 422)
122+
})
118123
})
119124

120125
await t.step('contains a space', async () => {
121126
await cache
122127
.deleteStore('foo bar')
123128
.toPromise()
124-
.then(() => assert(false))
125-
.catch(() => assert(true))
129+
.then((err: any) => {
130+
assertEquals(err.status, 422)
131+
})
126132
})
127133

128134
await t.step('contains a slash', async () => {
129135
await cache
130136
.deleteStore('foo/bar')
131137
.toPromise()
132-
.then(() => assert(false))
133-
.catch(() => assert(true))
138+
.then((err: any) => {
139+
assertEquals(err.status, 422)
140+
})
134141
})
135142

136143
await t.step('contains non URI friendly character', async () => {
137144
await cache
138145
.deleteStore('foo?bar')
139146
.toPromise()
140-
.then(() => assert(false))
141-
.catch(() => assert(true))
147+
.then((err: any) => {
148+
assertEquals(err.status, 422)
149+
})
142150
})
143151
})
144152
})
@@ -156,37 +164,41 @@ Deno.test('cache', async (t) => {
156164
.toPromise()
157165
})
158166

159-
await t.step('should reject if the name is invalid', async (t) => {
167+
await t.step('should resolve HyperErr if the name is invalid', async (t) => {
160168
await t.step('does not start with alphanumeric', async () => {
161169
await cache
162170
.queryStore('_foo', 'foo*')
163171
.toPromise()
164-
.then(() => assert(false))
165-
.catch(() => assert(true))
172+
.then((err: any) => {
173+
assertEquals(err.status, 422)
174+
})
166175
})
167176

168177
await t.step('contains a space', async () => {
169178
await cache
170179
.queryStore('foo bar', 'foo*')
171180
.toPromise()
172-
.then(() => assert(false))
173-
.catch(() => assert(true))
181+
.then((err: any) => {
182+
assertEquals(err.status, 422)
183+
})
174184
})
175185

176186
await t.step('contains a slash', async () => {
177187
await cache
178188
.queryStore('foo/bar', 'foo*')
179189
.toPromise()
180-
.then(() => assert(false))
181-
.catch(() => assert(true))
190+
.then((err: any) => {
191+
assertEquals(err.status, 422)
192+
})
182193
})
183194

184195
await t.step('contains non URI friendly character', async () => {
185196
await cache
186197
.queryStore('foo?bar', 'foo*')
187198
.toPromise()
188-
.then(() => assert(false))
189-
.catch(() => assert(true))
199+
.then((err: any) => {
200+
assertEquals(err.status, 422)
201+
})
190202
})
191203
})
192204
})
@@ -228,12 +240,13 @@ Deno.test('cache', async (t) => {
228240
.toPromise()
229241
})
230242

231-
await t.step('should reject if cache doc has an invalid key', async () => {
243+
await t.step('should resolve HyperErr if cache doc has an invalid key', async () => {
232244
await cache
233245
.createDoc('store', 'Not_Valid', { beep: 'boop' })
234246
.toPromise()
235-
.then(() => assert(false))
236-
.catch(() => assert(true))
247+
.then((err: any) => {
248+
assertEquals(err.status, 422)
249+
})
237250
})
238251
})
239252

@@ -363,12 +376,13 @@ Deno.test('cache', async (t) => {
363376
.toPromise()
364377
})
365378

366-
await t.step('should reject if cache doc has an invalid key', async () => {
379+
await t.step('should resolve HyperErr if cache doc has an invalid key', async () => {
367380
await cache
368381
.updateDoc('store', 'Not_Valid', { beep: 'boop' })
369382
.toPromise()
370-
.then(() => assert(false))
371-
.catch(() => assert(true))
383+
.then((err: any) => {
384+
assertEquals(err.status, 422)
385+
})
372386
})
373387
})
374388

@@ -385,12 +399,13 @@ Deno.test('cache', async (t) => {
385399
.toPromise()
386400
})
387401

388-
await t.step('should reject if cache doc has an invalid key', async () => {
402+
await t.step('should resolve HyperErr if cache doc has an invalid key', async () => {
389403
await cache
390404
.deleteDoc('store', 'Not_Valid')
391405
.toPromise()
392-
.then(() => assert(false))
393-
.catch(() => assert(true))
406+
.then((err: any) => {
407+
assertEquals(err.status, 422)
408+
})
394409
})
395410
})
396411
})

packages/core/lib/cache/store.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const checkNameIsValid = is((name: string) => {
2020
// cache names should only start with alphanumeric characters
2121
// should return a true or false
2222
return /^[a-z0-9]+$/.test(name[0]) && /^[a-z0-9-~_]+$/.test(name)
23-
}, 'name is not valid')
23+
}, { status: 422, msg: 'name is not valid' })
2424

2525
export const index = () =>
2626
ask(({ svc }: ReaderEnvironment<CachePort>) => {
@@ -37,10 +37,10 @@ export const index = () =>
3737
export const create = (name: string) =>
3838
of(name)
3939
.map(toLower)
40-
.chain(checkNameIsValid)
4140
.chain((input) =>
4241
ask(({ svc }: ReaderEnvironment<CachePort>) => {
4342
return Async.of(input)
43+
.chain(checkNameIsValid)
4444
.chain(Async.fromPromise((input) => svc.createStore(input)))
4545
.bichain($resolveHyperErr, $logHyperErr)
4646
}).chain(lift)
@@ -52,10 +52,10 @@ export const create = (name: string) =>
5252
*/
5353
export const del = (name: string) =>
5454
of(name)
55-
.chain(checkNameIsValid)
5655
.chain((input) =>
5756
ask(({ svc }: ReaderEnvironment<CachePort>) => {
5857
return Async.of(input)
58+
.chain(checkNameIsValid)
5959
.chain(Async.fromPromise((input) => svc.destroyStore(input)))
6060
.bichain($resolveHyperErr, $logHyperErr)
6161
}).chain(lift)
@@ -67,12 +67,12 @@ export const del = (name: string) =>
6767
* @param {string} pattern
6868
*/
6969
export const query = (name: string, pattern: string) =>
70-
of(name)
71-
.chain(checkNameIsValid)
72-
.map((name) => ({ store: name, pattern }))
70+
of({ store: name, pattern })
7371
.chain((input) =>
7472
ask(({ svc }: ReaderEnvironment<CachePort>) => {
7573
return Async.of(input)
74+
.chain(({ store }) => checkNameIsValid(store))
75+
.map(() => input)
7676
.chain(Async.fromPromise((input) => svc.listDocs(input)))
7777
.bichain($resolveHyperErr, $logHyperErr)
7878
}).chain(lift)

packages/core/lib/data/db.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ const setDescending = <T extends { descending?: boolean }>(arg: T) => ({
1717
descending: Boolean(arg.descending),
1818
})
1919

20-
const checkNameIsValid = is<string>(() => true, 'database name is not valid')
20+
const checkNameIsValid = is<string>(() => true, { status: 422, msg: 'database name is not valid' })
2121

2222
/**
2323
* @param {string} name
2424
*/
2525
export const create = (name: string) =>
2626
of(name)
27-
.chain(checkNameIsValid)
2827
.chain((input) =>
2928
ask(({ svc }: ReaderEnvironment<DataPort>) => {
3029
return Async.of(input)
30+
.chain(checkNameIsValid)
3131
.chain(Async.fromPromise((input) => svc.createDatabase(input)))
3232
.bichain($resolveHyperErr, $logHyperErr)
3333
}).chain(lift)
@@ -39,10 +39,10 @@ export const create = (name: string) =>
3939
*/
4040
export const remove = (name: string) =>
4141
of(name)
42-
.chain(checkNameIsValid)
4342
.chain((input) =>
4443
ask(({ svc }: ReaderEnvironment<DataPort>) => {
4544
return Async.of(input)
45+
.chain(checkNameIsValid)
4646
.chain(Async.fromPromise((input) => svc.removeDatabase(input)))
4747
.bichain($resolveHyperErr, $logHyperErr)
4848
}).chain(lift)

packages/core/lib/queue/mod.test.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Deno.test('queue', async (t) => {
7777
},
7878
)
7979

80-
await t.step('should reject if the name is invalid', async (t) => {
80+
await t.step('should resolve HyperErr if the name is invalid', async (t) => {
8181
await t.step('contains a space', async () => {
8282
await queue
8383
.create({
@@ -86,8 +86,9 @@ Deno.test('queue', async (t) => {
8686
target: 'https://foo.bar',
8787
})
8888
.toPromise()
89-
.then(() => assert(false))
90-
.catch(() => assert(true))
89+
.then((err: any) => {
90+
assertEquals(err.status, 422)
91+
})
9192
})
9293

9394
await t.step('contains a slash', async () => {
@@ -98,8 +99,9 @@ Deno.test('queue', async (t) => {
9899
target: 'https://foo.bar',
99100
})
100101
.toPromise()
101-
.then(() => assert(false))
102-
.catch(() => assert(true))
102+
.then((err: any) => {
103+
assertEquals(err.status, 422)
104+
})
103105
})
104106

105107
await t.step('contains non URI friendly character', async () => {
@@ -110,8 +112,9 @@ Deno.test('queue', async (t) => {
110112
target: 'https://foo.bar',
111113
})
112114
.toPromise()
113-
.then(() => assert(false))
114-
.catch(() => assert(true))
115+
.then((err: any) => {
116+
assertEquals(err.status, 422)
117+
})
115118
})
116119
})
117120
})

0 commit comments

Comments
 (0)