{"id":15596625,"url":"https://github.com/ceramicnetwork/cartonne","last_synced_at":"2025-04-28T10:47:37.503Z","repository":{"id":80690702,"uuid":"545935055","full_name":"ceramicnetwork/cartonne","owner":"ceramicnetwork","description":"Reading and writing Content Addressable aRchive","archived":false,"fork":false,"pushed_at":"2024-01-10T13:37:00.000Z","size":695,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-20T22:59:20.231Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ceramicnetwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-05T08:25:32.000Z","updated_at":"2024-10-25T12:47:50.000Z","dependencies_parsed_at":"2024-01-03T12:30:21.181Z","dependency_job_id":"c33ac54b-9e65-4288-9a91-765fac63ee20","html_url":"https://github.com/ceramicnetwork/cartonne","commit_stats":{"total_commits":9,"total_committers":1,"mean_commits":9.0,"dds":0.0,"last_synced_commit":"84873faf524ac46e8e5d99f1ad8f7fa1e27eeedf"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceramicnetwork%2Fcartonne","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceramicnetwork%2Fcartonne/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceramicnetwork%2Fcartonne/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ceramicnetwork%2Fcartonne/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ceramicnetwork","download_url":"https://codeload.github.com/ceramicnetwork/cartonne/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251298330,"owners_count":21566998,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T01:05:52.755Z","updated_at":"2025-04-28T10:47:37.480Z","avatar_url":"https://github.com/ceramicnetwork.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cartonne\n\nIn-memory Content Addressable aRchive (CAR) file manipulation.\n\nSee also:\n\n- [CAR Specification](https://ipld.io/specs/transport/car/)\n- [Go implementation](https://github.com/ipld/go-car)\n- [@ipld/car](https://github.com/ipld/js-car) JS packages\n\n## Example\n\n```ts\nimport { CARFactory } from \"cartonne\";\n\nconst carFactory = new CARFactory(); // Here you can add codecs and hashers\n\nconst car = carFactory.build();\n// By default encode block as DAG-CBOR, use SHA256 for hashing\n// Similar to what you `ipfs.dag.put`\nconst cid0 = car.put({ hello: \"world\" });\n// Add a block and use it as one of the CAR \"roots\"\nconst cid1 = car.put({ foo: new Uint8Array([1, 2, 3]) }, { isRoot: true });\n// Return decoded payload\nconst payload0 = car.get(cid0); //= `{ hello: \"world\" }`\nconst payload1 = car.get(cid1); //= `{ foo: new Uint8Array([1, 2, 3]) }`\n\n// And then serialize to bytes...\ncar.bytes;\n// To string as multibase...\ncar.toString();\n// Or to Iterable\u003cUint8Array\u003e or AsyncIterable\u003cUint8Array\u003e\nimport * as fs from \"node:fs\";\nimport { pipeline } from \"node:stream/promises\";\nawait pipeline(car, fs.createWriteStream(\"./blah.car\"));\n```\n\n## Installation\n\n```shell\npnpm add cartonne\n```\n\n## Usage\n\n`cartonne` is designed to operate on relatively small CAR files.\nContent of a CAR file is fully loaded in memory.\n\n`CARFactory` serves as an entry point. You create an empty CAR file via `CARFactory#build`,\nor create it from bytes using `CARFactory#fromBytes`, `CARFactory#fromIterable`, or `CARFactory#fromAsyncIterable`.\nAll return an instance of `CAR`, which represents a CAR file.\n\n`cartonne` makes it easy to manipulate CAR files by providing access to IPLD data model. You could add IPLD data via\n`CAR#put`, and read it via `CAR#get`. By default, we include [dag-cbor](https://ipld.io/specs/codecs/dag-cbor/spec/) codec and [sha256 hasher](https://github.com/multiformats/js-multiformats#multihash-hashers).\nYou could use additional codecs and hashers by adding it to `CARFactory`, and referencing them by name, code, or directly\nwhen putting data:\n\n```ts\nimport { CARFactory } from \"cartonne\";\nimport * as dagJson from \"@ipld/dag-json\";\nimport { sha512 } from \"multihashes-sync/sha2\";\n\nconst carFactory0 = new CARFactory();\ncarFactory0.codecs.add(dagJson);\ncarFactory0.hashers.add(sha512);\n\nconst car0 = carFactory0.build();\nconst cid0 = car0.put({ hello: \"world\" }, { codec: \"dag-json\", hasher: \"sha2-512\" });\n\nconst carFactory1 = new CARFactory(); // Note: we do not add a codec and a hasher to CARFactory, we use them directly here\nconst car1 = carFactory1.build();\nconst cid1 = car1.put({ hello: \"world\" }, { codec: dagJson, hasher: sha512 });\n// Same CID as a result: \"baguqee2a7d5wrebdi6rmqkgtrqyodq3bo6gitrqtemxtliymakwswbazbu7ai763747ljp7ycqfv7aqx4xlgiugcx62quo2te45pcgjbg4qjsvq\"\nconsole.log(cid1.equals(cid0));\n```\n\nYou could put an IPLD block directly:\n\n```ts\nimport { CarBlock } from 'cartonne'\nconst car = ...\ncar.blocks.put(new CarBlock(cid, bytes))\n```\n\nWhen you are done manipulating with CAR file, you might want to serialize it. You can encode it as a byte blob via `car.bytes`,\nas a [multibase](https://github.com/multiformats/multibase)-encoded string via `car.toString(encoding)` (`base64url` by default). Or, you could stream `CAR`:\n\n```ts\n// Byte blob:\ncar.bytes; // returns `Uint8Array`\ncar.toString(); // returns base64url multibase string\ncar.toString(\"base58btc\"); // returns base58btc multibase string\nReadable.from(car); // turns CAR into ReadableStream\n// Synchronous chunks\nfor (const chunk of car) {\n  // Do something with `Uint8Array` chunk\n}\n// Asynchronous chunks\nfor await (const chunk of car) {\n  // Do something with `Uint8Array` chunk\n}\n```\n\n## CARv1 and CARv2\n\nBoth CARv1 and CARv2 are supported for reading and writing. Eventually we will add support for CARv2 indexes and characteristics.\nFor now, written CARv2 just wraps CARv1 payload.\n\nYou can convert CAR files to v1 or v2 using corresponding methods:\n\n```ts\nconst car: CAR = ...\nconst carV1 = car.asV1()\nconst carV2 = carV1.asV2()\n```\n\n## Roadmap\n\n- Faster encoding/decoding\n- Support CAR manipulation on file system\n- Read and write CARv2 indexes\n\n## License\n\nLicensed under either of:\n\n- [Apache 2.0](https://opensource.org/licenses/Apache-2.0),\n- [MIT](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fceramicnetwork%2Fcartonne","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fceramicnetwork%2Fcartonne","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fceramicnetwork%2Fcartonne/lists"}