hypercore-fetch 8.6.2-0 → 9.0.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.
@@ -7,7 +7,7 @@ jobs:
7
7
  continue-on-error: true
8
8
  strategy:
9
9
  matrix:
10
- node: [ '16' ]
10
+ node: [ '18' ]
11
11
  os: [ubuntu-latest, windows-latest, macOS-latest]
12
12
  runs-on: ${{ matrix.os }}
13
13
  name: Node ${{ matrix.node }}-${{matrix.os}} tests
package/index.js CHANGED
@@ -317,8 +317,7 @@ export default async function makeHyperFetch ({
317
317
  )
318
318
  }
319
319
 
320
- // TODO: Use 201 with location in response headers
321
- return { status: 200 }
320
+ return { status: 201, headers: { Location: request.url } }
322
321
  })
323
322
  router.delete('hyper://*/**', async function putFiles (request) {
324
323
  const { hostname, pathname } = new URL(request.url)
@@ -409,7 +408,8 @@ export default async function makeHyperFetch ({
409
408
  }
410
409
  }
411
410
  }
412
- const entry = await drive.entry(pathname)
411
+
412
+ const { entry, path } = await resolvePath(drive, pathname, noResolve)
413
413
 
414
414
  if (!entry) {
415
415
  return { status: 404, body: 'Not Found' }
@@ -417,7 +417,7 @@ export default async function makeHyperFetch ({
417
417
 
418
418
  resHeaders.ETag = `${entry.seq}`
419
419
 
420
- const contentType = getMimeType(pathname)
420
+ const contentType = getMimeType(path)
421
421
  resHeaders['Content-Type'] = contentType
422
422
 
423
423
  if (entry.metadata?.mtime) {
@@ -486,7 +486,7 @@ export default async function makeHyperFetch ({
486
486
  }
487
487
 
488
488
  if (accept.includes('text/html')) {
489
- const body = renderIndex(url, entries, fetch)
489
+ const body = await renderIndex(url, entries, fetch)
490
490
  return {
491
491
  status: 200,
492
492
  body,
@@ -506,13 +506,14 @@ export default async function makeHyperFetch ({
506
506
  }
507
507
  }
508
508
  }
509
- const entry = await drive.entry(pathname)
509
+
510
+ const { entry, path } = await resolvePath(drive, pathname, noResolve)
510
511
 
511
512
  if (!entry) {
512
513
  return { status: 404, body: 'Not Found' }
513
514
  }
514
515
 
515
- return serveFile(request.headers, drive, pathname)
516
+ return serveFile(request.headers, drive, path)
516
517
  })
517
518
 
518
519
  return fetch
@@ -568,6 +569,31 @@ async function serveFile (headers, drive, pathname) {
568
569
  }
569
570
  }
570
571
 
572
+ function makeToTry (pathname) {
573
+ return [
574
+ pathname,
575
+ pathname + '.html',
576
+ pathname + '.md'
577
+ ]
578
+ }
579
+
580
+ async function resolvePath (drive, pathname, noResolve) {
581
+ if (noResolve) {
582
+ const entry = drive.entry(pathname)
583
+
584
+ return { entry, path: pathname }
585
+ }
586
+
587
+ for (const path of makeToTry(pathname)) {
588
+ const entry = await drive.entry(path)
589
+ if (entry) {
590
+ return { entry, path }
591
+ }
592
+ }
593
+
594
+ return { entry: null, path: null }
595
+ }
596
+
571
597
  async function listEntries (drive, pathname = '/') {
572
598
  const entries = []
573
599
  for await (const path of drive.readdir(pathname)) {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "hypercore-fetch",
3
- "version": "8.6.2-0",
3
+ "version": "9.0.0",
4
4
  "description": "Implementation of Fetch that uses the Dat SDK for loading p2p content",
5
5
  "type": "module",
6
+ "main": "index.js",
6
7
  "scripts": {
7
8
  "test": "node test",
8
9
  "lint": "standard --fix"
@@ -31,7 +32,7 @@
31
32
  },
32
33
  "devDependencies": {
33
34
  "@rangermauve/fetch-event-source": "^1.0.3",
34
- "hyper-sdk": "^4.1.0",
35
+ "hyper-sdk": "^4.1.1",
35
36
  "standard": "^17.0.0",
36
37
  "tape": "^5.2.2"
37
38
  }
package/test.js CHANGED
@@ -93,11 +93,11 @@ test('PUT file', async (t) => {
93
93
  body: SAMPLE_CONTENT
94
94
  })
95
95
 
96
- await checkResponse(uploadResponse, t)
96
+ await checkResponse(uploadResponse, t, 'upload successful')
97
97
 
98
98
  const uploadedContentResponse = await fetch(uploadLocation)
99
99
 
100
- await checkResponse(uploadedContentResponse, t)
100
+ await checkResponse(uploadedContentResponse, t, 'able to load content')
101
101
 
102
102
  const content = await uploadedContentResponse.text()
103
103
  const contentType = uploadedContentResponse.headers.get('Content-Type')
@@ -272,8 +272,54 @@ test('Ignore index.html with noResolve', async (t) => {
272
272
  const entries = await listDirRequest.json()
273
273
  t.deepEqual(entries, ['index.html'], 'able to list index.html')
274
274
  })
275
- test.skip('Read directory as HTML', async (t) => {
275
+ test('Read directory as HTML', async (t) => {
276
+ const created = await nextURL(t)
277
+
278
+ const formData = new FormData()
279
+ formData.append('file', new Blob([SAMPLE_CONTENT]), 'example.txt')
280
+ formData.append('file', new Blob([SAMPLE_CONTENT]), 'example2.txt')
281
+
282
+ const uploadedResponse = await fetch(created, {
283
+ method: 'put',
284
+ body: formData
285
+ })
286
+ await checkResponse(uploadedResponse, t)
287
+
288
+ const listDirRequest = await fetch(created, {
289
+ headers: {
290
+ Accept: 'text/html'
291
+ }
292
+ })
293
+ await checkResponse(listDirRequest, t, 'Able to list HTML')
294
+
295
+ const html = await listDirRequest.text()
296
+
297
+ t.equal(listDirRequest.headers.get('Content-Type'), 'text/html; charset=utf-8', 'Returned HTML in mime type')
298
+ t.ok(html.includes('<title'), 'Listing has title')
299
+ t.ok(html.includes('./example.txt'), 'Listing has link to file')
300
+ })
301
+ test('Resolve pretty markdown URLs', async (t) => {
302
+ const created = await nextURL(t)
303
+
304
+ const uploadLocation = new URL('./example.md', created)
305
+
306
+ const uploadResponse = await fetch(uploadLocation, {
307
+ method: 'put',
308
+ body: SAMPLE_CONTENT
309
+ })
310
+ await checkResponse(uploadResponse, t)
311
+
312
+ const resolvedLocation = new URL('/example', created)
313
+
314
+ const uploadedContentResponse = await fetch(resolvedLocation)
315
+
316
+ await checkResponse(uploadedContentResponse, t, 'able to load content')
317
+
318
+ const content = await uploadedContentResponse.text()
319
+ const contentType = uploadedContentResponse.headers.get('Content-Type')
276
320
 
321
+ t.equal(content, SAMPLE_CONTENT, 'Got original content out')
322
+ t.equal(contentType, 'text/markdown; charset=utf-8', 'Got markdown mime type')
277
323
  })
278
324
 
279
325
  test('EventSource extension messages', async (t) => {