Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.7.0 - auto CID resolve #40

Merged
merged 4 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,6 @@ Upload contents of a local folder to specified bucket.
- `-b, --bucket-uuid <string>`: UUID of the bucket to upload files to.
- `-w, --wrap`: Wrap uploaded files to an IPFS directory
- `-p, --path <string>`: Path to upload files to (e.g. main/subdir). Required when --wrap is supplied.
- `--await`: await file CIDs to be resolved

**Example**

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apillon/cli",
"description": "▶◀ Apillon CLI tools ▶◀",
"version": "1.5.0",
"version": "1.6.0",
"author": "Apillon",
"license": "MIT",
"main": "./dist/index.js",
Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/modules/storage/storage.commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ export function createStorageCommands(cli: Command) {
.requiredOption('-b, --bucket-uuid <uuid>', 'UUID of destination bucket')
.option('-w, --wrap', 'Wrap uploaded files to an IPFS directory')
.option('-p, --path <string>', 'Path to upload files to')
.option('--await', 'await file CIDs to be resolved')
.option(
'--await',
'await file CIDs to be resolved (DEPRECATED - CIDs are now resolved automatically)',
)
.option('--ignore', 'ignore files from .gitignore file')
.action(async function (path: string) {
await uploadFromFolder(path, this.optsWithGlobals());
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apillon/sdk",
"description": "▶◀ Apillon SDK for NodeJS ▶◀",
"version": "3.6.0",
"version": "3.7.0",
"author": "Apillon",
"license": "MIT",
"main": "./dist/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/modules/rpc/rpc-api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class RpcApiKey extends ApillonModel {
/**
* Array of favorite URLs for the RPC API key.
*/
public urls: string[] = [];
public urls: string[] = null;

/**
* Constructor which should only be called via Rpc class.
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/src/tests/rpc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('Rpc Module tests', () => {

expect(apiKey).toBeInstanceOf(RpcApiKey);
expect(apiKey.id).toEqual(apiKeyId);
expect(apiKey.urls.length).toBeGreaterThan(0);
});

test('List endpoints', async () => {
Expand Down
45 changes: 28 additions & 17 deletions packages/sdk/src/tests/storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,22 +86,10 @@ describe('Storage tests', () => {
console.timeEnd('File upload complete');

expect(files.every((f) => !!f.fileUuid)).toBeTruthy();
});

test('upload files from folder with awaitCid', async () => {
const uploadDir = resolve(__dirname, './helpers/website/');

console.time('File upload complete');
const files = await storage
.bucket(bucketUuid)
.uploadFromFolder(uploadDir, { awaitCid: true });
console.timeEnd('File upload complete');

expect(files.length).toBeGreaterThan(0);
expect(files.every((f) => !!f.CID)).toBeTruthy();
});

test('upload files from folder with ignoreFiles = false', async () => {
test('upload files from folder with ignoreFiles=false', async () => {
const uploadDir = resolve(__dirname, './helpers/website/');

// .gitignore and index.html are not ignored
Expand All @@ -114,9 +102,6 @@ describe('Storage tests', () => {
});

test('upload files from buffer', async () => {
// const html = fs.readFileSync(
// resolve(__dirname, './helpers/website/index.html'),
// );
const css = fs.readFileSync(
resolve(__dirname, './helpers/website/style.css'),
);
Expand All @@ -130,7 +115,7 @@ describe('Storage tests', () => {
content: css,
},
],
{ wrapWithDirectory: true, directoryPath: 'main/subdir' },
{ directoryPath: 'main/subdir' },
);

expect(files.length).toBe(1);
Expand All @@ -142,6 +127,32 @@ describe('Storage tests', () => {
console.timeEnd('File upload complete');
});

test('upload files from buffer with wrapWithDirectory=true', async () => {
const css = fs.readFileSync(
resolve(__dirname, './helpers/website/style.css'),
);
console.time('File upload complete');
const files = await storage.bucket(bucketUuid).uploadFiles(
[
{
fileName: 'style.css',
contentType: 'text/css',
path: null,
content: css,
},
],
{ wrapWithDirectory: true, directoryPath: 'main/subdir-wrapped' },
);

expect(files.length).toBe(1);
expect(files[0].fileUuid).toBeDefined();
expect(files[0].CID).toBeUndefined();
expect(files[0].path).toBeNull();
expect(files[0].url).toBeUndefined();

console.timeEnd('File upload complete');
});

describe.skip('File detail tests', () => {
test('get file details', async () => {
const file = await storage.bucket(bucketUuid).file(fileUuid).get();
Expand Down
40 changes: 14 additions & 26 deletions packages/sdk/src/util/file-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,30 +53,22 @@ export async function uploadFiles(uploadParams: {
const uploadedFiles = [];

for (const fileGroup of chunkify(files, fileChunkSize)) {
if (params.wrapWithDirectory) {
if (params?.wrapWithDirectory) {
for (const fg of fileGroup) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { content, ...rest } = fg;

const readContent = fg.index ? fs.readFileSync(fg.index) : fg.content;

fg.content = readContent;
fg.content = fg.index ? fs.readFileSync(fg.index) : fg.content;
}

const { files } = await ApillonApi.post<IFileUploadResponse>(
`${apiPrefix}/upload`,
{
files: fileGroup.map((fg) => {
// Remove content property from the payload
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { content, ...rest } = fg;
return rest;
}),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
files: fileGroup.map(({ content, ...rest }) => rest),
sessionUuid,
},
);

await uploadFilesToS3(files, fileGroup);
files.forEach((file: any) => delete file.url);

uploadedFiles.push(files);
} else {
Expand Down Expand Up @@ -105,9 +97,7 @@ export async function uploadFiles(uploadParams: {

const { links } = await ApillonApi.post<{ links: string[] }>(
`/storage/link-on-ipfs-multiple`,
{
cids: metadata.cids,
},
{ cids: metadata.cids },
);

metadata.urls = links;
Expand All @@ -120,19 +110,17 @@ export async function uploadFiles(uploadParams: {
);

// Upload doesn't return files in the same order as sent
const sortedFiles = metadata.files.map((metaFile) => {
return files.find((file) => file.fileName === metaFile.fileName);
});
const sortedFiles = metadata.files.map((metaFile) =>
files.find((file) => file.fileName === metaFile.fileName),
);

await uploadFilesToS3(sortedFiles, fileGroup);

const filesWithUrl = sortedFiles.map((file, index) => {
return {
...file,
CID: metadata.cids[index],
url: metadata.urls[index],
};
});
const filesWithUrl = sortedFiles.map((file, index) => ({
...file,
CID: metadata.cids[index],
url: metadata.urls[index],
}));
uploadedFiles.push(filesWithUrl);
}
}
Expand Down