Skip to content

Instantly share code, notes, and snippets.

@ezzabuzaid
Created October 17, 2024 13:50
Show Gist options
  • Save ezzabuzaid/eca657d22a53ab2227de35148c24d03f to your computer and use it in GitHub Desktop.
Save ezzabuzaid/eca657d22a53ab2227de35148c24d03f to your computer and use it in GitHub Desktop.
import fs, { rm } from 'fs';
import { mkdir, writeFile } from 'fs/promises';
import git from 'isomorphic-git';
import http from 'isomorphic-git/http/node';
import os from 'os';
import { dirname, join } from 'path';
import { Context, Inject, Injectable, ServiceLifetime } from 'tiny-injector';
import { v4 } from 'uuid';
import { safeFail } from '@faslh/utils';
import { bundle } from '@january/generator/bundler';
@Injectable({
lifetime: ServiceLifetime.Scoped,
})
class SourceCodeManager {
constructor(@Inject(Context) private readonly _context: Context) {}
public async getFiles() {
return safeFail(() => JSON.parse(this._context.getExtra('files')), []) as {
content: string;
path: string;
}[];
}
public async writeFiles(repoPath: string) {
const files = await this.getFiles();
for (const file of files) {
await mkdir(dirname(join(repoPath, file.path)), { recursive: true });
await writeFile(join(repoPath, file.path), file.content, 'utf-8');
}
}
public bundle(repoPath: string) {
return bundle({
projectRoot: repoPath,
entry: join(repoPath, 'src', 'server.ts'),
out: join(repoPath, 'build', 'server.js'),
});
}
}
@Injectable({
lifetime: ServiceLifetime.Scoped,
})
class Remote {
constructor(private readonly _sourceCodeManager: SourceCodeManager) {}
async push(config: { message: string; accessToken: string }) {
const selectedProject = null as any;
if (!selectedProject.repositoryId) {
throw new Error('Repository name is not set');
}
// Clone the repository first before generating the files so that the generated code sits on top of the latest commit
const repoPath = join(os.tmpdir(), v4());
const repoUrl = `https://${config.accessToken}@github.com/${selectedProject.repositoryName}.git`;
await git.clone({
fs: fs,
http: http,
dir: repoPath,
url: repoUrl,
depth: 1,
remote: 'origin',
ref: 'main',
singleBranch: true,
// corsProxy: 'https://cors.isomorphic-git.org',
});
const files = await this._sourceCodeManager.getFiles();
await this._sourceCodeManager.writeFiles(repoPath);
await this._sourceCodeManager.bundle(repoPath);
try {
for (const file of [
...files,
{
path: join('build', 'server.js'),
},
]) {
await git.add({
fs,
dir: repoPath,
filepath: file.path,
});
}
const sha = await git.commit({
fs,
dir: repoPath,
message: config.message,
author: {
name: 'JanuaryLabs',
},
});
await git.push({
fs,
http,
url: repoUrl,
dir: repoPath,
remote: 'origin',
ref: 'main',
});
return sha;
} finally {
rm(repoPath, { recursive: true, force: true }, (error) => {
console.error(error);
// ignore delete tmp directory error as it is not critical
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment