Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 11, 2022 01:14 am GMT

One Click to Optimize Images, Create Repo and Making Commit

Continuing from last post, I have completed my feature that produces optimized images, create a remote repository and make a commit with the files. My PR may be updated, but I think the change would not be so big from now.

So the main challenge was how I can make one click to create a repo and make a commit. I tried to use octokit.rest library. I'm not sure what I did wrong, but it didn't read the parameters that I passed. But GitHub API version works for me. And the post How to push files programatically to a repository using Octokit with Typescript was a huge help for me. My version is not so different from this post except that I use JavaScript and create multiple blobs in the middle of the process.

First I create a remote repo with createRepo function below.

const createRepo = async (octokit, username, repoName) => {  try {    await octokit.rest.repos.createForAuthenticatedUser({      name: repoName ? repoName : generateUniqueName(username),      description: 'Your repository generated using my-photohub',      private: false,      auto_init: true,    });    return true;  } catch (err) {    console.error(err);    return false;  }};

Then, I produce optimized images with compressor.js.

const compressImage = (file, option) => {  return new Promise((resolve, reject) => {    new Compressor(file, {      width: option.width,      quality: 0.6,      success: (result) => {        const fileName =          file.name.replace(/\.[^/.]+$/, '') +          '_' +          option.width +          '.' +          option.mimeType.substring(option.mimeType.indexOf('/') + 1);        resolve(new File([result], fileName, { type: option.mimeType }));      },      error: (err) => {        console.error(err.message);        reject(err);      },    });  });};export const createOptimizedImages = async (originalImages) => {  if (!originalImages) {    return;  }  let compressFilesPromises = [];  compressorOptions.forEach((option) => {    for (const image of originalImages) {      compressFilesPromises.push(compressImage(image, option));    }  });  return Promise.all(compressFilesPromises);};

You can change image quality or pass different options. I set customized mimeType and width by passing option parameter here. You can find more usages from compressor.js original documentation.

Then I need to create a blob from each file with the function below.

const createBlobForFile = async (octokit, username, repoName, files) => {  let blobDataPromises = [];  for (const file of files) {    let reader = new FileReader();    await reader.readAsDataURL(file);    const promise = new Promise((resolve, reject) => {      reader.onload = async () => {        const base64Data = reader.result;        const blobData = octokit.request(`POST /repos/${username}/${repoName}/git/blobs`, {          owner: username,          repo: repoName,          content: base64Data,        });        resolve(blobData);      };      reader.onerror = reject;    });    blobDataPromises.push(promise);  }  return Promise.all(blobDataPromises);};

So this function returns an array of blob object in the same order from files.

In the blob, it doesn't have a file name that I can use as a path in next function. So I added getPathNamesFromFile().

const getPathNamesFromFile = (convertedFiles) => {  let pathNames = [];  for (const file of convertedFiles) {    pathNames.push(file.name);  }  return pathNames;};

Next step is that I need to get current existing commit from the repo that I just created so that I can add a new commit as a child. Here's the function.

const createNewCommit = async (  octokit,  username,  repoName,  message,  currentTreeSha,  currentCommitSha) =>  (    await octokit.request(`POST /repos/${username}/${repoName}/git/commits`, {      owner: username,      repo: repoName,      message: message,      tree: currentTreeSha,      parents: [currentCommitSha],    })  ).data;

The function is pretty obvious as if I'm making an actual commit. Then, I need to create trees to add. You can find details of git tree object here. Basically blob is a file and tree is a directory in git. You can check your git folder with this command.

 git cat-file -p main^{tree}                                                ...040000 tree f808c5b1a9eaa36928f49ac82b8b2ed85c53af45    .vscode100644 blob 3ee245e88d83084868e58ba369200acc8354f9df    CONTRIBUTING.md...100644 blob 8202e8c8292a2681114b67099e5f47c5aa0e13e4    package.json040000 tree 2ce2a0fdb03a853cc6c855ebc46865cd20d3afaf    public040000 tree e3ef837d95be8981e826c7ad683101475f2b6528    src...

And you would have noticed numbers in front of tree and blob. This number is an associated mode with the file. 100644 means a normal file. You would have figured 040000 is a directory. 100755 is an executable file and 120000 is a symbolic link.

And the last step is to set the branch to this new commit.

const setBranchToCommit = (octokit, username, repoName, branch = `main`, commitSha) =>  octokit.request(`PATCH /repos/${username}/${repoName}/git/refs/heads/${branch}`, {    owner: username,    repo: repoName,    ref: `heads/${branch}`,    sha: commitSha,  });

Conclusion

I spent many days to figure this out. But in the end, I was so happy to see my code working as intended. I was on the issue that my array of promises in createBlobForFile() returned an empty array for many hours. I could have fixed the problem if I tried to think more rational about the behaviour and root cause. I was adding each promise inside reader.onload. So the outer function just bypassed the code block and returned an empty array immediately. It was a lot of trials and learning. Moreover, I'm so glad that I set very fundamental of this app.


Original Link: https://dev.to/genne23v/one-click-to-optimize-images-create-repo-and-making-commit-2203

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To