diff --git a/packages/nest/README.md b/packages/nest/README.md index b957586..5caeb4c 100644 --- a/packages/nest/README.md +++ b/packages/nest/README.md @@ -38,25 +38,18 @@ const blockstore = new IDBBlockstore('path/to/store') await blockstore.open() const fs = await FileSystem.create({ - blockstore + blockstore, }) // Create the private node of which we'll keep the encryption key around. const { capsuleKey } = await fs.mountPrivateNode({ - path: Path.root() // ie. root private directory + path: Path.root(), // ie. root private directory }) // Write & Read -await fs.write( - Path.file('private', 'file'), - 'utf8', - '🪺' -) - -const contents = await fs.read( - Path.file('private', 'file'), - 'utf8' -) +await fs.write(Path.file('private', 'file'), 'utf8', '🪺') + +const contents = await fs.read(Path.file('private', 'file'), 'utf8') ``` Scenario 2:
@@ -73,11 +66,7 @@ of our root tree, the pointer to our file system. let fsPointer: CID = await fs.calculateDataRoot() // When we make a modification to the file system a verification is performed. -await fs.write( - Path.file('private', 'file'), - 'utf8', - '🪺' -) +await fs.write(Path.file('private', 'file'), 'utf8', '🪺') // If the commit is approved, the changes are reflected in the file system and // the `commit` and `publish` events are emitted. @@ -103,7 +92,7 @@ const fs = await FileSystem.fromCID(fsPointer, { blockstore }) // `capsuleKey` from scenario 1 await fs.mountPrivateNode({ path: Path.root(), - capsuleKey + capsuleKey, }) ``` @@ -115,6 +104,7 @@ await fs.mountPrivateNode({ fs.exists fs.listDirectory // alias: fs.ls fs.read +fs.size ``` ### Mutations @@ -153,12 +143,16 @@ import { Modification } from '@wnfs-wg/nest' const fs = FileSystem.create({ blockstore, - onCommit: (modifications: Modification[]): { commit: boolean } => { + onCommit: async ( + modifications: Modification[] + ): Promise<{ commit: boolean }> => { // For example, check if I have access to all paths. - const satisfied = modifications.every(m => ALLOWED_PATHS.includes( Path.toPosix(m.path) )) + const satisfied = modifications.every((m) => + ALLOWED_PATHS.includes(Path.toPosix(m.path)) + ) if (satisfied) return { commit: true } else return { commit: false } - } + }, }) ``` diff --git a/packages/nest/src/class.ts b/packages/nest/src/class.ts index dba3cf9..dc75d3a 100644 --- a/packages/nest/src/class.ts +++ b/packages/nest/src/class.ts @@ -426,6 +426,11 @@ export class FileSystem { ) } + /** @group Querying */ + async size(path: Path.File>): Promise { + return await this.#transactionContext().size(path) + } + // MUTATIONS // --------- diff --git a/packages/nest/src/queries.ts b/packages/nest/src/queries.ts index 2d4607c..4d1b069 100644 --- a/packages/nest/src/queries.ts +++ b/packages/nest/src/queries.ts @@ -136,6 +136,24 @@ export const publicReadFromCID = ( } } +export const publicSize = () => { + return async (params: PublicParams): Promise => { + const wnfsBlockStore = Store.wnfs(params.blockstore) + + const node: PublicNode | null | undefined = await params.rootTree + .publicRoot() + .getNode(params.pathSegments, wnfsBlockStore) + + if (node === null || node === undefined) { + throw new Error('Failed to find public node') + } else if (node.isDir()) { + throw new Error('Expected node to be a file') + } + + return await node.asFile().getSize(wnfsBlockStore) + } +} + // PRIVATE export type PrivateParams = { @@ -321,3 +339,38 @@ export const privateReadFromAccessKey = ( } } } + +export const privateSize = () => { + return async (params: PrivateParams): Promise => { + let node + + if (params.node.isDir()) { + if (params.remainder.length === 0) { + throw new Error('Expected node to be a file') + } + + const tmpNode: PrivateNode | null | undefined = await params.node + .asDir() + .getNode( + params.remainder, + searchLatest(), + params.rootTree.privateForest(), + Store.wnfs(params.blockstore) + ) + + if (tmpNode === null || tmpNode === undefined) { + throw new Error('Failed to find private node') + } else if (tmpNode.isDir()) { + throw new Error('Expected node to be a file') + } + + node = tmpNode + } else { + node = params.node + } + + return await node + .asFile() + .getSize(params.rootTree.privateForest(), Store.wnfs(params.blockstore)) + } +} diff --git a/packages/nest/src/transaction.ts b/packages/nest/src/transaction.ts index acc1b35..7da8466 100644 --- a/packages/nest/src/transaction.ts +++ b/packages/nest/src/transaction.ts @@ -307,6 +307,14 @@ export class TransactionContext { return dataFromBytes(dataType, bytes) } + /** @group Querying */ + async size(path: Path.File>): Promise { + return await this.#query(path, { + public: Queries.publicSize(), + private: Queries.privateSize(), + }) + } + // MUTATIONS /** @group Mutating */ diff --git a/packages/nest/test/class.test.ts b/packages/nest/test/class.test.ts index 449fa12..512d149 100644 --- a/packages/nest/test/class.test.ts +++ b/packages/nest/test/class.test.ts @@ -557,6 +557,27 @@ describe('File System Class', () => { ) }) + // SIZE + // ---- + + it('returns the size of public files', async () => { + const path = Path.file('public', 'file') + + await fs.write(path, 'bytes', new Uint8Array([1, 2, 3])) + const size = await fs.size(path) + + assert.equal(size, 3) + }) + + it('returns the size of private files', async () => { + const path = Path.file('private', 'file') + + await fs.write(path, 'bytes', new Uint8Array([1, 2, 3, 4])) + const size = await fs.size(path) + + assert.equal(size, 4) + }) + // REMOVE // ------