@toa.io/extensions.storages 0.22.0 → 0.23.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,445 +1,468 @@
1
1
  import { Readable } from 'node:stream'
2
- import { match } from '@toa.io/match'
2
+ import { match } from 'matchacho'
3
3
  import { buffer } from '@toa.io/generic'
4
4
  import { Storage } from './Storage'
5
- import { cases, open, rnd } from './.test/util'
5
+ import { cases, open, rnd } from './test/util'
6
6
  import { type Entry } from './Entry'
7
7
  import { providers } from './providers'
8
+ import type { ErrorType } from 'error-value'
8
9
 
9
10
  let storage: Storage
10
11
  let dir: string
11
12
 
12
- describe.each(cases)('%s', (_, url, secrets) => {
13
- beforeEach(() => {
14
- dir = '/' + rnd()
13
+ const [, url, secrets] = cases[0]
15
14
 
16
- const Provider = providers[url.protocol]
17
- const provider = new Provider(url, secrets)
15
+ beforeEach(() => {
16
+ dir = '/' + rnd()
18
17
 
19
- storage = new Storage(provider)
20
- })
18
+ const Provider = providers[url.protocol]
19
+ const provider = new Provider(url, secrets)
21
20
 
22
- it('should be', async () => {
23
- expect(storage).toBeInstanceOf(Storage)
24
- })
21
+ storage = new Storage(provider)
22
+ })
25
23
 
26
- it('should return error if entry is not found', async () => {
27
- const result = await storage.get('not-found')
24
+ it('should be', async () => {
25
+ expect(storage).toBeInstanceOf(Storage)
26
+ })
28
27
 
29
- match(result,
30
- Error, (error: Error) => expect(error.message).toBe('NOT_FOUND'))
31
- })
28
+ it('should return error if entry is not found', async () => {
29
+ const result = await storage.get('not-found')
32
30
 
33
- describe('put', () => {
34
- let lenna: Entry
31
+ if (!(result instanceof Error))
32
+ throw new Error('Expected error')
35
33
 
36
- beforeEach(async () => {
37
- const stream = await open('lenna.png')
34
+ expect(result).toMatchObject({ code: 'NOT_FOUND' })
35
+ })
38
36
 
39
- lenna = await storage.put(dir, stream) as Entry
40
- })
37
+ describe('put', () => {
38
+ let lenna: Entry
39
+ let startCreation: number
41
40
 
42
- it('should not return error', async () => {
43
- expect(lenna).not.toBeInstanceOf(Error)
44
- })
41
+ beforeEach(async () => {
42
+ const stream = open('lenna.png')
45
43
 
46
- it('should return entry id', async () => {
47
- expect(lenna.id).toBeDefined()
48
- })
44
+ startCreation = Date.now()
45
+ lenna = await storage.put(dir, stream) as Entry
46
+ })
49
47
 
50
- it('should return id as checksum', async () => {
51
- const stream = await open('lenna.png')
52
- const dir2 = '/' + rnd()
53
- const copy = await storage.put(dir2, stream) as Entry
48
+ it('should not return error', async () => {
49
+ expect(lenna).not.toBeInstanceOf(Error)
50
+ })
54
51
 
55
- expect(copy.id).toBe(lenna.id)
56
- })
52
+ it('should return entry id', async () => {
53
+ expect(lenna.id).toBeDefined()
54
+ })
57
55
 
58
- it('should detect file type', async () => {
59
- expect(lenna.type).toBe('image/png')
60
- })
56
+ it('should return id as checksum', async () => {
57
+ const stream = open('lenna.png')
58
+ const dir2 = '/' + rnd()
59
+ const copy = await storage.put(dir2, stream) as Entry
61
60
 
62
- it('should count size', async () => {
63
- expect(lenna.size).toBe(473831)
61
+ expect(copy.id).toBe(lenna.id)
62
+ })
63
+
64
+ it('should detect file type', async () => {
65
+ expect(lenna.type).toBe('image/png')
66
+ })
67
+
68
+ it('should count size', async () => {
69
+ expect(lenna.size).toBe(473831)
70
+ })
71
+
72
+ it('should return entry', async () => {
73
+ expect(lenna).toMatchObject({
74
+ id: lenna.id,
75
+ type: 'image/png',
76
+ variants: [],
77
+ meta: {}
64
78
  })
79
+ })
65
80
 
66
- it('should return entry', async () => {
67
- expect(lenna).toMatchObject({
81
+ it('should create entry', async () => {
82
+ const entry = await storage.get(`${dir}/${lenna.id}`)
83
+
84
+ match(entry,
85
+ {
68
86
  id: lenna.id,
69
87
  type: 'image/png',
70
88
  variants: [],
71
89
  meta: {}
72
- })
73
- })
90
+ }, undefined)
91
+ })
74
92
 
75
- it('should create entry', async () => {
76
- const entry = await storage.get(`${dir}/${lenna.id}`)
93
+ it('should set timestamp', async () => {
94
+ const now = Date.now()
95
+ const entry = await storage.get(`${dir}/${lenna.id}`) as Entry
77
96
 
78
- match(entry,
79
- {
80
- id: lenna.id,
81
- type: 'image/png',
82
- variants: [],
83
- meta: {}
84
- }, undefined)
85
- })
97
+ expect(entry.created).toBeLessThanOrEqual(now)
98
+ expect(entry.created).toBeGreaterThanOrEqual(startCreation)
99
+ })
86
100
 
87
- it('should set timestamp', async () => {
88
- const now = Date.now()
89
- const entry = await storage.get(`${dir}/${lenna.id}`) as Entry
101
+ describe('existing entry', () => {
102
+ it('should unhide existing', async () => {
103
+ const stream = open('lenna.png')
104
+ const path = `${dir}/${lenna.id}`
90
105
 
91
- expect(entry.created).toBeLessThanOrEqual(now)
92
- expect(entry.created).toBeGreaterThan(now - 100)
93
- })
106
+ await storage.conceal(path)
107
+ await storage.put(dir, stream)
108
+
109
+ const list = await storage.list(dir)
94
110
 
95
- describe('existing entry', () => {
96
- it('should unhide existing', async () => {
97
- const stream = await open('lenna.png')
98
- const path = `${dir}/${lenna.id}`
111
+ expect(list).toContainEqual(lenna.id)
112
+ })
99
113
 
100
- await storage.conceal(path)
101
- await storage.put(dir, stream)
114
+ it('should preserve meta', async () => {
115
+ const path = `${dir}/${lenna.id}`
116
+ const stream = open('lenna.png')
102
117
 
103
- const list = await storage.list(dir)
118
+ await storage.annotate(path, 'foo', 'bar')
119
+ await storage.put(dir, stream)
104
120
 
105
- expect(list).toContainEqual(lenna.id)
106
- })
121
+ const entry = await storage.get(path) as Entry
107
122
 
108
- it('should preserve meta', async () => {
109
- const path = `${dir}/${lenna.id}`
110
- const stream = await open('lenna.png')
123
+ expect(entry.meta).toMatchObject({ foo: 'bar' })
124
+ })
125
+ })
126
+ })
111
127
 
112
- await storage.annotate(path, 'foo', 'bar')
113
- await storage.put(dir, stream)
128
+ describe('list', () => {
129
+ let albert: Entry
130
+ let lenna: Entry
114
131
 
115
- const entry = await storage.get(path) as Entry
132
+ beforeEach(async () => {
133
+ const stream0 = open('albert.jpg')
134
+ const stream1 = open('lenna.png')
116
135
 
117
- expect(entry.meta).toMatchObject({ foo: 'bar' })
118
- })
119
- })
136
+ albert = await storage.put(dir, stream0) as Entry
137
+ lenna = await storage.put(dir, stream1) as Entry
120
138
  })
121
139
 
122
- describe('list', () => {
123
- let albert: Entry
124
- let lenna: Entry
140
+ it('should list entries', async () => {
141
+ const list = await storage.list(dir)
125
142
 
126
- beforeEach(async () => {
127
- const stream0 = await open('albert.jpg')
128
- const stream1 = await open('lenna.png')
143
+ expect(list).toMatchObject([albert.id, lenna.id])
144
+ })
129
145
 
130
- albert = await storage.put(dir, stream0) as Entry
131
- lenna = await storage.put(dir, stream1) as Entry
132
- })
146
+ it('should permutate', async () => {
147
+ const error = await storage.permute(dir, [lenna.id, albert.id])
133
148
 
134
- it('should list entries', async () => {
135
- const list = await storage.list(dir)
149
+ expect(error).toBeUndefined()
136
150
 
137
- expect(list).toMatchObject([albert.id, lenna.id])
138
- })
151
+ const list = await storage.list(dir)
139
152
 
140
- it('should permutate', async () => {
141
- const error = await storage.reorder(dir, [lenna.id, albert.id])
153
+ expect(list).toMatchObject([lenna.id, albert.id])
154
+ })
142
155
 
143
- expect(error).toBeUndefined()
156
+ it('should return PERMUTATION_MISMATCH', async () => {
157
+ const cases = [
158
+ [lenna.id],
159
+ [albert.id, lenna.id, 'unknown'],
160
+ [lenna.id, lenna.id],
161
+ [lenna.id, lenna.id, albert.id]
162
+ ]
144
163
 
145
- const list = await storage.list(dir)
164
+ for (const permutation of cases) {
165
+ const error = await storage.permute(dir, permutation)
146
166
 
147
- expect(list).toMatchObject([lenna.id, albert.id])
148
- })
167
+ expect(error).toBeInstanceOf(Error)
168
+ expect(error).toMatchObject({ code: 'PERMUTATION_MISMATCH' })
169
+ }
170
+ })
149
171
 
150
- it('should return PERMUTATION_MISMATCH', async () => {
151
- const cases = [
152
- [lenna.id],
153
- [albert.id, lenna.id, 'unknown'],
154
- [lenna.id, lenna.id],
155
- [lenna.id, lenna.id, albert.id]
156
- ]
172
+ it('should exclude concealed', async () => {
173
+ const path = `${dir}/${lenna.id}`
157
174
 
158
- for (const permutation of cases) {
159
- const error = await storage.reorder(dir, permutation)
175
+ await storage.conceal(path)
160
176
 
161
- expect(error).toBeInstanceOf(Error)
162
- expect(error).toMatchObject({ message: 'PERMUTATION_MISMATCH' })
163
- }
164
- })
177
+ const entries = await storage.list(dir)
165
178
 
166
- it('should exclude concealed', async () => {
167
- const path = `${dir}/${lenna.id}`
179
+ expect(entries).toMatchObject([albert.id])
180
+ })
168
181
 
169
- await storage.conceal(path)
182
+ it('should reveal', async () => {
183
+ const path = `${dir}/${lenna.id}`
170
184
 
171
- const entries = await storage.list(dir)
185
+ await storage.conceal(path)
186
+ await storage.reveal(path)
187
+ await storage.reveal(path) // test that no duplicates are created
172
188
 
173
- expect(entries).toMatchObject([albert.id])
174
- })
189
+ const entries = await storage.list(dir)
175
190
 
176
- it('should reveal', async () => {
177
- const path = `${dir}/${lenna.id}`
191
+ expect(entries).toMatchObject([albert.id, lenna.id])
192
+ })
178
193
 
179
- await storage.conceal(path)
180
- await storage.reveal(path)
181
- await storage.reveal(path) // test that no duplicates are created
194
+ it('should return ERR_NOT_FOOUD if entry doesnt exist', async () => {
195
+ const path = `${dir}/oopsie`
182
196
 
183
- const entries = await storage.list(dir)
197
+ const methods: Array<'reveal' | 'conceal'> = ['reveal', 'conceal']
184
198
 
185
- expect(entries).toMatchObject([albert.id, lenna.id])
186
- })
199
+ for (const method of methods) {
200
+ const error = await storage[method](path)
187
201
 
188
- it('should return ERR_NOT_FOOUD if entry doesnt exist', async () => {
189
- const path = `${dir}/oopsie`
202
+ expect(error).toBeInstanceOf(Error)
203
+ expect(error).toMatchObject({ code: 'NOT_FOUND' })
204
+ }
205
+ })
206
+ })
190
207
 
191
- const methods: Array<'reveal' | 'conceal'> = ['reveal', 'conceal']
208
+ describe('annotate', () => {
209
+ let lenna: Entry
192
210
 
193
- for (const method of methods) {
194
- const error = await storage[method](path)
211
+ beforeEach(async () => {
212
+ const stream = open('lenna.png')
195
213
 
196
- expect(error).toBeInstanceOf(Error)
197
- expect(error).toMatchObject({ message: 'NOT_FOUND' })
198
- }
199
- })
214
+ lenna = await storage.put(dir, stream) as Entry
200
215
  })
201
216
 
202
- describe('annotate', () => {
203
- let lenna: Entry
217
+ it('should set meta', async () => {
218
+ const path = `${dir}/${lenna.id}`
204
219
 
205
- beforeEach(async () => {
206
- const stream = await open('lenna.png')
220
+ await storage.annotate(path, 'foo', 'bar')
207
221
 
208
- lenna = await storage.put(dir, stream) as Entry
209
- })
222
+ const state0 = await storage.get(path) as Entry
210
223
 
211
- it('should set meta', async () => {
212
- const path = `${dir}/${lenna.id}`
224
+ expect(state0.meta).toMatchObject({ foo: 'bar' })
213
225
 
214
- await storage.annotate(path, 'foo', 'bar')
226
+ await storage.annotate(path, 'foo')
215
227
 
216
- const state0 = await storage.get(path) as Entry
228
+ const state1 = await storage.get(path) as Entry
217
229
 
218
- expect(state0.meta).toMatchObject({ foo: 'bar' })
230
+ expect('foo' in state1.meta).toBe(false)
231
+ })
232
+ })
219
233
 
220
- await storage.annotate(path, 'foo')
234
+ describe('variants', () => {
235
+ let lenna: Entry
221
236
 
222
- const state1 = await storage.get(path) as Entry
237
+ beforeEach(async () => {
238
+ const stream = open('lenna.png')
223
239
 
224
- expect('foo' in state1.meta).toBe(false)
225
- })
240
+ lenna = await storage.put(dir, stream) as Entry
226
241
  })
227
242
 
228
- describe('variants', () => {
229
- let lenna: Entry
243
+ it('should add variant', async () => {
244
+ const stream = open('sample.jpeg')
230
245
 
231
- beforeEach(async () => {
232
- const stream = await open('lenna.png')
246
+ const path = `${dir}/${lenna.id}`
233
247
 
234
- lenna = await storage.put(dir, stream) as Entry
235
- })
248
+ await storage.diversify(path, 'foo', stream)
236
249
 
237
- it('should add variant', async () => {
238
- const stream = await open('sample.jpeg')
250
+ const state = await storage.get(path) as Entry
239
251
 
240
- const path = `${dir}/${lenna.id}`
252
+ expect(state.variants).toMatchObject([{ name: 'foo', size: 73444, type: 'image/jpeg' }])
253
+ })
241
254
 
242
- await storage.diversify(path, 'foo', stream)
255
+ it('should replace variant', async () => {
256
+ const stream0 = open('sample.jpeg')
257
+ const stream1 = open('sample.webp')
258
+ const path = `${dir}/${lenna.id}`
243
259
 
244
- const state = await storage.get(path) as Entry
260
+ await storage.diversify(path, 'foo', stream0)
261
+ await storage.diversify(path, 'foo', stream1)
245
262
 
246
- expect(state.variants).toMatchObject([{ name: 'foo', size: 73444, type: 'image/jpeg' }])
247
- })
263
+ const state = await storage.get(path) as Entry
248
264
 
249
- it('should replace variant', async () => {
250
- const stream0 = await open('sample.jpeg')
251
- const stream1 = await open('sample.webp')
252
- const path = `${dir}/${lenna.id}`
265
+ expect(state.variants).toMatchObject([{ name: 'foo', type: 'image/webp' }])
266
+ })
267
+ })
253
268
 
254
- await storage.diversify(path, 'foo', stream0)
255
- await storage.diversify(path, 'foo', stream1)
269
+ describe('fetch', () => {
270
+ let lenna: Entry
256
271
 
257
- const state = await storage.get(path) as Entry
272
+ beforeEach(async () => {
273
+ const stream = open('lenna.png')
258
274
 
259
- expect(state.variants).toMatchObject([{ name: 'foo', type: 'image/webp' }])
260
- })
275
+ lenna = await storage.put(dir, stream) as Entry
261
276
  })
262
277
 
263
- describe('fetch', () => {
264
- let lenna: Entry
278
+ it('should fetch', async () => {
279
+ const path = `${dir}/${lenna.id}`
280
+ const stream = await storage.fetch(path)
265
281
 
266
- beforeEach(async () => {
267
- const stream = await open('lenna.png')
282
+ const stored: Buffer = await match(stream,
283
+ Readable, async (stream: Readable) => await buffer(stream))
268
284
 
269
- lenna = await storage.put(dir, stream) as Entry
270
- })
285
+ const buf = await buffer(open('lenna.png'))
271
286
 
272
- it('should fetch', async () => {
273
- const path = `${dir}/${lenna.id}`
274
- const stream = await storage.fetch(path)
287
+ expect(stored.compare(buf)).toBe(0)
288
+ })
275
289
 
276
- const stored: Buffer = await match(stream,
277
- Readable, async (stream: Readable) => await buffer(stream))
290
+ it('should fetch blob by id', async () => {
291
+ const stream = open('lenna.ascii')
292
+ const entry = await storage.put(dir, stream) as Entry
293
+ const stored = await storage.fetch(entry.id)
278
294
 
279
- const buf = await buffer(await open('lenna.png'))
295
+ if (stored instanceof Error)
296
+ throw stored
280
297
 
281
- expect(stored.compare(buf)).toBe(0)
282
- })
298
+ const buf = await buffer(stored)
299
+ const expected = await buffer(open('lenna.ascii'))
283
300
 
284
- it('should fetch blob by id', async () => {
285
- const stream = await open('lenna.ascii')
286
- const entry = await storage.put(dir, stream) as Entry
287
- const stored = await storage.fetch(entry.id)
301
+ expect(buf.compare(expected)).toBe(0)
302
+ })
288
303
 
289
- if (stored instanceof Error)
290
- throw stored
304
+ it('should fetch variant', async () => {
305
+ const stream = open('sample.jpeg')
291
306
 
292
- const buf = await buffer(stored)
293
- const expected = await buffer(await open('lenna.ascii'))
307
+ const buf = await buffer(stream)
308
+ const path = `${dir}/${lenna.id}`
294
309
 
295
- expect(buf.compare(expected)).toBe(0)
296
- })
310
+ await storage.diversify(path, '100x100.jpeg', Readable.from(buf))
297
311
 
298
- it('should fetch variant', async () => {
299
- const stream = await open('sample.jpeg')
312
+ const variant = await storage.fetch(`${path}.100x100.jpeg`)
300
313
 
301
- const buf = await buffer(stream)
302
- const path = `${dir}/${lenna.id}`
314
+ const stored = await match<Promise<Buffer>>(variant,
315
+ Readable, async (stream: Readable) => await buffer(stream))
303
316
 
304
- await storage.diversify(path, '100x100.jpeg', Readable.from(buf))
317
+ expect(stored.compare(buf)).toBe(0)
318
+ })
305
319
 
306
- const variant = await storage.fetch(`${path}.100x100.jpeg`)
320
+ it('should not fetch blob by id and fake path', async () => {
321
+ const stored = await storage.fetch(`fake/${lenna.id}`)
307
322
 
308
- const stored = await match(variant,
309
- Readable, async (stream: Readable) => await buffer(stream))
323
+ match(stored,
324
+ Error, (error: ErrorType) => expect(error.code).toBe('NOT_FOUND'))
325
+ })
326
+ })
310
327
 
311
- expect(stored.compare(buf)).toBe(0)
312
- })
328
+ describe('delete', () => {
329
+ let lenna: Entry
313
330
 
314
- it('should not fetch blob by id and fake path', async () => {
315
- const stored = await storage.fetch(`fake/${lenna.id}`)
331
+ beforeEach(async () => {
332
+ const stream = open('lenna.png')
316
333
 
317
- match(stored,
318
- Error, (error: Error) => expect(error.message).toBe('NOT_FOUND'))
319
- })
334
+ lenna = await storage.put(dir, stream) as Entry
320
335
  })
321
336
 
322
- describe('delete', () => {
323
- let lenna: Entry
337
+ it('should remove from the list', async () => {
338
+ await storage.delete(`${dir}/${lenna.id}`)
324
339
 
325
- beforeEach(async () => {
326
- const stream = await open('lenna.png')
340
+ const list = await storage.list(dir)
327
341
 
328
- lenna = await storage.put(dir, stream) as Entry
329
- })
342
+ expect(list).not.toContain(lenna.id)
343
+ })
330
344
 
331
- it('should remove from the list', async () => {
332
- await storage.delete(`${dir}/${lenna.id}`)
345
+ it('should delete entry', async () => {
346
+ await storage.delete(`${dir}/${lenna.id}`)
333
347
 
334
- const list = await storage.list(dir)
348
+ const result = await storage.get(`${dir}/${lenna.id}`)
335
349
 
336
- expect(list).not.toContain(lenna.id)
337
- })
350
+ match(result,
351
+ Error, (error: ErrorType) => expect(error.code).toBe('NOT_FOUND'))
352
+ })
338
353
 
339
- it('should delete entry', async () => {
340
- await storage.delete(`${dir}/${lenna.id}`)
354
+ it('should delete variants', async () => {
355
+ const stream = open('sample.jpeg')
341
356
 
342
- const result = await storage.get(`${dir}/${lenna.id}`)
357
+ const path = `${dir}/${lenna.id}`
343
358
 
344
- match(result,
345
- Error, (error: Error) => expect(error.message).toBe('NOT_FOUND'))
346
- })
359
+ await storage.diversify(path, 'foo', stream)
360
+ await storage.delete(`${dir}/${lenna.id}`)
347
361
 
348
- it('should delete variants', async () => {
349
- const stream = await open('sample.jpeg')
362
+ const variant = await storage.fetch(`${path}.foo`)
350
363
 
351
- const path = `${dir}/${lenna.id}`
364
+ match(variant,
365
+ Error, (error: ErrorType) => expect(error.code).toBe('NOT_FOUND'))
352
366
 
353
- await storage.diversify(path, 'foo', stream)
354
- await storage.delete(`${dir}/${lenna.id}`)
367
+ stream.destroy()
368
+ })
355
369
 
356
- const variant = await storage.fetch(`${path}.foo`)
370
+ it('should throw if path is not an entry', async () => {
371
+ const result = await storage.delete(dir)
357
372
 
358
- match(variant,
359
- Error, (error: Error) => expect(error.message).toBe('NOT_FOUND'))
373
+ expect(result).toBeInstanceOf(Error)
374
+ expect(result).toMatchObject({ code: 'NOT_FOUND' })
375
+ })
376
+ })
360
377
 
361
- stream.destroy()
362
- })
378
+ describe('signatures', () => {
379
+ it.each(['jpeg', 'gif', 'webp', 'heic', 'jxl', 'avif'])('should detect image/%s',
380
+ async (type) => {
381
+ const stream = open('sample.' + type)
363
382
 
364
- it('should throw if path is not an entry', async () => {
365
- const result = await storage.delete(dir)
383
+ const entry = await storage.put(dir, stream) as Entry
366
384
 
367
- expect(result).toBeInstanceOf(Error)
368
- expect(result).toMatchObject({ message: 'NOT_FOUND' })
385
+ expect(entry.type).toBe('image/' + type)
369
386
  })
370
- })
387
+ })
371
388
 
372
- describe('signatures', () => {
373
- it.each(['jpeg', 'gif', 'webp', 'heic', 'jxl', 'avif'])('should detect image/%s',
374
- async (type) => {
375
- const stream = await open('sample.' + type)
389
+ it('should return error if type doesnt match', async () => {
390
+ const stream = open('sample.jpeg')
376
391
 
377
- const entry = await storage.put(dir, stream) as Entry
392
+ const result = await storage.put(dir, stream, { claim: 'image/png' })
378
393
 
379
- expect(entry.type).toBe('image/' + type)
380
- })
381
- })
394
+ match(result,
395
+ Error, (error: ErrorType) => expect(error.code).toBe('TYPE_MISMATCH'))
396
+ })
382
397
 
383
- it('should return error if type doesnt match', async () => {
384
- const stream = await open('sample.jpeg')
398
+ it('should trust unknown types', async () => {
399
+ const stream = open('lenna.ascii')
385
400
 
386
- const result = await storage.put(dir, stream, 'image/png')
401
+ const result = await storage.put(dir, stream, { claim: 'text/plain' })
387
402
 
388
- match(result,
389
- Error, (error: Error) => expect(error.message).toBe('TYPE_MISMATCH'))
390
- })
403
+ expect(result).not.toBeInstanceOf(Error)
404
+ expect(result).toMatchObject({ type: 'text/plain' })
405
+ })
391
406
 
392
- it('should trust unknown types', async () => {
393
- const stream = await open('lenna.ascii')
407
+ it('should return error if type is identifiable', async () => {
408
+ const stream = open('lenna.ascii')
394
409
 
395
- const result = await storage.put(dir, stream, 'text/plain')
410
+ const result = await storage.put(dir, stream, { claim: 'image/jpeg' })
396
411
 
397
- expect(result).not.toBeInstanceOf(Error)
398
- expect(result).toMatchObject({ type: 'text/plain' })
399
- })
412
+ expect(result).toBeInstanceOf(Error)
413
+ expect(result).toMatchObject({ code: 'TYPE_MISMATCH' })
414
+ })
400
415
 
401
- it('should return error if type is identifiable', async () => {
402
- const stream = await open('lenna.ascii')
416
+ it('should not return error if type application/octet-stream', async () => {
417
+ const stream = open('sample.jpeg')
403
418
 
404
- const result = await storage.put(dir, stream, 'image/jpeg')
419
+ const result = await storage.put(dir, stream, { claim: 'application/octet-stream' })
405
420
 
406
- expect(result).toBeInstanceOf(Error)
407
- expect(result).toMatchObject({ message: 'TYPE_MISMATCH' })
408
- })
421
+ expect(result).not.toBeInstanceOf(Error)
422
+ expect(result).toMatchObject({ type: 'image/jpeg' })
423
+ })
409
424
 
410
- it('should not return error if type application/octet-stream', async () => {
411
- const stream = await open('sample.jpeg')
425
+ it('should return error if type is not acceptable', async () => {
426
+ const stream = open('sample.jpeg')
412
427
 
413
- const result = await storage.put(dir, stream, 'application/octet-stream')
428
+ const result = await storage.put(dir, stream, { accept: 'image/png' })
414
429
 
415
- expect(result).not.toBeInstanceOf(Error)
416
- expect(result).toMatchObject({ type: 'image/jpeg' })
417
- })
430
+ match(result,
431
+ Error, (error: ErrorType) => expect(error.code).toBe('NOT_ACCEPTABLE'))
432
+ })
418
433
 
419
- it('should handle root entries', async () => {
420
- const stream = await open('sample.jpeg')
434
+ it('should accept wildcard types', async () => {
435
+ const stream = open('sample.jpeg')
421
436
 
422
- const result = await storage.put('hello', stream) as Entry
437
+ const result = await storage.put(dir, stream, { accept: 'image/*' })
423
438
 
424
- expect(result).not.toBeInstanceOf(Error)
439
+ expect(result).not.toBeInstanceOf(Error)
440
+ expect(result).toMatchObject({ type: 'image/jpeg' })
441
+ })
425
442
 
426
- const stored = await storage.fetch(result.id)
443
+ it('should handle root entries', async () => {
444
+ const stream = open('sample.jpeg')
427
445
 
428
- expect(stored).not.toBeInstanceOf(Error)
429
- })
446
+ const result = await storage.put('hello', stream) as Entry
430
447
 
431
- it('should store empty file', async () => {
432
- const stream = await open('empty.txt')
433
- const result = await storage.put('empty', stream) as Entry
448
+ expect(result).not.toBeInstanceOf(Error)
434
449
 
435
- expect(result.size).toBe(0)
450
+ const stored = await storage.fetch(result.id)
436
451
 
437
- const stored = await storage.fetch(result.id) as Readable
452
+ expect(stored).not.toBeInstanceOf(Error)
453
+ })
438
454
 
439
- expect(stored).not.toBeInstanceOf(Error)
455
+ it('should store empty file', async () => {
456
+ const stream = open('empty.txt')
457
+ const result = await storage.put('empty', stream) as Entry
440
458
 
441
- const buf = await buffer(stored)
459
+ expect(result.size).toBe(0)
442
460
 
443
- expect(buf.length).toBe(0)
444
- })
461
+ const stored = await storage.fetch(result.id) as Readable
462
+
463
+ expect(stored).not.toBeInstanceOf(Error)
464
+
465
+ const buf = await buffer(stored)
466
+
467
+ expect(buf.length).toBe(0)
445
468
  })