11import { CID } from "multiformats" ;
22import { UnixFS } from "ipfs-unixfs" ;
3- import * as dagJSON from "multiformats/codecs/json" ;
4- import type { PBLink } from "@ipld/dag-pb" ;
53import PeerId from "peer-id" ;
64import type { Multiaddr } from "multiaddr" ;
7- import { allSelector , Node , parseContext , walkBlocks } from "./traversal" ;
5+ import {
6+ allSelector ,
7+ Node ,
8+ Kind ,
9+ parseContext ,
10+ walkBlocks ,
11+ SelectorNode ,
12+ } from "./traversal" ;
813import mime from "mime/lite" ;
914import type { GraphSync } from "./graphsync" ;
1015
@@ -19,11 +24,37 @@ export function parsePath(path: string): {root: CID; segments: string[]} {
1924 const comps = toPathComponents ( path ) ;
2025 const root = CID . parse ( comps [ 0 ] ) ;
2126 return {
22- segments : comps ,
27+ segments : comps . slice ( 1 ) ,
2328 root,
2429 } ;
2530}
2631
32+ export function unixfsPathSelector ( path : string ) : {
33+ root : CID ;
34+ selector : SelectorNode ;
35+ } {
36+ const { root, segments} = parsePath ( path ) ;
37+ let selector = allSelector ;
38+ if ( segments . length === 0 ) {
39+ return { root, selector} ;
40+ }
41+ for ( let i = segments . length - 1 ; i >= 0 ; i -- ) {
42+ selector = {
43+ "~" : {
44+ as : "unixfs" ,
45+ ">" : {
46+ f : {
47+ "f>" : {
48+ [ segments [ i ] ] : selector ,
49+ } ,
50+ } ,
51+ } ,
52+ } ,
53+ } ;
54+ }
55+ return { root, selector} ;
56+ }
57+
2758export function getPeerID ( addr : Multiaddr ) : PeerId {
2859 const addrStr = addr . toString ( ) ;
2960 const parts = addrStr . split ( "/" ) ;
@@ -39,17 +70,14 @@ export async function* resolve(
3970 provider : Multiaddr ,
4071 exchange : GraphSync
4172) : AsyncIterable < any > {
42- const { segments, root} = parsePath ( path ) ;
43- let cid = root ;
44- let segs = segments . slice ( 1 ) ;
45- const sel = allSelector ;
73+ const { root, selector : sel } = unixfsPathSelector ( path ) ;
4674 const pid = getPeerID ( provider ) ;
4775 exchange . network . peerStore . addressBook . add ( pid , [ provider ] ) ;
48- const request = exchange . request ( cid , sel ) ;
76+ const request = exchange . request ( root , sel ) ;
4977 const id = Date . now ( ) ;
5078 const voucher = {
5179 ID : id ,
52- PayloadCID : cid ,
80+ PayloadCID : root ,
5381 Params : {
5482 Selector : sel ,
5583 PieceCID : null ,
@@ -63,7 +91,7 @@ export async function* resolve(
6391 [ EXTENSION ] : {
6492 IsRq : true ,
6593 Request : {
66- BCid : cid ,
94+ BCid : root ,
6795 Type : 0 ,
6896 Pull : true ,
6997 Paus : false ,
@@ -78,7 +106,7 @@ export async function* resolve(
78106 } ,
79107 } ) ;
80108 for await ( const blk of walkBlocks (
81- new Node ( cid ) ,
109+ new Node ( root ) ,
82110 parseContext ( ) . parseSelector ( sel ) ,
83111 request
84112 ) ) {
@@ -88,46 +116,22 @@ export async function* resolve(
88116 case 0x71 :
89117 break ;
90118 default :
91- console . log ( "raw bytes" ) ;
92119 yield blk . bytes ;
93120 continue ;
94121 }
95- try {
96- const unixfs = UnixFS . unmarshal ( blk . value . Data ) ;
97- if ( unixfs . isDirectory ( ) ) {
98- // if it's a directory and we have a segment to resolve, identify the link
99- if ( segs . length > 0 ) {
100- for ( const link of blk . value . Links ) {
101- if ( link . Name === segs [ 0 ] ) {
102- cid = link . Hash ;
103- segs = segs . slice ( 1 ) ;
104- console . log ( "found link in directory" ) ;
105- continue ;
106- }
122+ if ( blk . value . kind === Kind . Map && blk . value . Data ) {
123+ try {
124+ const unixfs = UnixFS . unmarshal ( blk . value . Data ) ;
125+ if ( unixfs . type === "file" ) {
126+ if ( unixfs . data && unixfs . data . length ) {
127+ yield unixfs . data ;
107128 }
108- throw new Error ( "key not found: " + segs [ 0 ] ) ;
109- } else {
110- // if the block is a directory and we have no key return the entries as JSON
111- yield dagJSON . encode (
112- blk . value . Links . map ( ( l : PBLink ) => ( {
113- name : l . Name ,
114- hash : l . Hash . toString ( ) ,
115- size : l . Tsize ,
116- } ) )
117- ) ;
118- break ;
129+ continue ;
119130 }
120- }
121- if ( unixfs . type === "file" ) {
122- if ( unixfs . data && unixfs . data . length ) {
123- console . log ( "unixfs file" ) ;
124- yield unixfs . data ;
125- }
126- continue ;
127- }
128- } catch ( e ) { }
129- // we're outside of unixfs territory
130- // ignore
131+ } catch ( e ) { }
132+ // we're outside of unixfs territory
133+ // ignore
134+ }
131135 }
132136 // tell the loader we're done receiving blocks for this traversal
133137 request . close ( ) ;
0 commit comments