Skip to content

Commit 08b2c9e

Browse files
Merge pull request #245 from ardriveapp/PE-7146-skip-files-missing-data-content-type-while-listing-folders-and-drives
PE-7146: skip files missing data content type while listing folders and drives
2 parents a5b2ae7 + 053c657 commit 08b2c9e

File tree

7 files changed

+390
-51
lines changed

7 files changed

+390
-51
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ardrive-core-js",
3-
"version": "2.0.6",
3+
"version": "2.0.7",
44
"description": "ArDrive Core contains the essential back end application features to support the ArDrive CLI and Desktop apps, such as file management, Permaweb upload/download, wallet management and other common functions.",
55
"main": "./lib/exports.js",
66
"types": "./lib/exports.d.ts",

src/arfs/arfs_builders/arfs_file_builders.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { expect } from 'chai';
22
import { stub } from 'sinon';
3-
import { fakeArweave, stubTxID } from '../../../tests/stubs';
3+
import { fakeArweave, stubTxID, stubTxIDAlt } from '../../../tests/stubs';
44
import { expectAsyncErrorThrow } from '../../../tests/test_helpers';
5-
import { EntityKey, GQLNodeInterface } from '../../types';
5+
import { EID, EntityKey, GQLNodeInterface } from '../../types';
66
import { gatewayUrlForArweave } from '../../utils/common';
77
import { GatewayAPI } from '../../utils/gateway_api';
88
import { ArFSPrivateFileBuilder, ArFSPublicFileBuilder } from './arfs_file_builders';
9+
import { ArFSDAOAnonymous } from '../arfsdao_anonymous';
10+
import { ADDR, DriveID, FolderID } from '../../types';
11+
import { stub, SinonStub } from 'sinon';
912

1013
const gatewayApi = new GatewayAPI({
1114
gatewayUrl: gatewayUrlForArweave(fakeArweave),

src/arfs/arfs_builders/arfs_file_builders.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Utf8ArrayToStr, extToMime } from '../../utils/common';
1818
import { ArFSPublicFile, ArFSPrivateFile } from '../arfs_entities';
1919
import { ArFSFileOrFolderBuilder } from './arfs_builders';
2020
import { GatewayAPI } from '../../utils/gateway_api';
21-
21+
import { FileBuilderValidation, InvalidFileStateException } from '../../types/exceptions';
2222
export interface FileMetaDataTransactionData extends EntityMetaDataTransactionData {
2323
// FIXME: do we need our safe types here? This interface refers to a JSON with primitive types
2424
name: string;
@@ -86,16 +86,10 @@ export class ArFSPublicFileBuilder extends ArFSFileBuilder<ArFSPublicFile> {
8686
this.dataTxId = new TransactionID(dataJSON.dataTxId);
8787
this.dataContentType = dataJSON.dataContentType ?? extToMime(this.name);
8888

89-
if (
90-
!this.name ||
91-
this.size === undefined ||
92-
!this.lastModifiedDate ||
93-
!this.dataTxId ||
94-
!this.dataContentType ||
95-
!(this.entityType === 'file')
96-
) {
97-
throw new Error('Invalid file state');
98-
}
89+
const fileBuilderValidation = new FileBuilderValidation();
90+
fileBuilderValidation.validateFileProperties(this);
91+
fileBuilderValidation.throwIfMissingProperties();
92+
9993
this.parseCustomMetaDataFromDataJson(dataJSON);
10094

10195
return Promise.resolve(
@@ -188,6 +182,10 @@ export class ArFSPrivateFileBuilder extends ArFSFileBuilder<ArFSPrivateFile> {
188182
const dataBuffer = Buffer.from(txData);
189183
const fileKey = this.fileKey ?? (await deriveFileKey(`${this.fileId}`, this.driveKey));
190184

185+
if (!fileKey) {
186+
throw new InvalidFileStateException(['fileKey']);
187+
}
188+
191189
const decryptedFileBuffer: Buffer = await fileDecrypt(this.cipherIV, fileKey, dataBuffer);
192190
const decryptedFileString: string = await Utf8ArrayToStr(decryptedFileBuffer);
193191
const decryptedFileJSON: FileMetaDataTransactionData = await JSON.parse(decryptedFileString);
@@ -199,17 +197,9 @@ export class ArFSPrivateFileBuilder extends ArFSFileBuilder<ArFSPrivateFile> {
199197
this.dataTxId = new TransactionID(decryptedFileJSON.dataTxId);
200198
this.dataContentType = decryptedFileJSON.dataContentType ?? extToMime(this.name);
201199

202-
if (
203-
!this.name ||
204-
this.size === undefined ||
205-
!this.lastModifiedDate ||
206-
!this.dataTxId ||
207-
!this.dataContentType ||
208-
!fileKey ||
209-
!(this.entityType === 'file')
210-
) {
211-
throw new Error('Invalid file state');
212-
}
200+
const fileBuilderValidation = new FileBuilderValidation();
201+
fileBuilderValidation.validateFileProperties(this);
202+
fileBuilderValidation.throwIfMissingProperties();
213203

214204
this.parseCustomMetaDataFromDataJson(decryptedFileJSON);
215205

src/arfs/arfsdao.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ import { assertDataRootsMatch, rePrepareV2Tx } from '../utils/arfsdao_utils';
179179
import { ArFSDataToUpload, ArFSFolderToUpload, DrivePrivacy, errorMessage } from '../exports';
180180
import { Turbo, TurboCachesResponse } from './turbo';
181181
import { ArweaveSigner } from 'arbundles/src/signing';
182+
import { InvalidFileStateException } from '../types/exceptions';
182183

183184
/** Utility class for holding the driveId and driveKey of a new drive */
184185
export class PrivateDriveKeyData {
@@ -1583,21 +1584,31 @@ export class ArFSDAO extends ArFSDAOAnonymous {
15831584
const transactions = await this.gatewayApi.gqlRequest(gqlQuery);
15841585
const { edges } = transactions;
15851586
hasNextPage = transactions.pageInfo.hasNextPage;
1586-
const files: Promise<ArFSPrivateFile>[] = edges.map(async (edge: GQLEdgeInterface) => {
1587-
const { node } = edge;
1588-
cursor = edge.cursor;
1589-
const fileBuilder = ArFSPrivateFileBuilder.fromArweaveNode(node, this.gatewayApi, driveKey);
1590-
// Build the file so that we don't add something invalid to the cache
1591-
const file = await fileBuilder.build(node);
1592-
const fileKey: FileKey = await deriveFileKey(`${file.fileId}`, driveKey);
1593-
const cacheKey = {
1594-
fileId: file.fileId,
1595-
owner,
1596-
fileKey
1597-
};
1598-
return this.caches.privateFileCache.put(cacheKey, Promise.resolve(file));
1587+
const files: Promise<ArFSPrivateFile | null>[] = edges.map(async (edge: GQLEdgeInterface) => {
1588+
try {
1589+
const { node } = edge;
1590+
cursor = edge.cursor;
1591+
const fileBuilder = ArFSPrivateFileBuilder.fromArweaveNode(node, this.gatewayApi, driveKey);
1592+
// Build the file so that we don't add something invalid to the cache
1593+
const file = await fileBuilder.build(node);
1594+
const fileKey: FileKey = await deriveFileKey(`${file.fileId}`, driveKey);
1595+
const cacheKey = {
1596+
fileId: file.fileId,
1597+
owner,
1598+
fileKey
1599+
};
1600+
return this.caches.privateFileCache.put(cacheKey, Promise.resolve(file));
1601+
} catch (e) {
1602+
if (e instanceof InvalidFileStateException) {
1603+
console.error(`Error building file. Skipping... Error: ${e}`);
1604+
return null;
1605+
}
1606+
1607+
throw e;
1608+
}
15991609
});
1600-
allFiles.push(...(await Promise.all(files)));
1610+
const validFiles = (await Promise.all(files)).filter((f) => f !== null) as ArFSPrivateFile[];
1611+
allFiles.push(...validFiles);
16011612
}
16021613
return latestRevisionsOnly ? allFiles.filter(latestRevisionFilter) : allFiles;
16031614
}

0 commit comments

Comments
 (0)