@autonomys/auto-drive 0.5.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.
Files changed (67) hide show
  1. package/README.md +1 -0
  2. package/dist/cid/index.d.ts +9 -0
  3. package/dist/cid/index.d.ts.map +1 -0
  4. package/dist/cid/index.js +20 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/ipld/chunker.d.ts +17 -0
  9. package/dist/ipld/chunker.d.ts.map +1 -0
  10. package/dist/ipld/chunker.js +77 -0
  11. package/dist/ipld/index.d.ts +4 -0
  12. package/dist/ipld/index.d.ts.map +1 -0
  13. package/dist/ipld/index.js +3 -0
  14. package/dist/ipld/nodes.d.ts +11 -0
  15. package/dist/ipld/nodes.d.ts.map +1 -0
  16. package/dist/ipld/nodes.js +60 -0
  17. package/dist/ipld/utils.d.ts +5 -0
  18. package/dist/ipld/utils.d.ts.map +1 -0
  19. package/dist/ipld/utils.js +10 -0
  20. package/dist/metadata/index.d.ts +3 -0
  21. package/dist/metadata/index.d.ts.map +1 -0
  22. package/dist/metadata/index.js +2 -0
  23. package/dist/metadata/offchain/base.d.ts +4 -0
  24. package/dist/metadata/offchain/base.d.ts.map +1 -0
  25. package/dist/metadata/offchain/base.js +1 -0
  26. package/dist/metadata/offchain/file.d.ts +16 -0
  27. package/dist/metadata/offchain/file.d.ts.map +1 -0
  28. package/dist/metadata/offchain/file.js +18 -0
  29. package/dist/metadata/offchain/folder.d.ts +17 -0
  30. package/dist/metadata/offchain/folder.d.ts.map +1 -0
  31. package/dist/metadata/offchain/folder.js +9 -0
  32. package/dist/metadata/offchain/index.d.ts +4 -0
  33. package/dist/metadata/offchain/index.d.ts.map +1 -0
  34. package/dist/metadata/offchain/index.js +3 -0
  35. package/dist/metadata/onchain/index.d.ts +3 -0
  36. package/dist/metadata/onchain/index.d.ts.map +1 -0
  37. package/dist/metadata/onchain/index.js +2 -0
  38. package/dist/metadata/onchain/protobuf/OnchainMetadat.d.ts +26 -0
  39. package/dist/metadata/onchain/protobuf/OnchainMetadat.d.ts.map +1 -0
  40. package/dist/metadata/onchain/protobuf/OnchainMetadat.js +108 -0
  41. package/dist/metadata/onchain/protobuf/onchainMetadata.d.ts +26 -0
  42. package/dist/metadata/onchain/protobuf/onchainMetadata.d.ts.map +1 -0
  43. package/dist/metadata/onchain/protobuf/onchainMetadata.js +108 -0
  44. package/dist/metadata/onchain/utils.d.ts +4 -0
  45. package/dist/metadata/onchain/utils.d.ts.map +1 -0
  46. package/dist/metadata/onchain/utils.js +12 -0
  47. package/jest.config.ts +17 -0
  48. package/package.json +42 -0
  49. package/src/cid/index.ts +26 -0
  50. package/src/index.ts +3 -0
  51. package/src/ipld/chunker.ts +117 -0
  52. package/src/ipld/index.ts +3 -0
  53. package/src/ipld/nodes.ts +134 -0
  54. package/src/ipld/utils.ts +15 -0
  55. package/src/metadata/index.ts +2 -0
  56. package/src/metadata/offchain/base.ts +4 -0
  57. package/src/metadata/offchain/file.ts +36 -0
  58. package/src/metadata/offchain/folder.ts +28 -0
  59. package/src/metadata/offchain/index.ts +3 -0
  60. package/src/metadata/onchain/index.ts +2 -0
  61. package/src/metadata/onchain/protobuf/OnchainMetadata.proto +19 -0
  62. package/src/metadata/onchain/protobuf/OnchainMetadata.ts +133 -0
  63. package/src/metadata/onchain/utils.ts +15 -0
  64. package/tests/chunker.spec.ts +157 -0
  65. package/tests/cid.spec.ts +20 -0
  66. package/tests/nodes.spec.ts +70 -0
  67. package/tsconfig.json +14 -0
@@ -0,0 +1,108 @@
1
+ /* eslint-disable import/export */
2
+ /* eslint-disable complexity */
3
+ /* eslint-disable @typescript-eslint/no-namespace */
4
+ /* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
5
+ /* eslint-disable @typescript-eslint/no-empty-interface */
6
+ import { decodeMessage, encodeMessage, enumeration, message } from 'protons-runtime';
7
+ export var IPLDNodeData;
8
+ (function (IPLDNodeData) {
9
+ let _codec;
10
+ IPLDNodeData.codec = () => {
11
+ if (_codec == null) {
12
+ _codec = message((obj, w, opts = {}) => {
13
+ if (opts.lengthDelimited !== false) {
14
+ w.fork();
15
+ }
16
+ if (obj.type != null && __MetadataTypeValues[obj.type] !== 0) {
17
+ w.uint32(8);
18
+ MetadataType.codec().encode(obj.type, w);
19
+ }
20
+ if ((obj.linkDepth != null && obj.linkDepth !== 0)) {
21
+ w.uint32(16);
22
+ w.int32(obj.linkDepth);
23
+ }
24
+ if (obj.size != null) {
25
+ w.uint32(24);
26
+ w.int32(obj.size);
27
+ }
28
+ if (obj.name != null) {
29
+ w.uint32(34);
30
+ w.string(obj.name);
31
+ }
32
+ if (obj.data != null) {
33
+ w.uint32(42);
34
+ w.bytes(obj.data);
35
+ }
36
+ if (opts.lengthDelimited !== false) {
37
+ w.ldelim();
38
+ }
39
+ }, (reader, length, opts = {}) => {
40
+ const obj = {
41
+ type: MetadataType.File,
42
+ linkDepth: 0
43
+ };
44
+ const end = length == null ? reader.len : reader.pos + length;
45
+ while (reader.pos < end) {
46
+ const tag = reader.uint32();
47
+ switch (tag >>> 3) {
48
+ case 1: {
49
+ obj.type = MetadataType.codec().decode(reader);
50
+ break;
51
+ }
52
+ case 2: {
53
+ obj.linkDepth = reader.int32();
54
+ break;
55
+ }
56
+ case 3: {
57
+ obj.size = reader.int32();
58
+ break;
59
+ }
60
+ case 4: {
61
+ obj.name = reader.string();
62
+ break;
63
+ }
64
+ case 5: {
65
+ obj.data = reader.bytes();
66
+ break;
67
+ }
68
+ default: {
69
+ reader.skipType(tag & 7);
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ return obj;
75
+ });
76
+ }
77
+ return _codec;
78
+ };
79
+ IPLDNodeData.encode = (obj) => {
80
+ return encodeMessage(obj, IPLDNodeData.codec());
81
+ };
82
+ IPLDNodeData.decode = (buf, opts) => {
83
+ return decodeMessage(buf, IPLDNodeData.codec(), opts);
84
+ };
85
+ })(IPLDNodeData || (IPLDNodeData = {}));
86
+ export var MetadataType;
87
+ (function (MetadataType) {
88
+ MetadataType["File"] = "File";
89
+ MetadataType["FileInlink"] = "FileInlink";
90
+ MetadataType["FileChunk"] = "FileChunk";
91
+ MetadataType["Folder"] = "Folder";
92
+ MetadataType["FolderInlink"] = "FolderInlink";
93
+ MetadataType["Metadata"] = "Metadata";
94
+ })(MetadataType || (MetadataType = {}));
95
+ var __MetadataTypeValues;
96
+ (function (__MetadataTypeValues) {
97
+ __MetadataTypeValues[__MetadataTypeValues["File"] = 0] = "File";
98
+ __MetadataTypeValues[__MetadataTypeValues["FileInlink"] = 1] = "FileInlink";
99
+ __MetadataTypeValues[__MetadataTypeValues["FileChunk"] = 2] = "FileChunk";
100
+ __MetadataTypeValues[__MetadataTypeValues["Folder"] = 3] = "Folder";
101
+ __MetadataTypeValues[__MetadataTypeValues["FolderInlink"] = 4] = "FolderInlink";
102
+ __MetadataTypeValues[__MetadataTypeValues["Metadata"] = 5] = "Metadata";
103
+ })(__MetadataTypeValues || (__MetadataTypeValues = {}));
104
+ (function (MetadataType) {
105
+ MetadataType.codec = () => {
106
+ return enumeration(__MetadataTypeValues);
107
+ };
108
+ })(MetadataType || (MetadataType = {}));
@@ -0,0 +1,4 @@
1
+ import { IPLDNodeData } from '../onchain/index.js';
2
+ export declare const encodeIPLDNodeData: (metadata: IPLDNodeData) => Uint8Array;
3
+ export declare const decodeIPLDNodeData: (data: Uint8Array) => IPLDNodeData;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metadata/onchain/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,eAAO,MAAM,kBAAkB,aAAc,YAAY,KAAG,UAE3D,CAAA;AAED,eAAO,MAAM,kBAAkB,SAAU,UAAU,KAAG,YAOrD,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { decode } from '@ipld/dag-pb';
2
+ import { IPLDNodeData } from '../onchain/index.js';
3
+ export const encodeIPLDNodeData = (metadata) => {
4
+ return IPLDNodeData.encode(metadata);
5
+ };
6
+ export const decodeIPLDNodeData = (data) => {
7
+ const decoded = decode(data);
8
+ if (!decoded.Data) {
9
+ throw new Error('Invalid data');
10
+ }
11
+ return IPLDNodeData.decode(decoded.Data);
12
+ };
package/jest.config.ts ADDED
@@ -0,0 +1,17 @@
1
+ const { createDefaultEsmPreset } = require('ts-jest')
2
+
3
+ module.exports = {
4
+ ...createDefaultEsmPreset(),
5
+ extensionsToTreatAsEsm: ['.ts'],
6
+ moduleNameMapper: {
7
+ '^(\\.{1,2}/.*)\\.js$': '$1',
8
+ },
9
+ transform: {
10
+ '^.+\\.tsx?$': [
11
+ 'ts-jest',
12
+ {
13
+ useESM: true,
14
+ },
15
+ ],
16
+ },
17
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@autonomys/auto-drive",
3
+ "packageManager": "yarn@4.1.1",
4
+ "version": "0.5.0",
5
+ "main": "dist/index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/autonomys/auto-sdk"
9
+ },
10
+ "author": {
11
+ "name": "Autonomys",
12
+ "url": "https://www.autonomys.net"
13
+ },
14
+ "type": "module",
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "pb": "yarn protons src/metadata/onchain/protobuf/OnchainMetadata.proto -o src/metadata/onchain/protobuf",
18
+ "clean": "rm -rf dist",
19
+ "format": "prettier --write \"src/**/*.ts\"",
20
+ "test": "yarn node --experimental-vm-modules $(yarn bin jest)"
21
+ },
22
+ "exports": {
23
+ ".": "./dist/index.js",
24
+ "./protobuf": "./dist/metadata/onchain/protobuf/onchainMetadata.js"
25
+ },
26
+ "devDependencies": {
27
+ "@types/jest": "^29.5.13",
28
+ "jest": "^29.7.0",
29
+ "protobufjs": "^7.4.0",
30
+ "ts-jest": "^29.2.5",
31
+ "typescript": "^5.6.2"
32
+ },
33
+ "dependencies": {
34
+ "@ipld/dag-pb": "^4.1.2",
35
+ "blake3": "1.1.0",
36
+ "multiformats": "^13.2.2",
37
+ "protobufjs": "^7.4.0",
38
+ "protons": "^7.6.0",
39
+ "protons-runtime": "^5.5.0"
40
+ },
41
+ "gitHead": "b7b40dfa6b9cb8bf189fd9d5d3a0ad190b21197a"
42
+ }
@@ -0,0 +1,26 @@
1
+ import { encode, PBNode } from '@ipld/dag-pb'
2
+ import { hash } from 'blake3'
3
+ import { CID } from 'multiformats/cid'
4
+ import * as base32 from 'multiformats/bases/base32'
5
+ import * as raw from 'multiformats/codecs/raw'
6
+ import { create } from 'multiformats/hashes/digest'
7
+
8
+ export const BLAKE3_CODE = 0x1f
9
+
10
+ export const cidOfNode = (node: PBNode) => {
11
+ return cidFromBlakeHash(hash(encode(node)))
12
+ }
13
+
14
+ export const cidToString = (cid: CID) => {
15
+ return cid.toString(base32.base32)
16
+ }
17
+
18
+ export const stringToCid = (str: string) => {
19
+ return CID.parse(str, base32.base32)
20
+ }
21
+
22
+ export const cidFromBlakeHash = (hash: Buffer) => {
23
+ return CID.create(1, raw.code, create(BLAKE3_CODE, hash))
24
+ }
25
+
26
+ export const blake3HashFromCid = (cid: CID) => cid.multihash.digest
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './cid/index.js'
2
+ export * from './ipld/index.js'
3
+ export * from './metadata/index.js'
@@ -0,0 +1,117 @@
1
+ import { PBNode } from '@ipld/dag-pb'
2
+ import { CID } from 'multiformats'
3
+ import { cidOfNode } from '../cid/index.js'
4
+ import {
5
+ createChunkedFileIpldNode,
6
+ createChunkIpldNode,
7
+ createFileInlinkIpldNode,
8
+ createFolderInlinkIpldNode,
9
+ createFolderIpldNode,
10
+ createSingleFileIpldNode,
11
+ } from './nodes.js'
12
+ import { chunkBuffer, encodeNode } from './utils.js'
13
+
14
+ export const DEFAULT_MAX_CHUNK_SIZE = 1024 * 64
15
+ export const DEFAULT_MAX_LINK_PER_NODE = DEFAULT_MAX_CHUNK_SIZE / 64
16
+
17
+ export interface IPLDDag {
18
+ headCID: CID
19
+ nodes: Map<CID, PBNode>
20
+ }
21
+
22
+ export const createFileIPLDDag = (
23
+ file: Buffer,
24
+ filename?: string,
25
+ { chunkSize, maxLinkPerNode }: { chunkSize: number; maxLinkPerNode: number } = {
26
+ chunkSize: DEFAULT_MAX_CHUNK_SIZE,
27
+ maxLinkPerNode: DEFAULT_MAX_LINK_PER_NODE,
28
+ },
29
+ ): IPLDDag => {
30
+ if (file.length <= chunkSize) {
31
+ const head = createSingleFileIpldNode(file, filename)
32
+ const headCID = cidOfNode(head)
33
+ return {
34
+ headCID,
35
+ nodes: new Map([[headCID, head]]),
36
+ }
37
+ }
38
+
39
+ const bufferChunks = chunkBuffer(file, chunkSize)
40
+
41
+ const nodes = new Map<CID, PBNode>()
42
+
43
+ let CIDs: CID[] = bufferChunks.map((chunk) => {
44
+ const node = createChunkIpldNode(chunk)
45
+ const cid = cidOfNode(node)
46
+ nodes.set(cid, node)
47
+
48
+ return cid
49
+ })
50
+
51
+ let depth = 1
52
+ while (CIDs.length > maxLinkPerNode) {
53
+ const newCIDs: CID[] = []
54
+ for (let i = 0; i < CIDs.length; i += maxLinkPerNode) {
55
+ const chunk = CIDs.slice(i, i + maxLinkPerNode)
56
+
57
+ const node = createFileInlinkIpldNode(chunk, chunk.length, depth, chunkSize)
58
+ const cid = cidOfNode(node)
59
+ nodes.set(cid, node)
60
+ newCIDs.push(cid)
61
+ }
62
+ depth++
63
+ CIDs = newCIDs
64
+ }
65
+ const head = createChunkedFileIpldNode(CIDs, file.length, depth, filename, chunkSize)
66
+ const headCID = cidOfNode(head)
67
+ nodes.set(headCID, head)
68
+
69
+ return {
70
+ headCID,
71
+ nodes,
72
+ }
73
+ }
74
+
75
+ export const createFolderIPLDDag = (
76
+ children: CID[],
77
+ name: string,
78
+ size: number,
79
+ { maxLinkPerNode }: { maxLinkPerNode: number } = { maxLinkPerNode: DEFAULT_MAX_LINK_PER_NODE },
80
+ ): IPLDDag => {
81
+ const nodes = new Map<CID, PBNode>()
82
+ let cids = children
83
+ let depth = 0
84
+ while (cids.length > maxLinkPerNode) {
85
+ const newCIDs: CID[] = []
86
+ for (let i = 0; i < cids.length; i += maxLinkPerNode) {
87
+ const chunk = cids.slice(i, i + maxLinkPerNode)
88
+ const node = createFolderInlinkIpldNode(chunk, depth)
89
+ const cid = cidOfNode(node)
90
+ nodes.set(cid, node)
91
+ newCIDs.push(cid)
92
+ }
93
+ cids = newCIDs
94
+ depth++
95
+ }
96
+
97
+ const node = createFolderIpldNode(cids, name, depth, size)
98
+ const cid = cidOfNode(node)
99
+ nodes.set(cid, node)
100
+
101
+ return {
102
+ headCID: cid,
103
+ nodes,
104
+ }
105
+ }
106
+
107
+ export const ensureNodeMaxSize = (
108
+ node: PBNode,
109
+ maxSize: number = DEFAULT_MAX_CHUNK_SIZE,
110
+ ): PBNode => {
111
+ const nodeSize = encodeNode(node).byteLength
112
+ if (nodeSize > maxSize) {
113
+ throw new Error(`Node is too large to fit in a single chunk: ${nodeSize} > ${maxSize}`)
114
+ }
115
+
116
+ return node
117
+ }
@@ -0,0 +1,3 @@
1
+ export * from './chunker.js'
2
+ export * from './nodes.js'
3
+ export { encodeNode } from './utils.js'
@@ -0,0 +1,134 @@
1
+ import { createNode, PBNode } from '@ipld/dag-pb'
2
+ import { CID } from 'multiformats/cid'
3
+ import { OffchainMetadata } from '../metadata/index.js'
4
+ import { encodeIPLDNodeData, MetadataType } from '../metadata/onchain/index.js'
5
+ import { DEFAULT_MAX_CHUNK_SIZE, ensureNodeMaxSize } from './chunker.js'
6
+
7
+ /// Creates a chunk ipld node
8
+ export const createChunkIpldNode = (data: Buffer): PBNode =>
9
+ createNode(
10
+ encodeIPLDNodeData({
11
+ type: MetadataType.FileChunk,
12
+ size: data.length,
13
+ linkDepth: 0,
14
+ data,
15
+ }),
16
+ [],
17
+ )
18
+
19
+ // Creates a file ipld node
20
+ // links: the CIDs of the file's contents
21
+ // @todo: add the file's metadata
22
+ export const createChunkedFileIpldNode = (
23
+ links: CID[],
24
+ size: number,
25
+ linkDepth: number,
26
+ name?: string,
27
+ maxNodeSize: number = DEFAULT_MAX_CHUNK_SIZE,
28
+ ): PBNode =>
29
+ ensureNodeMaxSize(
30
+ createNode(
31
+ encodeIPLDNodeData({
32
+ type: MetadataType.File,
33
+ name,
34
+ size,
35
+ linkDepth,
36
+ }),
37
+ links.map((cid) => ({ Hash: cid })),
38
+ ),
39
+ maxNodeSize,
40
+ )
41
+ // Creates a file ipld node
42
+ // links: the CIDs of the file's contents
43
+ // @todo: add the file's metadata
44
+ export const createFileInlinkIpldNode = (
45
+ links: CID[],
46
+ size: number,
47
+ linkDepth: number,
48
+ maxNodeSize: number = DEFAULT_MAX_CHUNK_SIZE,
49
+ ): PBNode =>
50
+ ensureNodeMaxSize(
51
+ createNode(
52
+ encodeIPLDNodeData({
53
+ type: MetadataType.FileInlink,
54
+ size,
55
+ linkDepth,
56
+ }),
57
+ links.map((cid) => ({ Hash: cid })),
58
+ ),
59
+ maxNodeSize,
60
+ )
61
+
62
+ // Creates a file ipld node
63
+ // links: the CIDs of the file's contents
64
+ // @todo: add the file's metadata
65
+ export const createSingleFileIpldNode = (data: Buffer, name?: string): PBNode =>
66
+ createNode(
67
+ encodeIPLDNodeData({
68
+ type: MetadataType.File,
69
+ name,
70
+ size: data.length,
71
+ linkDepth: 0,
72
+ data,
73
+ }),
74
+ [],
75
+ )
76
+
77
+ // Creates a folder ipld node
78
+ // links: the CIDs of the folder's contents
79
+ // @todo: add the folder's metadata
80
+ export const createFolderIpldNode = (
81
+ links: CID[],
82
+ name: string,
83
+ linkDepth: number,
84
+ size: number,
85
+ maxNodeSize: number = DEFAULT_MAX_CHUNK_SIZE,
86
+ ): PBNode =>
87
+ ensureNodeMaxSize(
88
+ createNode(
89
+ encodeIPLDNodeData({
90
+ type: MetadataType.Folder,
91
+ name,
92
+ size,
93
+ linkDepth,
94
+ }),
95
+ links.map((cid) => ({ Hash: cid })),
96
+ ),
97
+ maxNodeSize,
98
+ )
99
+
100
+ export const createFolderInlinkIpldNode = (
101
+ links: CID[],
102
+ linkDepth: number,
103
+ maxNodeSize: number = DEFAULT_MAX_CHUNK_SIZE,
104
+ ): PBNode =>
105
+ ensureNodeMaxSize(
106
+ createNode(
107
+ encodeIPLDNodeData({
108
+ type: MetadataType.FolderInlink,
109
+ linkDepth,
110
+ }),
111
+ links.map((cid) => ({ Hash: cid })),
112
+ ),
113
+ maxNodeSize,
114
+ )
115
+
116
+ /// Creates a metadata ipld node
117
+ export const createMetadataNode = (
118
+ metadata: OffchainMetadata,
119
+ maxNodeSize: number = DEFAULT_MAX_CHUNK_SIZE,
120
+ ): PBNode => {
121
+ const data = Buffer.from(JSON.stringify(metadata))
122
+
123
+ return ensureNodeMaxSize(
124
+ createNode(
125
+ encodeIPLDNodeData({
126
+ type: MetadataType.Metadata,
127
+ name: metadata.name,
128
+ linkDepth: 0,
129
+ data,
130
+ }),
131
+ ),
132
+ maxNodeSize,
133
+ )
134
+ }
@@ -0,0 +1,15 @@
1
+ import { decode, encode, PBNode } from '@ipld/dag-pb'
2
+
3
+ export const chunkBuffer = (buffer: Buffer, chunkSize: number) => {
4
+ const chunks: Buffer[] = []
5
+
6
+ for (let i = 0; i < buffer.length; i += chunkSize) {
7
+ chunks.push(Buffer.from(buffer.buffer.slice(i, i + chunkSize)))
8
+ }
9
+
10
+ return chunks
11
+ }
12
+
13
+ export const encodeNode = (node: PBNode): Buffer => Buffer.from(encode(node))
14
+
15
+ export const decodeNode = (data: Uint8Array): PBNode => decode(data)
@@ -0,0 +1,2 @@
1
+ export * from './offchain/index.js'
2
+ export * from './onchain/index.js'
@@ -0,0 +1,4 @@
1
+ import { OffchainFileMetadata } from './file.js'
2
+ import { OffchainFolderMetadata } from './folder.js'
3
+
4
+ export type OffchainMetadata = OffchainFolderMetadata | OffchainFileMetadata
@@ -0,0 +1,36 @@
1
+ import { cidOfNode, cidToString, IPLDDag } from '../../index.js'
2
+
3
+ export type OffchainFileMetadata = {
4
+ type: 'file'
5
+ dataCid: string
6
+ name?: string
7
+ mimeType?: string
8
+ totalSize: number
9
+ totalChunks: number
10
+ chunks: ChunkInfo[]
11
+ }
12
+
13
+ export interface ChunkInfo {
14
+ size: number
15
+ cid: string
16
+ }
17
+
18
+ export const fileMetadata = (
19
+ dag: IPLDDag,
20
+ totalSize: number,
21
+ name?: string,
22
+ mimeType?: string,
23
+ ): OffchainFileMetadata => {
24
+ return {
25
+ type: 'file',
26
+ dataCid: cidToString(dag.headCID),
27
+ name,
28
+ mimeType,
29
+ totalSize,
30
+ totalChunks: dag.nodes.size,
31
+ chunks: Array.from(dag.nodes.values()).map((chunk) => ({
32
+ cid: cidToString(cidOfNode(chunk)),
33
+ size: chunk.Data?.length ?? 0,
34
+ })),
35
+ }
36
+ }
@@ -0,0 +1,28 @@
1
+ interface ChildrenMetadata {
2
+ type: 'folder' | 'file'
3
+ name?: string
4
+ cid: string
5
+ totalSize: number
6
+ }
7
+
8
+ export type OffchainFolderMetadata = {
9
+ type: 'folder'
10
+ dataCid: string
11
+ name?: string
12
+ totalSize: number
13
+ totalFiles: number
14
+ children: ChildrenMetadata[]
15
+ }
16
+
17
+ export const folderMetadata = (
18
+ cid: string,
19
+ children: ChildrenMetadata[],
20
+ ): OffchainFolderMetadata => {
21
+ return {
22
+ dataCid: cid,
23
+ totalSize: children.reduce((acc, child) => acc + child.totalSize, 0),
24
+ totalFiles: children.length,
25
+ children,
26
+ type: 'folder',
27
+ }
28
+ }
@@ -0,0 +1,3 @@
1
+ export * from './base.js'
2
+ export * from './file.js'
3
+ export * from './folder.js'
@@ -0,0 +1,2 @@
1
+ export * from './protobuf/OnchainMetadata.js'
2
+ export * from './utils.js'
@@ -0,0 +1,19 @@
1
+ syntax = "proto3";
2
+
3
+ message IPLDNodeData {
4
+ MetadataType type = 1;
5
+ int32 linkDepth = 2;
6
+ optional int32 size = 3;
7
+ optional string name = 4;
8
+ optional bytes data = 5;
9
+ }
10
+
11
+ // MetadataType defines the possible types of metadata.
12
+ enum MetadataType {
13
+ File = 0;
14
+ FileInlink = 1;
15
+ FileChunk = 2;
16
+ Folder = 3;
17
+ FolderInlink = 4;
18
+ Metadata = 5;
19
+ }