diff --git a/ui/.env.development b/ui/.env.development
new file mode 100644
index 00000000..81235826
--- /dev/null
+++ b/ui/.env.development
@@ -0,0 +1 @@
+NEXT_PUBLIC_URL=http://localhost:3000
\ No newline at end of file
diff --git a/ui/.env.production b/ui/.env.production
new file mode 100644
index 00000000..11160838
--- /dev/null
+++ b/ui/.env.production
@@ -0,0 +1 @@
+NEXT_PUBLIC_URL=https://$NEXT_PUBLIC_VERCEL_URL
diff --git a/ui/app/api/create-stack-boilerplate/create-stack.ts b/ui/app/api/create-stack-boilerplate/create-stack.ts
index c9cab8e7..7f966822 100644
--- a/ui/app/api/create-stack-boilerplate/create-stack.ts
+++ b/ui/app/api/create-stack-boilerplate/create-stack.ts
@@ -1,65 +1,77 @@
-import { getSupabaseClient } from '@/app/stacks/stack-db';
+import { getSupabaseClient } from '@/app/stacks/stack-db';
import getFileFromGithub from './get-file-from-github';
import pushMultipleFilesToBranch from './push-multiple-files-to-branch';
-export default async function createStack(data) {
+export default async function createStack(data, token) {
+ const stackId = data.name
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
+ .replace(/\s+/g, '-')
+ .toLowerCase();
+
const supabase = await getSupabaseClient();
-
- data.tags = ['draft'];
- const { data: insertedData, error } = await supabase
+ const stackInfo = {
+ name: data.name,
+ id: stackId,
+ description: data.description,
+ tags: ['draft'],
+ }
+ const { data: insertedData, error } = await supabase
.from('stack')
- .insert([data])
+ .insert([
+ stackInfo
+ ])
.single();
- if (error) {
- return new Response(JSON.stringify({ error: error.message }), {
- status: 500,
- headers: {
- 'Content-Type': 'application/json',
- },
- });
- }
- // let filesArray = [];
-
- let path = `ui/app/components/stacks/${data.id}.tsx`;
- let message = `Frontend For Stack ${data.id} created`;
+ if (error) {
+ if (error.message.includes('duplicate key ')) {
+ throw new Error('This app already exists.');
+ }
+ throw error;
+ }
+
+ // creating api key
+ let path = `ui/app/components/stacks/${stackInfo.id}.tsx`;
+ let message = `Frontend For ${stackInfo.id} created`;
let response = await getFileFromGithub(
- 'ui/public/stacks/boilerplate-basic.tsx',
+ 'ui/public/stacks/boilerplate-basic.tsx', token
);
+ await new Promise((resolve) => setTimeout(resolve, 500));
let filesArray = [
{
path: path,
- sha: response.sha,
+ sha: response.content,
+ message: message,
},
];
- await new Promise((resolve) => setTimeout(resolve, 1000));
- path = `ui/app/api/${data.id}/route.ts`;
- message = `Backend For Stack ${data.id} created`;
+ path = `ui/app/api/${stackInfo.id}/route.ts`;
+ message = `Backend For ${stackInfo.id} created`;
response = await getFileFromGithub(
- 'ui/public/stacks/boilerplate-basic/route.ts',
+ 'ui/public/stacks/boilerplate-basic/route.ts', token
);
+ await new Promise((resolve) => setTimeout(resolve, 500));
filesArray.push({
path: path,
- sha: response.sha,
+ sha: response.content,
+ message: message,
});
- path = `ui/public/stack-pictures/${data.id}.png`;
- message = `Stack ${data.id} created`;
+ path = `ui/public/stack-pictures/${stackInfo.id}.png`;
+ message = `Preview For ${stackInfo.id} created`;
response = await getFileFromGithub(
- 'ui/public/stack-pictures/boilerplate-basic.png',
+ 'ui/public/stack-pictures/boilerplate-basic.png', token
);
+ await new Promise((resolve) => setTimeout(resolve, 500));
filesArray.push({
path: path,
- sha: response.sha,
+ sha: response.content,
+ message: message,
});
- const sourceBranch = process.env.VERCEL_GIT_COMMIT_REF ?? ''; // or 'master', depending on your repository
-
- await pushMultipleFilesToBranch(filesArray, sourceBranch, message);
+ // const sourceBranch = process.env.VERCEL_GIT_COMMIT_REF ?? ''; // or 'master', depending on your repository
- await supabase.rpc('commit');
+ await pushMultipleFilesToBranch(filesArray, stackInfo.id, token);
}
diff --git a/ui/app/api/create-stack-boilerplate/get-file-from-github.ts b/ui/app/api/create-stack-boilerplate/get-file-from-github.ts
index d68dd3a8..bc6dc014 100644
--- a/ui/app/api/create-stack-boilerplate/get-file-from-github.ts
+++ b/ui/app/api/create-stack-boilerplate/get-file-from-github.ts
@@ -1,13 +1,13 @@
-export default async function getFileFromGithub(path) {
+export default async function getFileFromGithub(path, token) {
const owner = 'stackwiseai';
const repo = 'stackwise';
const sourceBranch = process.env.VERCEL_GIT_COMMIT_REF ?? ''; // or 'master', depending on your repository
- const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${sourceBranch}`;
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=main`;
console.log(url, 'url');
const response = await fetch(url, {
headers: {
- Authorization: `token ${process.env.GITHUB_TOKEN}`,
+ Authorization: `token ${token}`,
},
});
return response.json();
diff --git a/ui/app/api/create-stack-boilerplate/push-multiple-files-to-branch.ts b/ui/app/api/create-stack-boilerplate/push-multiple-files-to-branch.ts
index 376fd3c6..11bf3018 100644
--- a/ui/app/api/create-stack-boilerplate/push-multiple-files-to-branch.ts
+++ b/ui/app/api/create-stack-boilerplate/push-multiple-files-to-branch.ts
@@ -1,6 +1,5 @@
import { Octokit } from '@octokit/rest';
-const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const owner = 'stackwiseai';
const repo = 'stackwise';
const sourceBranch = process.env.VERCEL_GIT_COMMIT_REF ?? ''; // or 'master', depending on your repository
@@ -10,62 +9,71 @@ export const revalidate = 0;
export default async function pushMultipleFilesToBranch(
filesArray,
branch,
- message,
+ token
) {
- try {
- let parentSha;
- const { data: sourceBranchData } = await octokit.repos.getBranch({
- owner,
- repo,
- branch: sourceBranch,
- });
- parentSha = sourceBranchData.commit.sha;
-
- const { data: commitData } = await octokit.git.getCommit({
- owner,
- repo,
- commit_sha: parentSha,
- });
- const treeSha = commitData.tree.sha;
- //iterate througjh filesArray
- let tree = filesArray.map((file) => ({
- path: file.path,
- mode: '100644', // blob (file)
- type: 'blob',
- sha: file.sha,
- }));
+ const octokit = new Octokit({ auth: token });
- const { data: treeData } = await octokit.git.createTree({
+ try {
+ const response = await octokit.rest.repos.createFork({
owner,
repo,
- tree,
- base_tree: treeSha,
});
- // Create a new commit with the new tree and the parent commit
- const { data: newCommitData } = await octokit.git.createCommit({
- owner,
- repo,
- message,
- tree: treeData.sha,
- parents: [parentSha],
- });
+ await octokit.rest.activity.starRepoForAuthenticatedUser({
+ owner: owner,
+ repo: repo
+ });
+ const { data: user } = await octokit.users.getAuthenticated();
+ const forkedRepoOwner = user.login;
+ console.log(user, 'user');
+ // wait 2 seconds
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ const { data: refData } = await octokit.git.getRef({
+ owner: forkedRepoOwner,
+ repo: repo,
+ ref: `heads/main`
+ });
+ const sha = refData.object.sha;
- console.log('Created commit:', newCommitData.sha);
+ // Create a new branch using the SHA
- // Update the branch reference to point to the new commit
- await octokit.git.updateRef({
- owner,
+ try {
+ await octokit.git.createRef({
+ owner: forkedRepoOwner,
+ repo: repo,
+ ref: `refs/heads/${branch}`,
+ sha: sha
+ });
+ } catch (error) {
+ console.log("branch already exists ");
+ }
+
+ for (let i = 0; i < filesArray.length; i++) {
+ const file = filesArray[i];
+ const response = await octokit.rest.repos.createOrUpdateFileContents({
+ owner: forkedRepoOwner,
+ repo,
+ path: file.path,
+ branch: branch,
+ message: file.message,
+ content: file.sha,
+ });
+ //wait .5 seconds
+ await new Promise((resolve) => setTimeout(resolve, 500));
+ console.log('response', response);
+ }
+
+ const { data } = await octokit.pulls.create({
+ owner: "stackwiseai",
repo,
- ref: `heads/${branch}`,
- sha: newCommitData.sha,
+ title: `Create stack ${branch}`,
+ head: `${forkedRepoOwner}:${branch}`,
+ base: "main",
+ body:"",
});
-
- console.log('Successfully pushed multiple files to branch:', branch);
- const gitDiffLink = `https://github.com/${owner}/${repo}/compare/${sourceBranch}...${branch}`;
- console.log('gitDiffLink', gitDiffLink);
- return gitDiffLink;
+
+ return "ok";
} catch (error) {
console.error('Error pushing multiple files to branch:', error);
}
diff --git a/ui/app/api/create-stack-boilerplate/route.ts b/ui/app/api/create-stack-boilerplate/route.ts
index 6730b8af..902c0f3d 100644
--- a/ui/app/api/create-stack-boilerplate/route.ts
+++ b/ui/app/api/create-stack-boilerplate/route.ts
@@ -15,12 +15,32 @@ export const fetchCache = 'force-no-store'; // TODO: remove this line to enable
export const revalidate = 0;
export async function POST(req: Request) {
const data = await req.json();
- createStack(data);
- // Return a success response
- return new Response(JSON.stringify({}), {
- status: 200,
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-}
+ // get the token from header and strip the Bearer
+ try {
+ if (req.headers) {
+ const header = req.headers.get('Authorization');
+ if (header) {
+ const token = header.split(' ')[1];
+ await createStack(data, token);
+ return new Response(JSON.stringify({}), {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ } else {
+ throw new Error('No token provided');
+
+ }} else {
+ throw new Error('No headers provided');
+ }
+ } catch (error) {
+ console.error('Error during data insertion:', error);
+ return new Response(JSON.stringify({ message: error.message }), {
+ status: 500,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ }
+}
diff --git a/ui/app/components/stacks/create-stack-boilerplate.tsx b/ui/app/components/stacks/create-stack-boilerplate.tsx
index f20eba92..291f183e 100644
--- a/ui/app/components/stacks/create-stack-boilerplate.tsx
+++ b/ui/app/components/stacks/create-stack-boilerplate.tsx
@@ -1,13 +1,35 @@
-import { useState } from 'react';
+"use client"
+import SignIn from '@/app/stacks/signIn';
+import { supabaseClient } from '@/app/stacks/stack-db';
+import { useEffect, useState } from 'react';
export const BasicForm = () => {
const [formData, setFormData] = useState({
- name: '',
- description: '',
- id: '',
+ name: 'My New App',
});
const [formErrors, setFormErrors] = useState({ id: '' });
const [Message, setMessage] = useState('');
+ const [isUserSignedIn, setIsUserSignedIn] = useState(false);
+ const [username, setUsername] = useState("");
+ const [token, setToken] = useState("");
+ useEffect(() => {
+ // Check if user is signed in
+ async function checkUser() {
+ try {
+ const session = await supabaseClient.auth.getSession()
+ const token = session?.data?.session?.provider_token
+
+ if (token) {
+ setIsUserSignedIn(true);
+ setUsername(session?.data?.session?.user.user_metadata.preferred_username)
+ setToken(token)
+ }
+ } catch {
+ console.log("Error getting user")
+ }
+ }
+ checkUser()
+ }, []);
// const { getToken } = useAuth();
const isKebabCase = (str) => /^[a-z0-9]+(-[a-z0-9]+)*$/.test(str);
@@ -27,19 +49,17 @@ export const BasicForm = () => {
};
const handleSubmit = async (event) => {
+ setMessage('');
event.preventDefault();
- // const token = await getToken({ template: "supabase" });
-
- if (!isKebabCase(formData.id)) {
- setFormErrors({ ...formErrors, id: 'ID must be in kebab-case.' });
- return;
- }
try {
+
+ // console.log(session, "session")
const response = await fetch('/api/create-stack-boilerplate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
},
body: JSON.stringify(formData),
});
@@ -49,14 +69,21 @@ export const BasicForm = () => {
const responseData = await response.json();
console.log('Response:', responseData);
} else {
- throw new Error(`HTTP error! Status: ${response.status}`);
+ const errorData = await response.json();
+
+ setMessage(errorData.message);
}
} catch (error) {
- console.error('Error during fetch:', error);
- setMessage('Error on form submission');
+ console.log(error);
+ setMessage("error on form submission");
+
}
};
+ if (!isUserSignedIn) {
+ return (
An unexpected error happened. Please contact us on Discord
+