Skip to content

Commit

Permalink
fix minio
Browse files Browse the repository at this point in the history
  • Loading branch information
CordlessWool committed Nov 11, 2024
1 parent b1f0d41 commit 7194d35
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 38 deletions.
83 changes: 46 additions & 37 deletions adapters/minio/src/core/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ import {
DirectoryNotEmptyException,
PathNotFoundException,
} from "@loom-io/core";
import { removePrecedingSlash } from "@loom-io/common";
import { join } from "path";
import { removePrecedingSlash, addTailingSlash } from "@loom-io/common";
import { join, normalize } from "node:path";
import { S3Error } from "minio/dist/esm/errors.mjs";

function addTailSlash(path: string): string {
return path.endsWith("/") ? path : `${path}/`;
}

type AdapterStat = {
size: number;
Expand All @@ -28,7 +25,7 @@ export class Adapter implements SourceAdapter<AdapterStat> {
protected bucket: string,
) {}
async deleteFile(path: string): Promise<void> {
await this.s3.removeObject(this.bucket, path);
await this.s3.removeObject(this.bucket, this.translatePath(path));
}

get raw() {
Expand All @@ -39,7 +36,17 @@ export class Adapter implements SourceAdapter<AdapterStat> {
return this.bucket;
}

protected translatePath(path: string) {
if(path.match(/[A-Za-z]{1}:/)) {
return path.slice(2).replaceAll('\\', '/');
} else if (path.includes('\\')) {
return path.replaceAll('\\', '/');
}
return path;
}

protected async exists(path: string): Promise<boolean> {

const bucketStream = this.s3.listObjectsV2(this.bucket, path);
return new Promise((resolve, reject) => {
bucketStream.on("data", () => {
Expand All @@ -56,35 +63,35 @@ export class Adapter implements SourceAdapter<AdapterStat> {
}

async fileExists(path: string): Promise<boolean> {
return this.exists(path);
return this.exists(this.translatePath(path));
}

async dirExists(path: string): Promise<boolean> {
const pathWithTailSlash = addTailSlash(path);
const pathWithTailSlash = this.translatePath(addTailingSlash(path));
if (path === "/") {
return true;
}
return this.exists(pathWithTailSlash);
}

async mkdir(path: string): Promise<void> {
const pathWithTailSlash = removePrecedingSlash(addTailSlash(path));
const pathWithTailSlash = this.translatePath(removePrecedingSlash(addTailingSlash(path)));
if (pathWithTailSlash === "") {
return;
}
await this.s3.putObject(this.bucket, pathWithTailSlash, Buffer.alloc(0));
}

protected async rmdirRecursive(bucket: string, path: string): Promise<void> {
path = removePrecedingSlash(addTailSlash(path));
const objects = await this.s3.listObjectsV2(bucket, path, true);
const pathWithTailSlash = this.translatePath(removePrecedingSlash(addTailingSlash(path)));
const objects = await this.s3.listObjectsV2(bucket, pathWithTailSlash, true);
for await (const obj of objects) {
await this.s3.removeObject(bucket, obj.name);
}
}

protected async rmdirForce(path: string): Promise<void> {
const pathWithTailSlash = removePrecedingSlash(addTailSlash(path));
const pathWithTailSlash = this.translatePath(removePrecedingSlash(addTailingSlash(path)));
if (pathWithTailSlash === "") {
await this.rmdirRecursive(this.bucket, pathWithTailSlash);
return;
Expand All @@ -95,6 +102,7 @@ export class Adapter implements SourceAdapter<AdapterStat> {
}

protected async dirHasFiles(path: string): Promise<boolean> {
path = this.translatePath(path);
const pathWithTailSlash = path.endsWith("/") ? path : `${path}/`;
const bucketStream = await this.s3.listObjectsV2(
this.bucket,
Expand All @@ -117,8 +125,25 @@ export class Adapter implements SourceAdapter<AdapterStat> {
});
}

async rmdir(path: string, options: rmdirOptions = {}): Promise<void> {
if (options.force) {
await this.rmdirForce(path);
return;
} else if (options.recursive) {
await this.rmdirRecursive(this.bucket, path);
return;
} else {
path = this.translatePath(path);
if (await this.dirHasFiles(path)) {
throw new DirectoryNotEmptyException(path);
}
const pathWithTailSlash = path.endsWith("/") ? path : `${path}/`;
await this.s3.removeObject(this.bucket, pathWithTailSlash);
}
}

async readdir(path: string): Promise<ObjectDirentInterface[]> {
const pathWithTailSlash = removePrecedingSlash(addTailSlash(path));
const pathWithTailSlash = this.translatePath(removePrecedingSlash(addTailingSlash(path)));
const bucketStream = await this.s3.listObjectsV2(
this.bucket,
pathWithTailSlash,
Expand All @@ -144,25 +169,9 @@ export class Adapter implements SourceAdapter<AdapterStat> {
});
});
}

async rmdir(path: string, options: rmdirOptions = {}): Promise<void> {
if (options.force) {
await this.rmdirForce(path);
return;
} else if (options.recursive) {
await this.rmdirRecursive(this.bucket, path);
return;
} else {
if (await this.dirHasFiles(path)) {
throw new DirectoryNotEmptyException(path);
}
const pathWithTailSlash = path.endsWith("/") ? path : `${path}/`;
await this.s3.removeObject(this.bucket, pathWithTailSlash);
}
}


async stat(path: string) {
const stat = await this.s3.statObject(this.bucket, path);
const stat = await this.s3.statObject(this.bucket, this.translatePath(path));
return {
size: stat.size,
mtime: stat.lastModified,
Expand All @@ -175,7 +184,7 @@ export class Adapter implements SourceAdapter<AdapterStat> {
path: string,
encoding?: BufferEncoding,
): Promise<Buffer | string> {
const stream = await this.s3.getObject(this.bucket, path);
const stream = await this.s3.getObject(this.bucket, this.translatePath(path));
return new Promise((resolve, reject) => {
const buffers: Buffer[] = [];
stream.on("data", (data) => {
Expand All @@ -195,14 +204,14 @@ export class Adapter implements SourceAdapter<AdapterStat> {

async writeFile(path: string, data: Buffer | string): Promise<void> {
const buffer = Buffer.from(data);
await this.s3.putObject(this.bucket, path, buffer, buffer.length, {
await this.s3.putObject(this.bucket, this.translatePath(path), buffer, buffer.length, {
"Content-Type": "text/plain",
});
return;
}

async openFile(path: string): Promise<FileHandler> {
return new FileHandler(this, this.bucket, path);
return new FileHandler(this, this.bucket, this.translatePath(path));
}

async isCopyable(adapter: SourceAdapter): Promise<boolean> {
Expand All @@ -217,15 +226,15 @@ export class Adapter implements SourceAdapter<AdapterStat> {
const conds = new CopyConditions();
await this.s3.copyObject(
this.bucket,
dest,
join(this.bucket, src),
this.translatePath(dest),
this.translatePath(join(this.bucket, src)),
conds,
);
} catch (err) {
if (err instanceof S3Error) {
if (err.code === "NoSuchKey") {
// @ts-expect-error property code does not exist on S3Error
throw new PathNotFoundException(err.key);
throw new PathNotFoundException(normalize(err.key));
}

throw err;
Expand Down
3 changes: 2 additions & 1 deletion adapters/minio/src/core/object-dirent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ObjectDirentInterface } from '@loom-io/core';
import { BucketItem } from 'minio';
import { addPrecedingAndTailingSlash } from '@loom-io/common';
import { normalize } from 'node:path';

export class ObjectDirent implements ObjectDirentInterface{

Expand Down Expand Up @@ -44,7 +45,7 @@ export class ObjectDirent implements ObjectDirentInterface{

get path() {
const [path] = this.getPathAndName();
return addPrecedingAndTailingSlash(path);
return normalize(addPrecedingAndTailingSlash(path));
}

}

0 comments on commit 7194d35

Please sign in to comment.