@helia/car 5.1.0 → 5.1.1-4e5ff555

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 +1 @@
1
- {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../../src/car.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAU,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,qBAAa,GAAI,YAAW,YAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEf,UAAU,EAAE,aAAa;IAKhC,MAAM,CAAE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,eAAe,CAAC,2BAA2B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9H,MAAM,CAAE,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC;YAkC7F,OAAO;CAgEtB"}
1
+ {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../../src/car.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAU,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,qBAAa,GAAI,YAAW,YAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEf,UAAU,EAAE,aAAa;IAKhC,MAAM,CAAE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,eAAe,CAAC,2BAA2B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9H,MAAM,CAAE,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC;YAoC7F,OAAO;CAuEtB"}
package/dist/src/car.js CHANGED
@@ -2,7 +2,7 @@ import { CarWriter } from '@ipld/car';
2
2
  import drain from 'it-drain';
3
3
  import map from 'it-map';
4
4
  import { raceSignal } from 'race-signal';
5
- import { DAG_PB_CODEC_CODE } from "./constants.js";
5
+ import { DAG_PB_CODEC_CODE, IDENTITY_CODEC_CODE } from "./constants.js";
6
6
  import { SubgraphExporter } from './export-strategies/subgraph-exporter.js';
7
7
  import { UnixFSExporter } from './index.js';
8
8
  export class Car {
@@ -16,12 +16,13 @@ export class Car {
16
16
  await drain(this.components.blockstore.putMany(map(reader.blocks(), ({ cid, bytes }) => ({ cid, bytes })), options));
17
17
  }
18
18
  async *export(root, options) {
19
- const { writer, out } = CarWriter.create(root);
19
+ const roots = (Array.isArray(root) ? root : [root]);
20
+ const { writer, out } = CarWriter.create(roots);
20
21
  const iter = out[Symbol.asyncIterator]();
21
22
  const controller = new AbortController();
22
23
  // has to be done async so we write to `writer` and read from `out` at the
23
24
  // same time
24
- this._export(root, writer, options)
25
+ this._export(roots, writer, options)
25
26
  .catch((err) => {
26
27
  this.log.error('error during streaming export - %e', err);
27
28
  controller.abort(err);
@@ -43,10 +44,12 @@ export class Car {
43
44
  }
44
45
  }
45
46
  }
46
- async _export(root, writer, options) {
47
- const roots = Array.isArray(root) ? root : [root];
47
+ async _export(roots, writer, options) {
48
48
  const traversalStrategy = options?.traversal;
49
49
  for (const root of roots) {
50
+ if (root.multihash.code === IDENTITY_CODEC_CODE) {
51
+ continue;
52
+ }
50
53
  const exportStrategy = options?.exporter ?? (root.code === DAG_PB_CODEC_CODE ? new UnixFSExporter() : new SubgraphExporter());
51
54
  let current = root;
52
55
  let underRoot = false;
@@ -79,6 +82,9 @@ export class Car {
79
82
  if (options?.blockFilter?.has(cid.multihash.bytes) === true) {
80
83
  continue;
81
84
  }
85
+ if (cid.multihash.code === IDENTITY_CODEC_CODE) {
86
+ continue;
87
+ }
82
88
  // skip the export target block if we have already included it during
83
89
  // traversal
84
90
  if (underRoot && cid.equals(current)) {
@@ -1 +1 @@
1
- {"version":3,"file":"car.js","sourceRoot":"","sources":["../../src/car.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"car.js","sourceRoot":"","sources":["../../src/car.ts"],"names":[],"mappings":"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"}
@@ -7,4 +7,8 @@ export declare const DAG_PB_CODEC_CODE = 112;
7
7
  * The multicodec code for raw binary data
8
8
  */
9
9
  export declare const RAW_PB_CODEC_CODE = 85;
10
+ /**
11
+ * The multicodec code for identity hashes
12
+ */
13
+ export declare const IDENTITY_CODEC_CODE = 0;
10
14
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C;;GAEG;AACH,eAAO,MAAM,iBAAiB,MAAO,CAAA;AAErC;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAAO,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C;;GAEG;AACH,eAAO,MAAM,iBAAiB,MAAO,CAAA;AAErC;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAAO,CAAA;AAErC;;GAEG;AACH,eAAO,MAAM,mBAAmB,IAAO,CAAA"}
@@ -7,4 +7,8 @@ export const DAG_PB_CODEC_CODE = 0x70;
7
7
  * The multicodec code for raw binary data
8
8
  */
9
9
  export const RAW_PB_CODEC_CODE = 0x55;
10
+ /**
11
+ * The multicodec code for identity hashes
12
+ */
13
+ export const IDENTITY_CODEC_CODE = 0x00;
10
14
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAA"}
@@ -4,6 +4,35 @@ import type { AbortOptions } from '@libp2p/interface';
4
4
  import type { Blockstore } from 'interface-blockstore';
5
5
  import type { BlockView } from 'multiformats';
6
6
  import type { CID } from 'multiformats/cid';
7
+ export interface UnixFSExporterOptions {
8
+ /**
9
+ * Include blocks that start with this offset.
10
+ *
11
+ * If the CID being exported is a directory, this option is ignored.
12
+ *
13
+ * @default 0
14
+ */
15
+ offset?: number;
16
+ /**
17
+ * Only include blocks that would include this many file bytes (exclusive,
18
+ * inclusive of offset).
19
+ *
20
+ * If the CID being exported is a directory, this option is ignored.
21
+ *
22
+ * @default Infinity
23
+ */
24
+ length?: number;
25
+ /**
26
+ * By default an exported CAR file will include all blocks that make up a
27
+ * directory, and the files that are stored there.
28
+ *
29
+ * To only include blocks that allow the initial enumeration of the directory,
30
+ * pass `true` here
31
+ *
32
+ * @default false
33
+ */
34
+ listingOnly?: boolean;
35
+ }
7
36
  /**
8
37
  * Traverses the DAG depth-first starting at the target CID and yields all
9
38
  * encountered blocks.
@@ -12,6 +41,8 @@ import type { CID } from 'multiformats/cid';
12
41
  * the helia config.
13
42
  */
14
43
  export declare class UnixFSExporter implements ExportStrategy {
44
+ private options?;
45
+ constructor(options?: UnixFSExporterOptions);
15
46
  export(cid: CID, blockstore: Blockstore, getCodec: CodecLoader, options?: AbortOptions): AsyncGenerator<BlockView<unknown, number, number, 0 | 1>, void, undefined>;
16
47
  }
17
48
  //# sourceMappingURL=unixfs-exporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"unixfs-exporter.d.ts","sourceRoot":"","sources":["../../../src/export-strategies/unixfs-exporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C;;;;;;GAMG;AACH,qBAAa,cAAe,YAAW,cAAc;IAC3C,MAAM,CAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC;CAc7K"}
1
+ {"version":3,"file":"unixfs-exporter.d.ts","sourceRoot":"","sources":["../../../src/export-strategies/unixfs-exporter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,GAAG,EAAW,MAAM,kBAAkB,CAAA;AAEpD,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAsBD;;;;;;GAMG;AACH,qBAAa,cAAe,YAAW,cAAc;IACnD,OAAO,CAAC,OAAO,CAAC,CAAuB;gBAE1B,OAAO,CAAC,EAAE,qBAAqB;IAIpC,MAAM,CAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC;CA6F7K"}
@@ -1,6 +1,27 @@
1
1
  import { depthFirstWalker } from '@helia/utils';
2
+ import { setMaxListeners, InvalidParametersError } from '@libp2p/interface';
3
+ import { anySignal } from 'any-signal';
4
+ import { UnixFS } from 'ipfs-unixfs';
2
5
  import { DAG_PB_CODEC_CODE, RAW_PB_CODEC_CODE } from "../constants.js";
3
6
  import { NotUnixFSError } from "../errors.js";
7
+ function isRawBlock(block) {
8
+ return block.cid.code === RAW_PB_CODEC_CODE;
9
+ }
10
+ function isDagPBBlock(block) {
11
+ return block.cid.code === DAG_PB_CODEC_CODE;
12
+ }
13
+ function isFile(block) {
14
+ if (isRawBlock(block)) {
15
+ return true;
16
+ }
17
+ else if (isDagPBBlock(block) && block.value.Data != null) {
18
+ const u = UnixFS.unmarshal(block.value.Data);
19
+ return u.type === 'file' || u.type === 'raw';
20
+ }
21
+ else {
22
+ throw new NotUnixFSError('Encountered non raw/dag-pb CID in UnixFS DAG');
23
+ }
24
+ }
4
25
  /**
5
26
  * Traverses the DAG depth-first starting at the target CID and yields all
6
27
  * encountered blocks.
@@ -9,6 +30,10 @@ import { NotUnixFSError } from "../errors.js";
9
30
  * the helia config.
10
31
  */
11
32
  export class UnixFSExporter {
33
+ options;
34
+ constructor(options) {
35
+ this.options = options;
36
+ }
12
37
  async *export(cid, blockstore, getCodec, options) {
13
38
  if (cid.code !== DAG_PB_CODEC_CODE && cid.code !== RAW_PB_CODEC_CODE) {
14
39
  throw new NotUnixFSError('Target CID was not UnixFS - use the SubGraphExporter to export arbitrary graphs');
@@ -17,8 +42,72 @@ export class UnixFSExporter {
17
42
  blockstore,
18
43
  getCodec
19
44
  });
20
- for await (const node of walker.walk(cid, options)) {
21
- yield node.block;
45
+ const offset = this.options?.offset ?? 0;
46
+ const length = this.options?.length ?? Infinity;
47
+ const listingOnly = this.options?.listingOnly ?? false;
48
+ if (offset < 0) {
49
+ throw new InvalidParametersError('Offset cannot be negative');
50
+ }
51
+ if (length < 0) {
52
+ throw new InvalidParametersError('Length cannot be negative');
53
+ }
54
+ let exportingFile;
55
+ const abortController = new AbortController();
56
+ const signal = anySignal([
57
+ abortController.signal,
58
+ options?.signal
59
+ ]);
60
+ setMaxListeners(Infinity, abortController.signal, signal);
61
+ function includeChild(child, parent) {
62
+ if (exportingFile == null) {
63
+ exportingFile = isFile(parent);
64
+ }
65
+ // ignore offset/length if not exporting a file
66
+ if (!exportingFile) {
67
+ const link = parent.value.Links.find(l => l.Hash.equals(child));
68
+ const u = UnixFS.unmarshal(parent.value.Data ?? new Uint8Array());
69
+ if (u.type === 'directory') {
70
+ // do not include directory files
71
+ return !listingOnly;
72
+ }
73
+ if (u.type === 'hamt-sharded-directory' && listingOnly) {
74
+ // only include sub-shards, not directory files
75
+ return link?.Name?.length === 2;
76
+ }
77
+ return true;
78
+ }
79
+ const childIndex = parent.value.Links.findIndex(link => link.Hash.equals(child));
80
+ const layout = UnixFS.unmarshal(parent.value.Data ?? new Uint8Array());
81
+ const start = offset;
82
+ const end = start + length;
83
+ const childStart = Number([...layout.blockSizes].slice(0, childIndex).reduce((curr, acc) => curr + acc, 0n));
84
+ const childEnd = childStart + Number(layout.blockSizes[childIndex]);
85
+ // slice starts in child
86
+ if (start >= childStart && start < childEnd) {
87
+ return true;
88
+ }
89
+ // slice ends in child
90
+ if (end >= childStart && end < childEnd) {
91
+ return true;
92
+ }
93
+ // slice contains child
94
+ if (start <= childStart && end >= childEnd) {
95
+ return true;
96
+ }
97
+ return false;
98
+ }
99
+ try {
100
+ for await (const node of walker.walk(cid, {
101
+ ...options,
102
+ includeChild,
103
+ signal
104
+ })) {
105
+ yield node.block;
106
+ }
107
+ }
108
+ finally {
109
+ abortController.abort();
110
+ signal.clear();
22
111
  }
23
112
  }
24
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"unixfs-exporter.js","sourceRoot":"","sources":["../../../src/export-strategies/unixfs-exporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAQ7C;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,CAAE,MAAM,CAAE,GAAQ,EAAE,UAAsB,EAAE,QAAqB,EAAE,OAAsB;QAC7F,IAAI,GAAG,CAAC,IAAI,KAAK,iBAAiB,IAAI,GAAG,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACrE,MAAM,IAAI,cAAc,CAAC,iFAAiF,CAAC,CAAA;QAC7G,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC;YAC9B,UAAU;YACV,QAAQ;SACT,CAAC,CAAA;QAEF,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,CAAC,KAAK,CAAA;QAClB,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"unixfs-exporter.js","sourceRoot":"","sources":["../../../src/export-strategies/unixfs-exporter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/car",
3
- "version": "5.1.0",
3
+ "version": "5.1.1-4e5ff555",
4
4
  "description": "Import/export car files from Helia",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/ipfs/helia/tree/main/packages/car#readme",
@@ -47,13 +47,15 @@
47
47
  "test:electron-main": "aegir test -t electron-main"
48
48
  },
49
49
  "dependencies": {
50
- "@helia/interface": "^6.0.0",
51
- "@helia/utils": "^2.1.0",
50
+ "@helia/interface": "6.0.0-4e5ff555",
51
+ "@helia/utils": "2.1.1-4e5ff555",
52
52
  "@ipld/car": "^5.4.2",
53
53
  "@ipld/dag-pb": "^4.1.5",
54
54
  "@libp2p/interface": "^3.0.2",
55
55
  "@libp2p/utils": "^7.0.5",
56
+ "any-signal": "^4.1.1",
56
57
  "interface-blockstore": "^6.0.1",
58
+ "ipfs-unixfs": "^12.0.0",
57
59
  "ipfs-unixfs-exporter": "^14.0.1",
58
60
  "it-drain": "^3.0.10",
59
61
  "it-map": "^3.1.4",
@@ -63,8 +65,8 @@
63
65
  "race-signal": "^2.0.0"
64
66
  },
65
67
  "devDependencies": {
66
- "@helia/mfs": "^6.0.1",
67
- "@helia/unixfs": "^6.0.1",
68
+ "@helia/mfs": "6.0.1-4e5ff555",
69
+ "@helia/unixfs": "6.0.1-4e5ff555",
68
70
  "@ipld/dag-cbor": "^9.2.5",
69
71
  "@libp2p/logger": "^6.0.5",
70
72
  "aegir": "^47.0.22",
package/src/car.ts CHANGED
@@ -2,7 +2,7 @@ import { CarWriter } from '@ipld/car'
2
2
  import drain from 'it-drain'
3
3
  import map from 'it-map'
4
4
  import { raceSignal } from 'race-signal'
5
- import { DAG_PB_CODEC_CODE } from './constants.ts'
5
+ import { DAG_PB_CODEC_CODE, IDENTITY_CODEC_CODE } from './constants.ts'
6
6
  import { SubgraphExporter } from './export-strategies/subgraph-exporter.js'
7
7
  import { UnixFSExporter } from './index.js'
8
8
  import type { CarComponents, Car as CarInterface, ExportCarOptions } from './index.js'
@@ -29,13 +29,15 @@ export class Car implements CarInterface {
29
29
  }
30
30
 
31
31
  async * export (root: CID | CID[], options?: ExportCarOptions): AsyncGenerator<Uint8Array, void, undefined> {
32
- const { writer, out } = CarWriter.create(root)
32
+ const roots = (Array.isArray(root) ? root : [root])
33
+
34
+ const { writer, out } = CarWriter.create(roots)
33
35
  const iter = out[Symbol.asyncIterator]()
34
36
  const controller = new AbortController()
35
37
 
36
38
  // has to be done async so we write to `writer` and read from `out` at the
37
39
  // same time
38
- this._export(root, writer, options)
40
+ this._export(roots, writer, options)
39
41
  .catch((err) => {
40
42
  this.log.error('error during streaming export - %e', err)
41
43
  controller.abort(err)
@@ -62,11 +64,14 @@ export class Car implements CarInterface {
62
64
  }
63
65
  }
64
66
 
65
- private async _export (root: CID | CID[], writer: Pick<CarWriter, 'put' | 'close'>, options?: ExportCarOptions): Promise<void> {
66
- const roots = Array.isArray(root) ? root : [root]
67
+ private async _export (roots: CID[], writer: Pick<CarWriter, 'put' | 'close'>, options?: ExportCarOptions): Promise<void> {
67
68
  const traversalStrategy = options?.traversal
68
69
 
69
70
  for (const root of roots) {
71
+ if (root.multihash.code === IDENTITY_CODEC_CODE) {
72
+ continue
73
+ }
74
+
70
75
  const exportStrategy = options?.exporter ?? (root.code === DAG_PB_CODEC_CODE ? new UnixFSExporter() : new SubgraphExporter())
71
76
  let current = root
72
77
  let underRoot = false
@@ -106,6 +111,10 @@ export class Car implements CarInterface {
106
111
  continue
107
112
  }
108
113
 
114
+ if (cid.multihash.code === IDENTITY_CODEC_CODE) {
115
+ continue
116
+ }
117
+
109
118
  // skip the export target block if we have already included it during
110
119
  // traversal
111
120
  if (underRoot && cid.equals(current)) {
package/src/constants.ts CHANGED
@@ -9,3 +9,8 @@ export const DAG_PB_CODEC_CODE = 0x70
9
9
  * The multicodec code for raw binary data
10
10
  */
11
11
  export const RAW_PB_CODEC_CODE = 0x55
12
+
13
+ /**
14
+ * The multicodec code for identity hashes
15
+ */
16
+ export const IDENTITY_CODEC_CODE = 0x00
@@ -1,12 +1,68 @@
1
1
  import { depthFirstWalker } from '@helia/utils'
2
+ import { setMaxListeners, InvalidParametersError } from '@libp2p/interface'
3
+ import { anySignal } from 'any-signal'
4
+ import { UnixFS } from 'ipfs-unixfs'
2
5
  import { DAG_PB_CODEC_CODE, RAW_PB_CODEC_CODE } from '../constants.ts'
3
6
  import { NotUnixFSError } from '../errors.ts'
4
7
  import type { ExportStrategy } from '../index.js'
5
8
  import type { CodecLoader } from '@helia/interface'
9
+ import type { PBNode } from '@ipld/dag-pb'
6
10
  import type { AbortOptions } from '@libp2p/interface'
7
11
  import type { Blockstore } from 'interface-blockstore'
8
12
  import type { BlockView } from 'multiformats'
9
- import type { CID } from 'multiformats/cid'
13
+ import type { CID, Version } from 'multiformats/cid'
14
+
15
+ export interface UnixFSExporterOptions {
16
+ /**
17
+ * Include blocks that start with this offset.
18
+ *
19
+ * If the CID being exported is a directory, this option is ignored.
20
+ *
21
+ * @default 0
22
+ */
23
+ offset?: number
24
+
25
+ /**
26
+ * Only include blocks that would include this many file bytes (exclusive,
27
+ * inclusive of offset).
28
+ *
29
+ * If the CID being exported is a directory, this option is ignored.
30
+ *
31
+ * @default Infinity
32
+ */
33
+ length?: number
34
+
35
+ /**
36
+ * By default an exported CAR file will include all blocks that make up a
37
+ * directory, and the files that are stored there.
38
+ *
39
+ * To only include blocks that allow the initial enumeration of the directory,
40
+ * pass `true` here
41
+ *
42
+ * @default false
43
+ */
44
+ listingOnly?: boolean
45
+ }
46
+
47
+ function isRawBlock (block: BlockView<any, number, number, Version>): block is BlockView<Uint8Array, 0x55, number, 1> {
48
+ return block.cid.code === RAW_PB_CODEC_CODE
49
+ }
50
+
51
+ function isDagPBBlock (block: BlockView<any, number, number, Version>): block is BlockView<PBNode, 0x70, number, 1> {
52
+ return block.cid.code === DAG_PB_CODEC_CODE
53
+ }
54
+
55
+ function isFile (block: BlockView<any, number, number, 0 | 1>): boolean {
56
+ if (isRawBlock(block)) {
57
+ return true
58
+ } else if (isDagPBBlock(block) && block.value.Data != null) {
59
+ const u = UnixFS.unmarshal(block.value.Data)
60
+
61
+ return u.type === 'file' || u.type === 'raw'
62
+ } else {
63
+ throw new NotUnixFSError('Encountered non raw/dag-pb CID in UnixFS DAG')
64
+ }
65
+ }
10
66
 
11
67
  /**
12
68
  * Traverses the DAG depth-first starting at the target CID and yields all
@@ -16,6 +72,12 @@ import type { CID } from 'multiformats/cid'
16
72
  * the helia config.
17
73
  */
18
74
  export class UnixFSExporter implements ExportStrategy {
75
+ private options?: UnixFSExporterOptions
76
+
77
+ constructor (options?: UnixFSExporterOptions) {
78
+ this.options = options
79
+ }
80
+
19
81
  async * export (cid: CID, blockstore: Blockstore, getCodec: CodecLoader, options?: AbortOptions): AsyncGenerator<BlockView<unknown, number, number, 0 | 1>, void, undefined> {
20
82
  if (cid.code !== DAG_PB_CODEC_CODE && cid.code !== RAW_PB_CODEC_CODE) {
21
83
  throw new NotUnixFSError('Target CID was not UnixFS - use the SubGraphExporter to export arbitrary graphs')
@@ -26,8 +88,87 @@ export class UnixFSExporter implements ExportStrategy {
26
88
  getCodec
27
89
  })
28
90
 
29
- for await (const node of walker.walk(cid, options)) {
30
- yield node.block
91
+ const offset = this.options?.offset ?? 0
92
+ const length = this.options?.length ?? Infinity
93
+ const listingOnly = this.options?.listingOnly ?? false
94
+
95
+ if (offset < 0) {
96
+ throw new InvalidParametersError('Offset cannot be negative')
97
+ }
98
+
99
+ if (length < 0) {
100
+ throw new InvalidParametersError('Length cannot be negative')
101
+ }
102
+
103
+ let exportingFile: boolean
104
+ const abortController = new AbortController()
105
+ const signal = anySignal([
106
+ abortController.signal,
107
+ options?.signal
108
+ ])
109
+ setMaxListeners(Infinity, abortController.signal, signal)
110
+
111
+ function includeChild (child: CID, parent: BlockView<PBNode>): boolean {
112
+ if (exportingFile == null) {
113
+ exportingFile = isFile(parent)
114
+ }
115
+
116
+ // ignore offset/length if not exporting a file
117
+ if (!exportingFile) {
118
+ const link = parent.value.Links.find(l => l.Hash.equals(child))
119
+ const u = UnixFS.unmarshal(parent.value.Data ?? new Uint8Array())
120
+
121
+ if (u.type === 'directory') {
122
+ // do not include directory files
123
+ return !listingOnly
124
+ }
125
+
126
+ if (u.type === 'hamt-sharded-directory' && listingOnly) {
127
+ // only include sub-shards, not directory files
128
+ return link?.Name?.length === 2
129
+ }
130
+
131
+ return true
132
+ }
133
+
134
+ const childIndex = parent.value.Links.findIndex(link => link.Hash.equals(child))
135
+ const layout = UnixFS.unmarshal(parent.value.Data ?? new Uint8Array())
136
+
137
+ const start = offset
138
+ const end = start + length
139
+
140
+ const childStart = Number([...layout.blockSizes].slice(0, childIndex).reduce((curr, acc) => curr + acc, 0n))
141
+ const childEnd = childStart + Number(layout.blockSizes[childIndex])
142
+
143
+ // slice starts in child
144
+ if (start >= childStart && start < childEnd) {
145
+ return true
146
+ }
147
+
148
+ // slice ends in child
149
+ if (end >= childStart && end < childEnd) {
150
+ return true
151
+ }
152
+
153
+ // slice contains child
154
+ if (start <= childStart && end >= childEnd) {
155
+ return true
156
+ }
157
+
158
+ return false
159
+ }
160
+
161
+ try {
162
+ for await (const node of walker.walk(cid, {
163
+ ...options,
164
+ includeChild,
165
+ signal
166
+ })) {
167
+ yield node.block
168
+ }
169
+ } finally {
170
+ abortController.abort()
171
+ signal.clear()
31
172
  }
32
173
  }
33
174
  }
@@ -1,21 +0,0 @@
1
- {
2
- "BlockExporter": "https://ipfs.github.io/helia/classes/_helia_car.BlockExporter.html",
3
- "CIDPath": "https://ipfs.github.io/helia/classes/_helia_car.CIDPath.html",
4
- "GraphSearch": "https://ipfs.github.io/helia/classes/_helia_car.GraphSearch.html",
5
- "SubgraphExporter": "https://ipfs.github.io/helia/classes/_helia_car.SubgraphExporter.html",
6
- "UnixFSExporter": "https://ipfs.github.io/helia/classes/_helia_car.UnixFSExporter.html",
7
- "UnixFSPath": "https://ipfs.github.io/helia/classes/_helia_car.UnixFSPath.html",
8
- "Car": "https://ipfs.github.io/helia/interfaces/_helia_car.Car.html",
9
- ".:Car": "https://ipfs.github.io/helia/interfaces/_helia_car.Car.html",
10
- "CarComponents": "https://ipfs.github.io/helia/interfaces/_helia_car.CarComponents.html",
11
- ".:CarComponents": "https://ipfs.github.io/helia/interfaces/_helia_car.CarComponents.html",
12
- "ExportCarOptions": "https://ipfs.github.io/helia/interfaces/_helia_car.ExportCarOptions.html",
13
- ".:ExportCarOptions": "https://ipfs.github.io/helia/interfaces/_helia_car.ExportCarOptions.html",
14
- "ExportStrategy": "https://ipfs.github.io/helia/interfaces/_helia_car.ExportStrategy.html",
15
- ".:ExportStrategy": "https://ipfs.github.io/helia/interfaces/_helia_car.ExportStrategy.html",
16
- "GraphSearchOptions": "https://ipfs.github.io/helia/interfaces/_helia_car.GraphSearchOptions.html",
17
- "TraversalStrategy": "https://ipfs.github.io/helia/interfaces/_helia_car.TraversalStrategy.html",
18
- ".:TraversalStrategy": "https://ipfs.github.io/helia/interfaces/_helia_car.TraversalStrategy.html",
19
- "car": "https://ipfs.github.io/helia/functions/_helia_car.car.html",
20
- ".:car": "https://ipfs.github.io/helia/functions/_helia_car.car.html"
21
- }