Skip to content

Commit 35c0a88

Browse files
committed
feat(gql): utilize drive ID in conflict resolution and list folder queries PE-6232
1 parent bd6f0d1 commit 35c0a88

File tree

4 files changed

+98
-36
lines changed

4 files changed

+98
-36
lines changed

src/ardrive.ts

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,11 @@ export class ArDrive extends ArDriveAnonymous {
191191
}
192192

193193
// Assert that there are no duplicate names in the destination folder
194-
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(newParentFolderId, owner);
194+
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(
195+
newParentFolderId,
196+
owner,
197+
destFolderDriveId
198+
);
195199
if (entityNamesInParentFolder.includes(originalFileMetaData.name)) {
196200
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
197201
throw new Error(errorMessage.entityNameExists);
@@ -269,7 +273,8 @@ export class ArDrive extends ArDriveAnonymous {
269273
const entityNamesInParentFolder = await this.arFsDao.getPrivateEntityNamesInFolder(
270274
newParentFolderId,
271275
owner,
272-
driveKey
276+
driveKey,
277+
destFolderDriveId
273278
);
274279
if (entityNamesInParentFolder.includes(originalFileMetaData.name)) {
275280
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
@@ -353,7 +358,11 @@ export class ArDrive extends ArDriveAnonymous {
353358
}
354359

355360
// Assert that there are no duplicate names in the destination folder
356-
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(newParentFolderId, owner);
361+
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(
362+
newParentFolderId,
363+
owner,
364+
destFolderDriveId
365+
);
357366
if (entityNamesInParentFolder.includes(originalFolderMetaData.name)) {
358367
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
359368
throw new Error(errorMessage.entityNameExists);
@@ -439,7 +448,8 @@ export class ArDrive extends ArDriveAnonymous {
439448
const entityNamesInParentFolder = await this.arFsDao.getPrivateEntityNamesInFolder(
440449
newParentFolderId,
441450
owner,
442-
driveKey
451+
driveKey,
452+
destFolderDriveId
443453
);
444454
if (entityNamesInParentFolder.includes(originalFolderMetaData.name)) {
445455
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
@@ -523,14 +533,14 @@ export class ArDrive extends ArDriveAnonymous {
523533
const resolvedEntitiesToUpload: UploadStats[] = [];
524534

525535
for (const entity of entitiesToUpload) {
526-
const { destFolderId, wrappedEntity, driveKey, owner, destName } = entity;
536+
const { destFolderId, wrappedEntity, driveKey, owner, destName, destDriveId } = entity;
527537

528538
const resolveConflictParams = {
529539
conflictResolution,
530540
getConflictInfoFn: (folderId: FolderID) =>
531541
driveKey
532-
? this.arFsDao.getPrivateNameConflictInfoInFolder(folderId, owner, driveKey)
533-
: this.arFsDao.getPublicNameConflictInfoInFolder(folderId, owner),
542+
? this.arFsDao.getPrivateNameConflictInfoInFolder(folderId, owner, driveKey, destDriveId)
543+
: this.arFsDao.getPublicNameConflictInfoInFolder(folderId, owner, destDriveId),
534544
prompts,
535545
destFolderId
536546
};
@@ -729,6 +739,7 @@ export class ArDrive extends ArDriveAnonymous {
729739
destinationFolderId
730740
}: RetryPublicArFSFileByDestFolderIdParams): Promise<ArFSResult> {
731741
const metaDataTx = await this.deriveMetaDataTxFromPublicFolder(destinationFolderId, dataTxId);
742+
const driveId = await this.arFsDao.getDriveIdForFolderId(destinationFolderId);
732743

733744
let metaDataTxId: undefined | TransactionID = undefined;
734745
let createMetaDataPlan: undefined | ArFSCreateFileMetaDataV2Plan = undefined;
@@ -743,7 +754,8 @@ export class ArDrive extends ArDriveAnonymous {
743754
const isValidUpload = await this.assertWriteFileMetaData({
744755
wrappedFile,
745756
conflictResolution,
746-
destinationFolderId
757+
destinationFolderId,
758+
driveId
747759
});
748760

749761
if (!isValidUpload) {
@@ -827,11 +839,13 @@ export class ArDrive extends ArDriveAnonymous {
827839
dataTxId: TransactionID
828840
): Promise<ArFSPublicFile | undefined> {
829841
const owner = await this.wallet.getAddress();
842+
const driveId = await this.arFsDao.getDriveIdForFolderId(destinationFolderId);
830843
await this.assertFolderExists(destinationFolderId, owner);
831844

832845
const allFileMetaDataTxInFolder = await this.arFsDao.getPublicFilesWithParentFolderIds(
833846
[destinationFolderId],
834-
owner
847+
owner,
848+
driveId
835849
);
836850
const metaDataTxsForThisTx = allFileMetaDataTxInFolder.filter((f) => `${f.dataTxId}` === `${dataTxId}`);
837851

@@ -853,19 +867,22 @@ export class ArDrive extends ArDriveAnonymous {
853867
private async assertWriteFileMetaData({
854868
wrappedFile,
855869
destinationFolderId,
856-
conflictResolution
870+
conflictResolution,
871+
driveId
857872
}: {
858873
wrappedFile: ArFSFileToUpload;
859874
destinationFolderId: FolderID;
860875
conflictResolution: FileNameConflictResolution;
876+
driveId: DriveID;
861877
}): Promise<boolean> {
862878
const owner = await this.wallet.getAddress();
863879
await resolveFileNameConflicts({
864880
wrappedFile,
865881
conflictResolution,
866882
destFolderId: destinationFolderId,
867883
destinationFileName: wrappedFile.destinationBaseName,
868-
getConflictInfoFn: (folderId: FolderID) => this.arFsDao.getPublicNameConflictInfoInFolder(folderId, owner)
884+
getConflictInfoFn: (folderId: FolderID) =>
885+
this.arFsDao.getPublicNameConflictInfoInFolder(folderId, owner, driveId)
869886
});
870887

871888
if (wrappedFile.conflictResolution) {
@@ -1019,7 +1036,11 @@ export class ArDrive extends ArDriveAnonymous {
10191036
const owner = await this.wallet.getAddress();
10201037

10211038
// Assert that there are no duplicate names in the destination folder
1022-
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(parentFolderId, owner);
1039+
const entityNamesInParentFolder = await this.arFsDao.getPublicEntityNamesInFolder(
1040+
parentFolderId,
1041+
owner,
1042+
driveId
1043+
);
10231044
if (entityNamesInParentFolder.includes(folderName)) {
10241045
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
10251046
throw new Error(errorMessage.entityNameExists);
@@ -1083,7 +1104,8 @@ export class ArDrive extends ArDriveAnonymous {
10831104
const entityNamesInParentFolder = await this.arFsDao.getPrivateEntityNamesInFolder(
10841105
parentFolderId,
10851106
owner,
1086-
driveKey
1107+
driveKey,
1108+
driveId
10871109
);
10881110
if (entityNamesInParentFolder.includes(folderName)) {
10891111
// TODO: Add optional interactive prompt to resolve name conflicts in ticket PE-599
@@ -1438,10 +1460,11 @@ export class ArDrive extends ArDriveAnonymous {
14381460
await fileToDownload.write();
14391461
}
14401462

1441-
async assertUniqueNameWithinPublicFolder(name: string, folderId: FolderID): Promise<void> {
1463+
async assertUniqueNameWithinPublicFolder(name: string, folderId: FolderID, driveId: DriveID): Promise<void> {
14421464
const allSiblingNames = await this.arFsDao.getPublicEntityNamesInFolder(
14431465
folderId,
1444-
await this.wallet.getAddress()
1466+
await this.wallet.getAddress(),
1467+
driveId
14451468
);
14461469
const collidesWithExistingSiblingName = allSiblingNames.reduce((accumulator, siblingName) => {
14471470
return accumulator || siblingName === name;
@@ -1451,11 +1474,17 @@ export class ArDrive extends ArDriveAnonymous {
14511474
}
14521475
}
14531476

1454-
async assertUniqueNameWithinPrivateFolder(name: string, folderId: FolderID, driveKey: DriveKey): Promise<void> {
1477+
async assertUniqueNameWithinPrivateFolder(
1478+
name: string,
1479+
folderId: FolderID,
1480+
driveKey: DriveKey,
1481+
driveId: DriveID
1482+
): Promise<void> {
14551483
const allSiblingNames = await this.arFsDao.getPrivateEntityNamesInFolder(
14561484
folderId,
14571485
await this.wallet.getAddress(),
1458-
driveKey
1486+
driveKey,
1487+
driveId
14591488
);
14601489
const collidesWithExistingSiblingName = allSiblingNames.reduce((accumulator, siblingName) => {
14611490
return accumulator || siblingName === name;
@@ -1467,13 +1496,14 @@ export class ArDrive extends ArDriveAnonymous {
14671496

14681497
async renamePublicFile({ fileId, newName }: RenamePublicFileParams): Promise<ArFSResult> {
14691498
const owner = await this.wallet.getAddress();
1499+
const driveId = await this.getDriveIdForFileId(fileId);
14701500

14711501
const file = await this.getPublicFile({ fileId, owner });
14721502
if (file.name === newName) {
14731503
throw new Error(`To rename a file, the new name must be different`);
14741504
}
14751505
assertValidArFSFileName(newName);
1476-
await this.assertUniqueNameWithinPublicFolder(newName, file.parentFolderId);
1506+
await this.assertUniqueNameWithinPublicFolder(newName, file.parentFolderId, driveId);
14771507
const fileMetadataTxDataStub = new ArFSPublicFileMetadataTransactionData(
14781508
newName,
14791509
file.size,
@@ -1527,11 +1557,12 @@ export class ArDrive extends ArDriveAnonymous {
15271557
async renamePrivateFile({ fileId, newName, driveKey }: RenamePrivateFileParams): Promise<ArFSResult> {
15281558
const owner = await this.wallet.getAddress();
15291559
const file = await this.getPrivateFile({ fileId, driveKey, owner });
1560+
const driveId = await this.getDriveIdForFileId(fileId);
15301561
if (file.name === newName) {
15311562
throw new Error(`To rename a file, the new name must be different`);
15321563
}
15331564
assertValidArFSFileName(newName);
1534-
await this.assertUniqueNameWithinPrivateFolder(newName, file.parentFolderId, driveKey);
1565+
await this.assertUniqueNameWithinPrivateFolder(newName, file.parentFolderId, driveKey, driveId);
15351566
const fileMetadataTxDataStub = await ArFSPrivateFileMetadataTransactionData.from(
15361567
newName,
15371568
file.size,
@@ -1590,6 +1621,7 @@ export class ArDrive extends ArDriveAnonymous {
15901621
async renamePublicFolder({ folderId, newName }: RenamePublicFolderParams): Promise<ArFSResult> {
15911622
const owner = await this.wallet.getAddress();
15921623
const folder = await this.getPublicFolder({ folderId, owner });
1624+
const driveId = await this.getDriveIdForFolderId(folderId);
15931625
if (`${folder.parentFolderId}` === ROOT_FOLDER_ID_PLACEHOLDER) {
15941626
throw new Error(
15951627
`The root folder with ID '${folderId}' cannot be renamed as it shares its name with its parent drive. Consider renaming the drive instead.`
@@ -1599,7 +1631,7 @@ export class ArDrive extends ArDriveAnonymous {
15991631
throw new Error(`New folder name '${newName}' must be different from the current folder name!`);
16001632
}
16011633
assertValidArFSFolderName(newName);
1602-
await this.assertUniqueNameWithinPublicFolder(newName, folder.parentFolderId);
1634+
await this.assertUniqueNameWithinPublicFolder(newName, folder.parentFolderId, driveId);
16031635
const folderMetadataTxDataStub = new ArFSPublicFolderTransactionData(newName, folder.customMetaDataJson);
16041636

16051637
const metadataRewardSettings = this.uploadPlanner.isTurboUpload()
@@ -1647,6 +1679,7 @@ export class ArDrive extends ArDriveAnonymous {
16471679
async renamePrivateFolder({ folderId, newName, driveKey }: RenamePrivateFolderParams): Promise<ArFSResult> {
16481680
const owner = await this.wallet.getAddress();
16491681
const folder = await this.getPrivateFolder({ folderId, driveKey, owner });
1682+
const driveId = await this.getDriveIdForFolderId(folderId);
16501683
if (`${folder.parentFolderId}` === ROOT_FOLDER_ID_PLACEHOLDER) {
16511684
throw new Error(
16521685
`The root folder with ID '${folderId}' cannot be renamed as it shares its name with its parent drive. Consider renaming the drive instead.`
@@ -1656,7 +1689,7 @@ export class ArDrive extends ArDriveAnonymous {
16561689
throw new Error(`New folder name '${newName}' must be different from the current folder name!`);
16571690
}
16581691
assertValidArFSFolderName(newName);
1659-
await this.assertUniqueNameWithinPrivateFolder(newName, folder.parentFolderId, driveKey);
1692+
await this.assertUniqueNameWithinPrivateFolder(newName, folder.parentFolderId, driveKey, driveId);
16601693
const folderMetadataTxDataStub = await ArFSPrivateFolderTransactionData.from(
16611694
newName,
16621695
driveKey,

src/arfs/arfs_entities.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export class ArFSEntity {
3434
readonly contentType: ContentType; // the mime type of the file uploaded. in the case of drives and folders, it is always a JSON file. Public drive/folders must use "application/json" and private drives use "application/octet-stream" since this data is encrypted.
3535
readonly driveId: DriveID; // the unique drive identifier, created with uuidv4 https://www.npmjs.com/package/uuidv4 eg. 41800747-a852-4dc9-9078-6c20f85c0f3a
3636
readonly entityType: EntityType; // the type of ArFS entity this is. this can only be set to "drive", "folder", "file"
37-
readonly name: string; // user defined entity name, cannot be longer than 64 characters. This is stored in the JSON file that is uploaded along with the drive/folder/file metadata transaction
38-
readonly txId: TransactionID; // the arweave transaction id for this entity. 43 numbers/letters eg. 1xRhN90Mu5mEgyyrmnzKgZP0y3aK8AwSucwlCOAwsaI
37+
readonly name: string; // user defined entity name, cannot be longer than 64 characters. This is stored in the JSON file that is uploaded along with the drive/folder/file metadata transaction cspell:disable
38+
readonly txId: TransactionID; // the arweave transaction id for this entity. 43 numbers/letters eg. 1xRhN90Mu5mEgyyrmnzKgZP0y3aK8AwSucwlCOAwsaI cspell:enable
3939
readonly unixTime: UnixTime; // seconds since unix epoch, taken at the time of upload, 10 numbers eg. 1620068042
4040

4141
readonly boost?: FeeMultiple;

src/arfs/arfsdao.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
15461546
folderIDs: FolderID[],
15471547
driveKey: DriveKey,
15481548
owner: ArweaveAddress,
1549+
driveId: DriveID,
15491550
latestRevisionsOnly = false
15501551
): Promise<ArFSPrivateFile[]> {
15511552
let cursor = '';
@@ -1555,6 +1556,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
15551556
while (hasNextPage) {
15561557
const gqlQuery = buildQuery({
15571558
tags: [
1559+
{ name: 'Drive-Id', value: `${driveId}` },
15581560
{ name: 'Parent-Folder-Id', value: folderIDs.map((fid) => fid.toString()) },
15591561
{ name: 'Entity-Type', value: 'file' }
15601562
],
@@ -1593,6 +1595,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
15931595
) =>
15941596
| ArFSFileOrFolderBuilder<'file', ArFSFileOrFolderEntity<'file'>>
15951597
| ArFSFileOrFolderBuilder<'folder', ArFSFileOrFolderEntity<'folder'>>,
1598+
driveId: DriveID,
15961599
latestRevisionsOnly = true,
15971600
filterOnOwner = true
15981601
): Promise<T[]> {
@@ -1603,6 +1606,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16031606
while (hasNextPage) {
16041607
const gqlQuery = buildQuery({
16051608
tags: [
1609+
{ name: 'Drive-Id', value: `${driveId}` },
16061610
{ name: 'Parent-Folder-Id', value: `${parentFolderId}` },
16071611
{ name: 'Entity-Type', value: ['file', 'folder'] }
16081612
],
@@ -1638,6 +1642,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16381642
parentFolderId: FolderID,
16391643
owner: ArweaveAddress,
16401644
driveKey: DriveKey,
1645+
driveId: DriveID,
16411646
latestRevisionsOnly = true
16421647
): Promise<(ArFSPrivateFile | ArFSPrivateFolder)[]> {
16431648
return this.getEntitiesInFolder(
@@ -1647,13 +1652,15 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16471652
entityType === 'folder'
16481653
? ArFSPrivateFolderBuilder.fromArweaveNode(node, this.gatewayApi, driveKey)
16491654
: ArFSPrivateFileBuilder.fromArweaveNode(node, this.gatewayApi, driveKey),
1655+
driveId,
16501656
latestRevisionsOnly
16511657
);
16521658
}
16531659

16541660
async getPublicEntitiesInFolder(
16551661
parentFolderId: FolderID,
16561662
owner: ArweaveAddress,
1663+
driveId: DriveID,
16571664
latestRevisionsOnly = true
16581665
): Promise<(ArFSPublicFile | ArFSPublicFolder)[]> {
16591666
return this.getEntitiesInFolder(
@@ -1663,6 +1670,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16631670
entityType === 'folder'
16641671
? ArFSPublicFolderBuilder.fromArweaveNode(node, this.gatewayApi)
16651672
: ArFSPublicFileBuilder.fromArweaveNode(node, this.gatewayApi),
1673+
driveId,
16661674
latestRevisionsOnly
16671675
);
16681676
}
@@ -1678,18 +1686,23 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16781686
async getPrivateEntityNamesInFolder(
16791687
folderId: FolderID,
16801688
owner: ArweaveAddress,
1681-
driveKey: DriveKey
1689+
driveKey: DriveKey,
1690+
driveId: DriveID
16821691
): Promise<string[]> {
1683-
const childrenOfFolder = await this.getPrivateEntitiesInFolder(folderId, owner, driveKey, true);
1692+
const childrenOfFolder = await this.getPrivateEntitiesInFolder(folderId, owner, driveKey, driveId, true);
16841693
return childrenOfFolder.map(entityToNameMap);
16851694
}
16861695

1687-
async getPublicEntityNamesInFolder(folderId: FolderID, owner: ArweaveAddress): Promise<string[]> {
1688-
const childrenOfFolder = await this.getPublicEntitiesInFolder(folderId, owner, true);
1696+
async getPublicEntityNamesInFolder(folderId: FolderID, owner: ArweaveAddress, driveId: DriveID): Promise<string[]> {
1697+
const childrenOfFolder = await this.getPublicEntitiesInFolder(folderId, owner, driveId, true);
16891698
return childrenOfFolder.map(entityToNameMap);
16901699
}
16911700

1692-
async getPublicNameConflictInfoInFolder(folderId: FolderID, owner: ArweaveAddress): Promise<NameConflictInfo> {
1701+
async getPublicNameConflictInfoInFolder(
1702+
folderId: FolderID,
1703+
owner: ArweaveAddress,
1704+
driveId: DriveID
1705+
): Promise<NameConflictInfo> {
16931706
const cacheKey = { folderId, owner };
16941707
const cachedConflictInfo = this.caches.publicConflictCache.get(cacheKey);
16951708
if (cachedConflictInfo) {
@@ -1699,7 +1712,7 @@ export class ArFSDAO extends ArFSDAOAnonymous {
16991712
return this.caches.publicConflictCache.put(
17001713
cacheKey,
17011714
(async () => {
1702-
const childrenOfFolder = await this.getPublicEntitiesInFolder(folderId, owner, true);
1715+
const childrenOfFolder = await this.getPublicEntitiesInFolder(folderId, owner, driveId, true);
17031716
return {
17041717
files: childrenOfFolder.filter(fileFilter).map(fileConflictInfoMap),
17051718
folders: childrenOfFolder.filter(folderFilter).map(folderToNameAndIdMap)
@@ -1711,7 +1724,8 @@ export class ArFSDAO extends ArFSDAOAnonymous {
17111724
async getPrivateNameConflictInfoInFolder(
17121725
folderId: FolderID,
17131726
owner: ArweaveAddress,
1714-
driveKey: DriveKey
1727+
driveKey: DriveKey,
1728+
driveId: DriveID
17151729
): Promise<NameConflictInfo> {
17161730
const cacheKey = { folderId, owner, driveKey };
17171731
const cachedConflictInfo = this.caches.privateConflictCache.get(cacheKey);
@@ -1722,7 +1736,13 @@ export class ArFSDAO extends ArFSDAOAnonymous {
17221736
return this.caches.privateConflictCache.put(
17231737
cacheKey,
17241738
(async () => {
1725-
const childrenOfFolder = await this.getPrivateEntitiesInFolder(folderId, owner, driveKey, true);
1739+
const childrenOfFolder = await this.getPrivateEntitiesInFolder(
1740+
folderId,
1741+
owner,
1742+
driveKey,
1743+
driveId,
1744+
true
1745+
);
17261746
// Hack to deal with potential typescript bug
17271747
const files = childrenOfFolder.filter(fileFilter) as ArFSPrivateFile[];
17281748
const folders = childrenOfFolder.filter(folderFilter) as ArFSPrivateFolder[];
@@ -2282,9 +2302,11 @@ export class ArFSDAO extends ArFSDAOAnonymous {
22822302
// Fetch all file entities within all Folders of the drive
22832303
const childFiles: ArFSPrivateFile[] = [];
22842304
for (const id of searchFolderIDs) {
2285-
(await this.getPrivateFilesWithParentFolderIds([id], driveKey, owner, true)).forEach((e) => {
2286-
childFiles.push(e);
2287-
});
2305+
(await this.getPrivateFilesWithParentFolderIds([id], driveKey, owner, driveIdOfFolder, true)).forEach(
2306+
(e) => {
2307+
childFiles.push(e);
2308+
}
2309+
);
22882310
}
22892311

22902312
const [, ...subFolderIDs]: FolderID[] = hierarchy.folderIdSubtreeFromFolderId(folder.entityId, maxDepth + 1);

0 commit comments

Comments
 (0)