From 33b81603cf65b04944dab5cade474df0d8e8b057 Mon Sep 17 00:00:00 2001
From: pankaj <0xpankaj@gmail.com>
Date: Sat, 5 Apr 2025 04:38:08 +0545
Subject: [PATCH 1/3] adding differnt stack
---
rust-backend/Cargo.toml | 6 ++++++
rust-backend/src/main.rs | 3 +++
2 files changed, 9 insertions(+)
create mode 100644 rust-backend/Cargo.toml
create mode 100644 rust-backend/src/main.rs
diff --git a/rust-backend/Cargo.toml b/rust-backend/Cargo.toml
new file mode 100644
index 0000000..989c27b
--- /dev/null
+++ b/rust-backend/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "rust-backend"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/rust-backend/src/main.rs b/rust-backend/src/main.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/rust-backend/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
From 79c3ff7d2aea3b7afe35950fd43e7c9153dcd38c Mon Sep 17 00:00:00 2001
From: pankaj <0xpankaj@gmail.com>
Date: Sat, 5 Apr 2025 04:46:02 +0545
Subject: [PATCH 2/3] working on dockerfile pod
---
.../frontend/app/project/[projectId]/page.tsx | 26 +-
.../frontend/components/ProjectsDrawer.tsx | 2 +-
mobile-magic/apps/k8s-orchestrator/index.ts | 410 ++++++++++--------
mobile-magic/apps/k8s-orchestrator/redis.ts | 15 +-
mobile-magic/apps/primary-backend/index.ts | 23 +-
mobile-magic/bun.lock | 24 +-
.../docker/Dockerfile.code-server-nextjs | 32 ++
.../docker/Dockerfile.code-server-react | 40 ++
.../docker/Dockerfile.code-server-react-expo | 32 ++
.../Dockerfile.code-server-rust-backend | 31 ++
mobile-magic/packages/common/.env.example | 1 +
mobile-magic/packages/common/middleware.ts | 35 +-
mobile-magic/packages/common/types.d.ts | 8 +-
13 files changed, 443 insertions(+), 236 deletions(-)
create mode 100644 mobile-magic/docker/Dockerfile.code-server-nextjs
create mode 100644 mobile-magic/docker/Dockerfile.code-server-react
create mode 100644 mobile-magic/docker/Dockerfile.code-server-react-expo
create mode 100644 mobile-magic/docker/Dockerfile.code-server-rust-backend
create mode 100644 mobile-magic/packages/common/.env.example
diff --git a/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx b/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
index 4f47bd0..4a4f190 100644
--- a/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
+++ b/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
@@ -3,18 +3,24 @@ import { K8S_ORCHESTRATOR_URL } from "@/config";
import ProjectWithInitRequest from "@/components/ProjectWithInitRequest";
interface Params {
- params: Promise<{ projectId: string }>
+ params: Promise<{ projectId: string }>;
}
export default async function ProjectPage({ params }: Params) {
- const projectId = (await params).projectId
- const response = await axios.get(`${K8S_ORCHESTRATOR_URL}/worker/${projectId}`);
- const { sessionUrl, previewUrl, workerUrl } = response.data;
+ const projectId = (await params).projectId;
+ console.log("k8s url: ", K8S_ORCHESTRATOR_URL);
+ console.log("projectId: ", projectId);
+ const response = await axios.get(
+ `${K8S_ORCHESTRATOR_URL}/worker/${projectId}`,
+ );
+ const { sessionUrl, previewUrl, workerUrl } = response.data;
- return
+ return (
+
+ );
}
diff --git a/mobile-magic/apps/frontend/components/ProjectsDrawer.tsx b/mobile-magic/apps/frontend/components/ProjectsDrawer.tsx
index 1a02abd..dc46c0b 100644
--- a/mobile-magic/apps/frontend/components/ProjectsDrawer.tsx
+++ b/mobile-magic/apps/frontend/components/ProjectsDrawer.tsx
@@ -8,7 +8,7 @@ import {
DrawerTitle,
} from "@/components/ui/drawer";
-import { SignedIn, useClerk, UserButton, useUser } from "@clerk/nextjs";
+import { SignedIn, UserButton, useUser } from "@clerk/nextjs";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { MessageSquareIcon, SearchIcon, UmbrellaOff } from "lucide-react";
diff --git a/mobile-magic/apps/k8s-orchestrator/index.ts b/mobile-magic/apps/k8s-orchestrator/index.ts
index 5f43cc8..68dbd8d 100644
--- a/mobile-magic/apps/k8s-orchestrator/index.ts
+++ b/mobile-magic/apps/k8s-orchestrator/index.ts
@@ -1,29 +1,28 @@
-process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
-import express from 'express';
+process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
+import express from "express";
import { KubeConfig, CoreV1Api } from "@kubernetes/client-node";
import * as k8s from "@kubernetes/client-node";
-import cors from 'cors';
-import { Writable } from 'stream';
-import { DOMAIN } from './config';
-import { prismaClient } from "db/client";
-import promClient from 'prom-client';
+import cors from "cors";
+import { Writable } from "stream";
+import { DOMAIN } from "./config";
+import { prismaClient } from "db/client";
+import promClient from "prom-client";
const containerCreateBucket = new promClient.Histogram({
- name: 'container_create_bucket',
- help: 'Number of times a container was created',
- labelNames: ['type'],
- buckets: [50, 100, 250, 500, 1000, 2500, 5000, 10000, 20000],
+ name: "container_create_bucket",
+ help: "Number of times a container was created",
+ labelNames: ["type"],
+ buckets: [50, 100, 250, 500, 1000, 2500, 5000, 10000, 20000],
});
-
const kc = new KubeConfig();
const app = express();
const PROJECT_TYPE_TO_BASE_FOLDER = {
- NEXTJS: "/tmp/next-app",
- REACT: "/tmp/react-app",
- REACT_NATIVE: "/tmp/mobile-app"
-}
+ NEXTJS: "/tmp/next-app",
+ REACT: "/tmp/react-app",
+ REACT_NATIVE: "/tmp/mobile-app",
+};
kc.loadFromDefault();
@@ -34,188 +33,255 @@ const currentContext = kc.getCurrentContext();
const cluster = kc.getCluster(currentContext);
async function listPods(): Promise {
- const res = await k8sApi.listNamespacedPod({ namespace: 'user-apps' });
- console.log(res.items.map((pod) => pod.status?.phase));
- return res.items.filter(pod => pod.status?.phase === 'Running' || pod.status?.phase === 'Pending').filter(pod => pod.metadata?.name).map((pod) => pod.metadata?.name as string);
+ const res = await k8sApi.listNamespacedPod({ namespace: "user-apps" });
+ console.log(res.items.map((pod) => pod.status?.phase));
+ return res.items
+ .filter(
+ (pod) =>
+ pod.status?.phase === "Running" || pod.status?.phase === "Pending",
+ )
+ .filter((pod) => pod.metadata?.name)
+ .map((pod) => pod.metadata?.name as string);
}
-async function createPod(name: string) {
-
- await k8sApi.createNamespacedPod({ namespace: 'user-apps', body: {
- metadata: {
- name: name,
- labels: {
- app: name,
- },
+async function createPod(name: string, projectType: ProjectType) {
+ await k8sApi.createNamespacedPod({
+ namespace: "user-apps",
+ body: {
+ metadata: {
+ name: name,
+ labels: {
+ app: name,
},
- spec: {
- containers: [{
- name: "code-server",
- image: '100xdevs/code-server-base:v3',
- ports: [{ containerPort: 8080 }, { containerPort: 8081 }],
- }, {
- name: "ws-relayer",
- image: "100xdevs/antidevs-ws-relayer:ff488d08f7a2bf15c77d9787352a79468c14fc3f",
- ports: [{ containerPort: 9093 }],
- }, {
- name: "worker",
- image: "100xdevs/antidevs-worker:ff488d08f7a2bf15c77d9787352a79468c14fc3f",
- ports: [{ containerPort: 9091 }],
- env: [{
- name: "WS_RELAYER_URL",
- value: `ws://localhost:9091`,
- }, {
- name: "ANTHROPIC_API_KEY",
- valueFrom: {
- secretKeyRef: {
- name: "worker-secret",
- key: "ANTHROPIC_API_KEY",
- }
- }
- }, {
- name: "DATABASE_URL",
- valueFrom: {
- secretKeyRef: {
- name: "worker-secret",
- key: "DATABASE_URL",
- }
- }
- }]
- }],
- },
- }});
+ },
+ spec: {
+ containers: [
+ {
+ name: "code-server",
+ image: PROJECT_TYPE_TO_IMAGE[projectType],
+ ports: [{ containerPort: 8080 }, { containerPort: 8081 }],
+ },
+ {
+ name: "ws-relayer",
+ image:
+ "100xdevs/antidevs-ws-relayer:ff488d08f7a2bf15c77d9787352a79468c14fc3f",
+ ports: [{ containerPort: 9093 }],
+ },
+ {
+ name: "worker",
+ image:
+ "100xdevs/antidevs-worker:ff488d08f7a2bf15c77d9787352a79468c14fc3f",
+ ports: [{ containerPort: 9091 }],
+ env: [
+ {
+ name: "WS_RELAYER_URL",
+ value: `ws://localhost:9091`,
+ },
+ {
+ name: "ANTHROPIC_API_KEY",
+ valueFrom: {
+ secretKeyRef: {
+ name: "worker-secret",
+ key: "ANTHROPIC_API_KEY",
+ },
+ },
+ },
+ {
+ name: "DATABASE_URL",
+ valueFrom: {
+ secretKeyRef: {
+ name: "worker-secret",
+ key: "DATABASE_URL",
+ },
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ });
- await k8sApi.createNamespacedService({ namespace: 'user-apps', body: {
- metadata: {
- name: `session-${name}`,
- },
- spec: {
- selector: {
- app: name,
- },
- ports: [{ port: 8080, targetPort: 8080, protocol: 'TCP', name: 'session' }],
+ await k8sApi.createNamespacedService({
+ namespace: "user-apps",
+ body: {
+ metadata: {
+ name: `session-${name}`,
+ },
+ spec: {
+ selector: {
+ app: name,
},
- }});
+ ports: [
+ { port: 8080, targetPort: 8080, protocol: "TCP", name: "session" },
+ ],
+ },
+ },
+ });
- await k8sApi.createNamespacedService({ namespace: 'user-apps', body: {
- metadata: {
- name: `preview-${name}`,
- },
- spec: {
- selector: {
- app: name,
- },
- ports: [{ port: 8080, targetPort: 8081, protocol: 'TCP', name: 'preview' }],
+ await k8sApi.createNamespacedService({
+ namespace: "user-apps",
+ body: {
+ metadata: {
+ name: `preview-${name}`,
+ },
+ spec: {
+ selector: {
+ app: name,
},
- }});
+ ports: [
+ { port: 8080, targetPort: 8081, protocol: "TCP", name: "preview" },
+ ],
+ },
+ },
+ });
- await k8sApi.createNamespacedService({ namespace: 'user-apps', body: {
- metadata: {
- name: `worker-${name}`,
+ await k8sApi.createNamespacedService({
+ namespace: "user-apps",
+ body: {
+ metadata: {
+ name: `worker-${name}`,
+ },
+ spec: {
+ selector: {
+ app: name,
},
- spec: {
- selector: {
- app: name,
- },
- ports: [{ port: 8080, targetPort: 9091, protocol: 'TCP', name: 'preview' }],
- },
- }});
+ ports: [
+ { port: 8080, targetPort: 9091, protocol: "TCP", name: "preview" },
+ ],
+ },
+ },
+ });
}
async function checkPodIsReady(name: string) {
- let attempts = 0;
- while (true) {
- const pod = await k8sApi.readNamespacedPod({ namespace: 'user-apps', name });
- if (pod.status?.phase === 'Running') {
- return;
- }
- if (attempts > 10) {
- throw new Error("Pod is not ready");
- }
- //TODO: Exponential backoff
- await new Promise((resolve) => setTimeout(resolve, 2000));
- attempts++;
+ let attempts = 0;
+ while (true) {
+ const pod = await k8sApi.readNamespacedPod({
+ namespace: "user-apps",
+ name,
+ });
+ if (pod.status?.phase === "Running") {
+ return;
+ }
+ if (attempts > 10) {
+ throw new Error("Pod is not ready");
}
+ //TODO: Exponential backoff
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ attempts++;
+ }
}
-async function assignPodToProject(projectId: string, projectType: "NEXTJS" | "REACT_NATIVE" | "REACT") {
- const pods = await listPods();
- const podExists = pods.find(pod => pod === projectId);
- if (!podExists) {
- console.log("Pod does not exist, creating pod");
- await createPod(projectId);
- }
+enum ProjectType {
+ REACT_NATIVE = "REACT_NATIVE",
+ NEXTJS = "NEXTJS",
+ REACT = "REACT",
+}
+
+const PROJECT_TYPE_TO_IMAGE: Record = {
+ [ProjectType.NEXTJS]: "100xdevs/code-server-nextjs:v3", //100xdevs/code-server-base:v3
+ [ProjectType.REACT]: "100xdevs/code-server-react:v3",
+ [ProjectType.REACT_NATIVE]: "100xdevs/code-server-react:v3",
+};
- console.log("Pod exists, checking if it is ready");
- await checkPodIsReady(projectId);
- console.log("Pod is ready, moving project to pod");
-
- const exec = new k8s.Exec(kc);
- let stdout = "";
- let stderr = "";
- console.log(`mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`);
-
- exec.exec("user-apps", projectId, "code-server", ["/bin/sh", "-c", `mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`],
- new Writable({
- write: (chunk: Buffer, encoding: BufferEncoding, callback: () => void) => {
- stdout += chunk;
- callback();
- }
- }),
- new Writable({
- write: (chunk: Buffer, encoding: BufferEncoding, callback: () => void) => {
- stderr += chunk;
- callback();
- }
- }),
- null,
- false,
- (status) => {
- console.log(status);
- console.log(stdout);
- console.log(stderr);
- }
- );
-
- await new Promise((resolve) => setTimeout(resolve, 1000));
- console.log(stdout);
- console.log(stderr);
-
- console.log(`Assigned project ${projectId} to pod ${projectId}`);
+async function assignPodToProject(projectId: string, projectType: ProjectType) {
+ const pods = await listPods();
+ const podExists = pods.find((pod) => pod === projectId);
+ if (!podExists) {
+ console.log("Pod does not exist, creating pod");
+
+ await createPod(projectId, projectType);
+ }
+
+ console.log("Pod exists, checking if it is ready");
+ await checkPodIsReady(projectId);
+ console.log("Pod is ready, moving project to pod");
+
+ const exec = new k8s.Exec(kc);
+ let stdout = "";
+ let stderr = "";
+ console.log(`mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`);
+
+ exec.exec(
+ "user-apps",
+ projectId,
+ "code-server",
+ ["/bin/sh", "-c", `mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`],
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stdout += chunk;
+ callback();
+ },
+ }),
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stderr += chunk;
+ callback();
+ },
+ }),
+ null,
+ false,
+ (status) => {
+ console.log(status);
+ console.log(stdout);
+ console.log(stderr);
+ },
+ );
+
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ console.log(stdout);
+ console.log(stderr);
+
+ console.log(`Assigned project ${projectId} to pod ${projectId}`);
}
app.get("/worker/:projectId", async (req, res) => {
- console.log("Received request to assign project to pod for project", req.params.projectId);
- const { projectId } = req.params;
- const project = await prismaClient.project.findUnique({
- where: {
- id: projectId,
- },
- });
+ console.log(
+ "Received request to assign project to pod for project",
+ req.params.projectId,
+ );
+ const { projectId } = req.params;
+ const project = await prismaClient.project.findUnique({
+ where: {
+ id: projectId,
+ },
+ });
- if (!project) {
- res.status(404).json({ error: "Project not found" });
- return;
- }
+ const projectType = project?.type;
- console.log("Project found, assigning to pod");
- const startTime = Date.now();
- await assignPodToProject(projectId, "REACT");
- console.log("Pod assigned, sending response");
- containerCreateBucket.observe({ type: project.type }, Date.now() - startTime);
+ if (!project) {
+ res.status(404).json({ error: "Project not found" });
+ return;
+ }
- res.json({
- sessionUrl: `https://session-${projectId}.${DOMAIN}`,
- previewUrl: `https://preview-${projectId}.${DOMAIN}`,
- workerUrl: `https://worker-${projectId}.${DOMAIN}`
- });
+ console.log("Project found, assigning to pod");
+ const startTime = Date.now();
+ //assigning project accourding to type user requested
+ await assignPodToProject(projectId, projectType! as ProjectType);
+ console.log("Pod assigned, sending response");
+ containerCreateBucket.observe({ type: project.type }, Date.now() - startTime);
+
+ res.json({
+ sessionUrl: `https://session-${projectId}.${DOMAIN}`,
+ previewUrl: `https://preview-${projectId}.${DOMAIN}`,
+ workerUrl: `https://worker-${projectId}.${DOMAIN}`,
+ });
});
app.get("/metrics", async (req, res) => {
- res.setHeader('Content-Type', promClient.register.contentType);
- res.end(await promClient.register.metrics());
+ res.setHeader("Content-Type", promClient.register.contentType);
+ res.end(await promClient.register.metrics());
});
app.listen(7001, () => {
- console.log("Server is running on port 7001");
+ console.log("Server is running on port 7001");
});
diff --git a/mobile-magic/apps/k8s-orchestrator/redis.ts b/mobile-magic/apps/k8s-orchestrator/redis.ts
index f04173d..66be1fa 100644
--- a/mobile-magic/apps/k8s-orchestrator/redis.ts
+++ b/mobile-magic/apps/k8s-orchestrator/redis.ts
@@ -6,21 +6,20 @@ export const redisClient = createClient({
redisClient.connect();
export async function addNewPod(pod: string) {
- // add expiry of 5 minutes
- await redisClient.hSet("POD_MAPPING", pod, "empty");
- await redisClient.expire("POD_MAPPING", 300); // expire after 5 minutes
+ // add expiry of 5 minutes
+ await redisClient.hSet("POD_MAPPING", pod, "empty");
+ await redisClient.expire("POD_MAPPING", 300); // expire after 5 minutes
}
export async function removePod(pod: string) {
- await redisClient.hDel("POD_MAPPING", pod);
+ await redisClient.hDel("POD_MAPPING", pod);
}
export function getAllPods() {
- return redisClient.hGetAll("POD_MAPPING");
+ return redisClient.hGetAll("POD_MAPPING");
}
export async function addProjectToPod(projectId: string, pod: string) {
- await redisClient.hSet("POD_MAPPING", pod, projectId);
- await redisClient.expire("POD_MAPPING", 300); // expire after 5 minutes
+ await redisClient.hSet("POD_MAPPING", pod, projectId);
+ await redisClient.expire("POD_MAPPING", 300); // expire after 5 minutes
}
-
diff --git a/mobile-magic/apps/primary-backend/index.ts b/mobile-magic/apps/primary-backend/index.ts
index d33ba1b..d0f5b05 100644
--- a/mobile-magic/apps/primary-backend/index.ts
+++ b/mobile-magic/apps/primary-backend/index.ts
@@ -2,18 +2,19 @@ import { prismaClient } from "db/client";
import express from "express";
import cors from "cors";
import { authMiddleware } from "common/middleware";
-import promMid from 'express-prometheus-middleware'
+import promMid from "express-prometheus-middleware";
const app = express();
-app.use(promMid({
- metricsPath: '/metrics',
- collectDefaultMetrics: true,
- requestDurationBuckets: [0.1, 0.5, 1, 1.5],
- requestLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
- responseLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
-}));
-
+app.use(
+ promMid({
+ metricsPath: "/metrics",
+ collectDefaultMetrics: true,
+ requestDurationBuckets: [0.1, 0.5, 1, 1.5],
+ requestLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
+ responseLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
+ }),
+);
app.use(express.json());
app.use(cors());
@@ -31,9 +32,11 @@ app.post("/project", authMiddleware, async (req, res) => {
app.get("/projects", authMiddleware, async (req, res) => {
const userId = req.userId!;
+ console.log("userId: ", userId);
const projects = await prismaClient.project.findMany({
where: { userId },
});
+ console.log("projects: ", projects);
res.json({ projects });
});
@@ -52,4 +55,4 @@ app.get("/prompts/:projectId", authMiddleware, async (req, res) => {
app.listen(9090, () => {
console.log("Server is running on port 9090");
-});
\ No newline at end of file
+});
diff --git a/mobile-magic/bun.lock b/mobile-magic/bun.lock
index c3cfc78..6ced5f3 100644
--- a/mobile-magic/bun.lock
+++ b/mobile-magic/bun.lock
@@ -2122,7 +2122,7 @@
"jsonwebtoken/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
- "k8s-orchestrator/@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
+ "k8s-orchestrator/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
"log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
@@ -2146,7 +2146,7 @@
"postcss/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
- "primary-backend/@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
+ "primary-backend/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
@@ -2182,9 +2182,9 @@
"use-sidecar/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
- "worker/@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
+ "worker/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
- "ws-relayer/@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
+ "ws-relayer/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
"@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
@@ -2216,7 +2216,7 @@
"inquirer/ora/log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
- "k8s-orchestrator/@types/bun/bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
+ "k8s-orchestrator/@types/bun/bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
"log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
@@ -2230,7 +2230,7 @@
"node-plop/inquirer/rxjs": ["rxjs@6.6.7", "", { "dependencies": { "tslib": "^1.9.0" } }, "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="],
- "primary-backend/@types/bun/bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
+ "primary-backend/@types/bun/bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
"send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
@@ -2238,16 +2238,14 @@
"snakecase-keys/snake-case/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
- "worker/@types/bun/bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
+ "worker/@types/bun/bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
- "ws-relayer/@types/bun/bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
+ "ws-relayer/@types/bun/bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
- "k8s-orchestrator/@types/bun/bun-types/@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
-
"log-symbols/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
"log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
@@ -2256,14 +2254,8 @@
"node-plop/inquirer/rxjs/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
- "primary-backend/@types/bun/bun-types/@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
-
"snakecase-keys/snake-case/dot-case/no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="],
- "worker/@types/bun/bun-types/@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
-
- "ws-relayer/@types/bun/bun-types/@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
-
"log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
"minizlib/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
diff --git a/mobile-magic/docker/Dockerfile.code-server-nextjs b/mobile-magic/docker/Dockerfile.code-server-nextjs
new file mode 100644
index 0000000..bcf2cc4
--- /dev/null
+++ b/mobile-magic/docker/Dockerfile.code-server-nextjs
@@ -0,0 +1,32 @@
+FROM codercom/code-server:4.96.4
+
+USER root
+RUN apt-get update \
+ && apt-get install -y curl \
+ && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
+ && apt-get install -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+USER coder
+EXPOSE 8080
+
+# Clone repo and copy Next.js template
+RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
+ && cp -r /tmp/bolty-worker/nextjs-base-app /app \
+ && rm -rf /tmp/bolty-worker
+
+
+WORKDIR /app
+# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
+
+
+RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix \
+ && code-server --install-extension bolty-listener-0.0.1.vsix \
+ && rm bolty-listener-0.0.1.vsix
+
+
+RUN mkdir -p /home/coder/.local/share/code-server/User \
+ && echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+
+CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-react b/mobile-magic/docker/Dockerfile.code-server-react
new file mode 100644
index 0000000..eb4423f
--- /dev/null
+++ b/mobile-magic/docker/Dockerfile.code-server-react
@@ -0,0 +1,40 @@
+FROM codercom/code-server:4.96.4
+
+USER root
+RUN apt-get update \
+ && apt-get install -y curl \
+ && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
+ && apt-get install -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+# Revert to the code-server default user
+USER coder
+# Expose code-server's default port
+EXPOSE 8080
+
+RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker
+RUN cp -r /tmp/bolty-worker/react-base-app /tmp/react-app
+
+
+RUN cd /tmp
+WORKDIR /app
+# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
+
+WORKDIR /tmp
+
+RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix
+RUN code-server --install-extension bolty-listener-0.0.1.vsix
+
+RUN sudo chown -R coder /tmp/bolty-worker
+RUN sudo chown -R coder /tmp/react-app
+RUN sudo chown -R coder /app
+
+RUN rm -rf /tmp/bolty-worker
+
+# Set default theme to dark
+RUN mkdir -p /home/coder/.local/share/code-server/User
+RUN echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+
+# Start code-server on container launch
+CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-react-expo b/mobile-magic/docker/Dockerfile.code-server-react-expo
new file mode 100644
index 0000000..9ff9f78
--- /dev/null
+++ b/mobile-magic/docker/Dockerfile.code-server-react-expo
@@ -0,0 +1,32 @@
+FROM codercom/code-server:4.96.4
+
+USER root
+RUN apt-get update \
+ && apt-get install -y curl \
+ && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
+ && apt-get install -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+USER coder
+EXPOSE 8080
+
+# Clone repo and copy React Native template
+RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
+ && cp -r /tmp/bolty-worker/expo-base-app /app \
+ && rm -rf /tmp/bolty-worker
+
+
+WORKDIR /app
+# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
+
+
+RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix \
+ && code-server --install-extension bolty-listener-0.0.1.vsix \
+ && rm bolty-listener-0.0.1.vsix
+
+
+RUN mkdir -p /home/coder/.local/share/code-server/User \
+ && echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+
+CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-rust-backend b/mobile-magic/docker/Dockerfile.code-server-rust-backend
new file mode 100644
index 0000000..0cf8a0e
--- /dev/null
+++ b/mobile-magic/docker/Dockerfile.code-server-rust-backend
@@ -0,0 +1,31 @@
+FROM codercom/code-server:4.96.4
+
+USER root
+RUN apt-get update \
+ && apt-get install -y curl \
+ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+USER coder
+EXPOSE 8080
+
+# Clone repo and copy Rust template (adjust path when available)
+RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
+ && cp -r /tmp/bolty-worker/rust-backend /app \
+ && rm -rf /tmp/bolty-worker
+
+
+WORKDIR /app
+ //working on it
+
+
+RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix \
+ && code-server --install-extension bolty-listener-0.0.1.vsix \
+ && rm bolty-listener-0.0.1.vsix
+
+
+RUN mkdir -p /home/coder/.local/share/code-server/User \
+ && echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+
+CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/packages/common/.env.example b/mobile-magic/packages/common/.env.example
new file mode 100644
index 0000000..b2c5dcf
--- /dev/null
+++ b/mobile-magic/packages/common/.env.example
@@ -0,0 +1 @@
+JWT_PUBLIC_KEY=
diff --git a/mobile-magic/packages/common/middleware.ts b/mobile-magic/packages/common/middleware.ts
index 09bd431..2818985 100644
--- a/mobile-magic/packages/common/middleware.ts
+++ b/mobile-magic/packages/common/middleware.ts
@@ -1,34 +1,41 @@
import type { NextFunction, Request, Response } from "express";
import jwt from "jsonwebtoken";
-const JWT_PUBLIC_KEY = process.env.JWT_PUBLIC_KEY ?? `-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7JkM9KqFNyC0B0ILTKJL
-vOgqXrfDqhW9rwpq5Pn2Vyhp0DdzmSGPzY+H/2EMzZzc//9b8eX6fxZIrW02uQ7o
-o1P6dv40vZab2Ie6tgpeKvSLyFcpdbZLWaDX4wH22uVnw7YH/yKdt3vEoSO+Pgev
-wIcSyh1w92x1TZ/obSTUpSJ0Ll5A4bR+WUsMqw2pxmKJR6onEoMSUAztGTTqrcdk
-32rnk/D3uFe2li5TtsL0Ytsj7CwyfpbHzpfDrqcdOHPEXptH4ALB14WvlHm0wrgw
-Aru84NfJ1dH3q/AbNdUGHbLaHJfagSwLMfF5UyxZw8+SgBa5XDUTQu3JXE9GA65Y
-DwIDAQAB
------END PUBLIC KEY-----`;
-
-export function authMiddleware(req: Request, res: Response, next: NextFunction) {
+declare global {
+ namespace Express {
+ interface Request {
+ userId?: string;
+ }
+ }
+}
+
+const JWT_PUBLIC_KEY = process.env.JWT_PUBLIC_KEY;
+
+console.log("jwtkey: ", JWT_PUBLIC_KEY);
+
+export function authMiddleware(
+ req: Request,
+ res: Response,
+ next: NextFunction,
+) {
const authHeader = req.headers.authorization; // Bearer token
const token = authHeader && authHeader.split(" ")[1];
+ console.log("token: ", token);
if (!token) {
res.status(401).json({ message: "Unauthorized" });
return;
}
- const decoded = jwt.verify(token, JWT_PUBLIC_KEY!, {
- algorithms: ["RS256"],
- });
+ const decoded = jwt.verify(token, JWT_PUBLIC_KEY!);
if (!decoded) {
res.status(401).json({ message: "Unauthorized" });
return;
}
+ console.log("decoded: ", decoded);
+
const userId = (decoded as any).sub;
if (!userId) {
diff --git a/mobile-magic/packages/common/types.d.ts b/mobile-magic/packages/common/types.d.ts
index a00caca..c10892f 100644
--- a/mobile-magic/packages/common/types.d.ts
+++ b/mobile-magic/packages/common/types.d.ts
@@ -1,7 +1,5 @@
-
declare namespace Express {
- interface Request {
- userId?: string;
- }
+ interface Request {
+ userId?: string;
}
-
\ No newline at end of file
+}
From e411c2ddcc939695f08341bd439c083c4f3ba82e Mon Sep 17 00:00:00 2001
From: pankaj <0xpankaj@gmail.com>
Date: Sun, 6 Apr 2025 19:55:21 +0545
Subject: [PATCH 3/3] added s3 and many thing
---
.../frontend/app/project/[projectId]/page.tsx | 1 +
mobile-magic/apps/k8s-orchestrator/config.ts | 4 +-
mobile-magic/apps/k8s-orchestrator/index.ts | 201 +++++++++++++-----
.../apps/k8s-orchestrator/package.json | 1 +
mobile-magic/bun.lock | 49 ++++-
...eact => Dockerfile.code-server-base-image} | 21 +-
.../docker/Dockerfile.code-server-nextjs | 32 ---
.../docker/Dockerfile.code-server-node | 52 +++++
.../docker/Dockerfile.code-server-react-expo | 32 ---
mobile-magic/packages/db/index.ts | 1 -
mobile-magic/packages/db/prisma/schema.prisma | 19 +-
11 files changed, 260 insertions(+), 153 deletions(-)
rename mobile-magic/docker/{Dockerfile.code-server-react => Dockerfile.code-server-base-image} (56%)
delete mode 100644 mobile-magic/docker/Dockerfile.code-server-nextjs
create mode 100644 mobile-magic/docker/Dockerfile.code-server-node
delete mode 100644 mobile-magic/docker/Dockerfile.code-server-react-expo
diff --git a/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx b/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
index 4a4f190..72f289c 100644
--- a/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
+++ b/mobile-magic/apps/frontend/app/project/[projectId]/page.tsx
@@ -13,6 +13,7 @@ export default async function ProjectPage({ params }: Params) {
const response = await axios.get(
`${K8S_ORCHESTRATOR_URL}/worker/${projectId}`,
);
+ console.log("response from orchestrator worker : ", response);
const { sessionUrl, previewUrl, workerUrl } = response.data;
return (
diff --git a/mobile-magic/apps/k8s-orchestrator/config.ts b/mobile-magic/apps/k8s-orchestrator/config.ts
index 42f954a..77e0d90 100644
--- a/mobile-magic/apps/k8s-orchestrator/config.ts
+++ b/mobile-magic/apps/k8s-orchestrator/config.ts
@@ -1,2 +1,2 @@
-
-export const DOMAIN = "cloud.antidevs.com";
\ No newline at end of file
+// export const DOMAIN = "cloud.antidevs.com";
+export const DOMAIN = "localhost";
diff --git a/mobile-magic/apps/k8s-orchestrator/index.ts b/mobile-magic/apps/k8s-orchestrator/index.ts
index 68dbd8d..174d2a7 100644
--- a/mobile-magic/apps/k8s-orchestrator/index.ts
+++ b/mobile-magic/apps/k8s-orchestrator/index.ts
@@ -7,6 +7,7 @@ import { Writable } from "stream";
import { DOMAIN } from "./config";
import { prismaClient } from "db/client";
import promClient from "prom-client";
+import AWS from "aws-sdk";
const containerCreateBucket = new promClient.Histogram({
name: "container_create_bucket",
@@ -18,6 +19,10 @@ const containerCreateBucket = new promClient.Histogram({
const kc = new KubeConfig();
const app = express();
+const s3 = new AWS.S3({
+ region: "",
+});
+
const PROJECT_TYPE_TO_BASE_FOLDER = {
NEXTJS: "/tmp/next-app",
REACT: "/tmp/react-app",
@@ -44,7 +49,38 @@ async function listPods(): Promise {
.map((pod) => pod.metadata?.name as string);
}
-async function createPod(name: string, projectType: ProjectType) {
+enum ProjectType {
+ REACT_NATIVE = "REACT_NATIVE",
+ REACT = "REACT",
+ NEXTJS = "NEXTJS",
+}
+
+const PROJECT_TYPE_TO_BASE_IMAGE: Record = {
+ [ProjectType.NEXTJS]: "100xdevs/code-server-nextjs:v3", //100xdevs/code-server-base:v3
+ [ProjectType.REACT]: "100xdevs/code-server-react:v3",
+ [ProjectType.REACT_NATIVE]: "100xdevs/code-server-reactnative-expo:v3",
+};
+
+const RUNTIME_TO_BASE_IMAGE: Record = {
+ nodejs: "100xdevs/code-server-nodejs:v1", // Base image with Node.js only
+ rust: "100xdevs/code-server-rust:v1", // Base image with Rust only
+ nodejs_rust: "100xdevs/code-server-nodejs-rust:v1", // Base image with Node.js and Rust
+};
+
+//determing runtime based on project type
+function getRuntimeForProjectType(projectType: ProjectType): string {
+ switch (projectType) {
+ case ProjectType.NEXTJS:
+ case ProjectType.REACT:
+ return "nodejs";
+ case ProjectType.REACT_NATIVE:
+ return "nodejs";
+ default:
+ return "nodejs"; // Default to Node.js
+ }
+}
+
+async function createPod(name: string, image: string) {
await k8sApi.createNamespacedPod({
namespace: "user-apps",
body: {
@@ -58,7 +94,7 @@ async function createPod(name: string, projectType: ProjectType) {
containers: [
{
name: "code-server",
- image: PROJECT_TYPE_TO_IMAGE[projectType],
+ image: image, //here adding dynamic image //100xdevs/code-server-base:v3
ports: [{ containerPort: 8080 }, { containerPort: 8081 }],
},
{
@@ -173,25 +209,22 @@ async function checkPodIsReady(name: string) {
}
}
-enum ProjectType {
- REACT_NATIVE = "REACT_NATIVE",
- NEXTJS = "NEXTJS",
- REACT = "REACT",
-}
-
-const PROJECT_TYPE_TO_IMAGE: Record = {
- [ProjectType.NEXTJS]: "100xdevs/code-server-nextjs:v3", //100xdevs/code-server-base:v3
- [ProjectType.REACT]: "100xdevs/code-server-react:v3",
- [ProjectType.REACT_NATIVE]: "100xdevs/code-server-react:v3",
-};
-
-async function assignPodToProject(projectId: string, projectType: ProjectType) {
+async function assignPodToProject(
+ projectId: string,
+ projectType: ProjectType,
+ isOnS3: boolean,
+) {
const pods = await listPods();
const podExists = pods.find((pod) => pod === projectId);
+
+ //determing base image
+ const image = isOnS3
+ ? RUNTIME_TO_BASE_IMAGE[getRuntimeForProjectType(projectType)]
+ : PROJECT_TYPE_TO_BASE_IMAGE[projectType];
+
if (!podExists) {
console.log("Pod does not exist, creating pod");
-
- await createPod(projectId, projectType);
+ await createPod(projectId, image);
}
console.log("Pod exists, checking if it is ready");
@@ -201,41 +234,95 @@ async function assignPodToProject(projectId: string, projectType: ProjectType) {
const exec = new k8s.Exec(kc);
let stdout = "";
let stderr = "";
- console.log(`mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`);
-
- exec.exec(
- "user-apps",
- projectId,
- "code-server",
- ["/bin/sh", "-c", `mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`],
- new Writable({
- write: (
- chunk: Buffer,
- encoding: BufferEncoding,
- callback: () => void,
- ) => {
- stdout += chunk;
- callback();
- },
- }),
- new Writable({
- write: (
- chunk: Buffer,
- encoding: BufferEncoding,
- callback: () => void,
- ) => {
- stderr += chunk;
- callback();
+
+ if (isOnS3) {
+ //pulling code from S3
+ const s3Bucket = "";
+ const s3Key = "";
+
+ const command = [
+ "/bin/sh",
+ "-c",
+ `aws s3 cp s3://${s3Bucket}/${s3Key} /tmp/code.zip && unzip /tmp/code.zip -d /app && rm /tmp/code.zip`,
+ ];
+ await new Promise((resolve, reject) => {
+ exec.exec(
+ "user-apps",
+ projectId,
+ "code-server",
+ command,
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stdout += chunk;
+ callback();
+ },
+ }),
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stderr += chunk;
+ callback();
+ },
+ }),
+ null,
+ false,
+ (status) => {
+ console.log("Exec status:", status);
+ console.log("Stdout:", stdout);
+ console.log("Stderr:", stderr);
+ if (status?.status === "Success") resolve(status);
+ else reject(new Error("Failed to pull and extract S3 code"));
+ },
+ );
+ });
+ } else {
+ console.log(`mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`);
+
+ exec.exec(
+ "user-apps",
+ projectId,
+ "code-server",
+ [
+ "/bin/sh",
+ "-c",
+ `mv ${PROJECT_TYPE_TO_BASE_FOLDER[projectType]}/* /app`,
+ ],
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stdout += chunk;
+ callback();
+ },
+ }),
+ new Writable({
+ write: (
+ chunk: Buffer,
+ encoding: BufferEncoding,
+ callback: () => void,
+ ) => {
+ stderr += chunk;
+ callback();
+ },
+ }),
+ null,
+ false,
+ (status) => {
+ console.log(status);
+ console.log(stdout);
+ console.log(stderr);
},
- }),
- null,
- false,
- (status) => {
- console.log(status);
- console.log(stdout);
- console.log(stderr);
- },
- );
+ );
+ }
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(stdout);
@@ -256,17 +343,21 @@ app.get("/worker/:projectId", async (req, res) => {
},
});
- const projectType = project?.type;
-
if (!project) {
res.status(404).json({ error: "Project not found" });
return;
}
+ const projectType = project.type as ProjectType;
+ const isOnS3 = project.onS3;
+ //if code is on s3 then we don't needed baseimage with initial code
+ // only needed baseimage with respective run time
+
console.log("Project found, assigning to pod");
const startTime = Date.now();
- //assigning project accourding to type user requested
- await assignPodToProject(projectId, projectType! as ProjectType);
+
+ await assignPodToProject(projectId, projectType, isOnS3); //argument as projectType
+
console.log("Pod assigned, sending response");
containerCreateBucket.observe({ type: project.type }, Date.now() - startTime);
diff --git a/mobile-magic/apps/k8s-orchestrator/package.json b/mobile-magic/apps/k8s-orchestrator/package.json
index 317015c..e0ca639 100644
--- a/mobile-magic/apps/k8s-orchestrator/package.json
+++ b/mobile-magic/apps/k8s-orchestrator/package.json
@@ -12,6 +12,7 @@
"@kubernetes/client-node": "^1.0.0",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
+ "aws-sdk": "^2.1692.0",
"cors": "^2.8.5",
"db": "*",
"express": "^4.21.2",
diff --git a/mobile-magic/bun.lock b/mobile-magic/bun.lock
index 6ced5f3..d13e6ab 100644
--- a/mobile-magic/bun.lock
+++ b/mobile-magic/bun.lock
@@ -56,6 +56,7 @@
"@kubernetes/client-node": "^1.0.0",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
+ "aws-sdk": "^2.1692.0",
"cors": "^2.8.5",
"db": "*",
"express": "^4.21.2",
@@ -810,6 +811,8 @@
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
+ "aws-sdk": ["aws-sdk@2.1692.0", "", { "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", "xml2js": "0.6.2" } }, "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw=="],
+
"axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="],
"axios": ["axios@1.8.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg=="],
@@ -834,7 +837,7 @@
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
- "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
+ "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
@@ -1054,6 +1057,8 @@
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
+ "events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="],
+
"execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
"express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="],
@@ -1190,7 +1195,7 @@
"iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
- "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+ "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
@@ -1214,6 +1219,8 @@
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
+ "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="],
+
"is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
@@ -1282,7 +1289,7 @@
"is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
- "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+ "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
"isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="],
@@ -1296,6 +1303,8 @@
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
+ "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="],
+
"jose": ["jose@6.0.8", "", {}, "sha512-EyUPtOKyTYq+iMOszO42eobQllaIjJnwkZ2U93aJzNyPibCy7CEvT9UQnaCVB51IAd49gbNdCew1c0LcLTCB2g=="],
"js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="],
@@ -1570,10 +1579,12 @@
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
- "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+ "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="],
"qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="],
+ "querystring": ["querystring@0.2.0", "", {}, "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="],
+
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
@@ -1640,6 +1651,8 @@
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
+ "sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="],
+
"scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
@@ -1838,6 +1851,8 @@
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+ "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="],
+
"url-value-parser": ["url-value-parser@2.2.0", "", {}, "sha512-yIQdxJpgkPamPPAPuGdS7Q548rLhny42tg8d4vyTNzFqvOnwqrgHXvgehT09U7fwrzxi3RxCiXjoNUNnNOlQ8A=="],
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
@@ -1846,11 +1861,13 @@
"use-sync-external-store": ["use-sync-external-store@1.4.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw=="],
+ "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="],
+
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
- "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
+ "uuid": ["uuid@8.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="],
"v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="],
@@ -1896,6 +1913,10 @@
"ws-relayer": ["ws-relayer@workspace:apps/ws-relayer"],
+ "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="],
+
+ "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
+
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="],
@@ -1920,6 +1941,8 @@
"@aws-sdk/client-ec2/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "@aws-sdk/client-ec2/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
+
"@aws-sdk/client-sso/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"@aws-sdk/core/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
@@ -2010,6 +2033,8 @@
"@smithy/middleware-retry/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "@smithy/middleware-retry/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
+
"@smithy/middleware-serde/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"@smithy/middleware-stack/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
@@ -2084,8 +2109,12 @@
"ast-types/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
+
"body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+ "buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+
"bun-types/@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
"eslint-config-next/@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.2.1-canary.1", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-MByTwWAK/O5IvYvgkWupgOZ15d5VzLkUFOJ9TG70qUrOaQL9hcbBhiQGs/IKTaJKm5nb7sKdayCjibWNbHLJfw=="],
@@ -2158,6 +2187,10 @@
"rxjs/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
"send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
"send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
@@ -2178,10 +2211,14 @@
"tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
+ "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
"use-callback-ref/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"use-sidecar/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+ "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
"worker/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
"ws-relayer/@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
@@ -2204,6 +2241,8 @@
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
+ "bl/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
diff --git a/mobile-magic/docker/Dockerfile.code-server-react b/mobile-magic/docker/Dockerfile.code-server-base-image
similarity index 56%
rename from mobile-magic/docker/Dockerfile.code-server-react
rename to mobile-magic/docker/Dockerfile.code-server-base-image
index eb4423f..6cd2ff4 100644
--- a/mobile-magic/docker/Dockerfile.code-server-react
+++ b/mobile-magic/docker/Dockerfile.code-server-base-image
@@ -1,5 +1,8 @@
FROM codercom/code-server:4.96.4
+# build arg for projectType
+ARG projectType
+
USER root
RUN apt-get update \
&& apt-get install -y curl \
@@ -13,28 +16,14 @@ USER coder
# Expose code-server's default port
EXPOSE 8080
-RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker
-RUN cp -r /tmp/bolty-worker/react-base-app /tmp/react-app
-
-
-RUN cd /tmp
-WORKDIR /app
-# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
-
-WORKDIR /tmp
-
-RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix
-RUN code-server --install-extension bolty-listener-0.0.1.vsix
-RUN sudo chown -R coder /tmp/bolty-worker
-RUN sudo chown -R coder /tmp/react-app
-RUN sudo chown -R coder /app
-RUN rm -rf /tmp/bolty-worker
# Set default theme to dark
RUN mkdir -p /home/coder/.local/share/code-server/User
RUN echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+WORKDIR /app
+
# Start code-server on container launch
CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-nextjs b/mobile-magic/docker/Dockerfile.code-server-nextjs
deleted file mode 100644
index bcf2cc4..0000000
--- a/mobile-magic/docker/Dockerfile.code-server-nextjs
+++ /dev/null
@@ -1,32 +0,0 @@
-FROM codercom/code-server:4.96.4
-
-USER root
-RUN apt-get update \
- && apt-get install -y curl \
- && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
- && apt-get install -y nodejs \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/*
-
-USER coder
-EXPOSE 8080
-
-# Clone repo and copy Next.js template
-RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
- && cp -r /tmp/bolty-worker/nextjs-base-app /app \
- && rm -rf /tmp/bolty-worker
-
-
-WORKDIR /app
-# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
-
-
-RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix \
- && code-server --install-extension bolty-listener-0.0.1.vsix \
- && rm bolty-listener-0.0.1.vsix
-
-
-RUN mkdir -p /home/coder/.local/share/code-server/User \
- && echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
-
-CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-node b/mobile-magic/docker/Dockerfile.code-server-node
new file mode 100644
index 0000000..b6e4731
--- /dev/null
+++ b/mobile-magic/docker/Dockerfile.code-server-node
@@ -0,0 +1,52 @@
+FROM codercom/code-server:4.96.4
+
+# build arg for projectType
+ARG projectType
+
+USER root
+RUN apt-get update \
+ && apt-get install -y curl \
+ && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
+ && apt-get install -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+# Revert to the code-server default user
+USER coder
+# Expose code-server's default port
+EXPOSE 8080
+
+# Cloning the repository and copy only the specified project based on projectType
+RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
+ && if [ "$projectType" = "mobile" ]; then \
+ cp -r /tmp/bolty-worker/expo-base-app /app && rm -rf /tmp/bolty-worker/* && mv /app /tmp/bolty-worker/expo-base-app; \
+ elif [ "$projectType" = "nextjs" ]; then \
+ cp -r /tmp/bolty-worker/nextjs-base-app /app && rm -rf /tmp/bolty-worker/* && mv /app /tmp/bolty-worker/nextjs-base-app; \
+ elif [ "$projectType" = "react" ]; then \
+ cp -r /tmp/bolty-worker/react-base-app /app && rm -rf /tmp/bolty-worker/* && mv /app /tmp/bolty-worker/react-base-app; \
+ else \
+ echo "Invalid projectType."; exit 1; \
+ fi \
+ && mv /tmp/bolty-worker/* /app \
+ && rm -rf /tmp/bolty-worker
+
+# install dependencies only for the selected project
+WORKDIR /app
+RUN npm install
+
+# downloading and installing extension]
+RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix
+RUN code-server --install-extension bolty-listener-0.0.1.vsix
+
+USER root
+RUN chown -R coder /app
+USER coder
+
+
+# Set default theme to dark
+RUN mkdir -p /home/coder/.local/share/code-server/User
+RUN echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
+
+
+# Start code-server on container launch
+CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/docker/Dockerfile.code-server-react-expo b/mobile-magic/docker/Dockerfile.code-server-react-expo
deleted file mode 100644
index 9ff9f78..0000000
--- a/mobile-magic/docker/Dockerfile.code-server-react-expo
+++ /dev/null
@@ -1,32 +0,0 @@
-FROM codercom/code-server:4.96.4
-
-USER root
-RUN apt-get update \
- && apt-get install -y curl \
- && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
- && apt-get install -y nodejs \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/*
-
-USER coder
-EXPOSE 8080
-
-# Clone repo and copy React Native template
-RUN git clone https://github.com/code100x/mobile-magic.git /tmp/bolty-worker \
- && cp -r /tmp/bolty-worker/expo-base-app /app \
- && rm -rf /tmp/bolty-worker
-
-
-WORKDIR /app
-# RUN npm install //still update on dependency will rebuild so no benefit of pre-build just larger image size
-
-
-RUN wget https://github.com/code100x/mobile-magic/raw/refs/heads/main/ext/bolty-listener-0.0.1.vsix \
- && code-server --install-extension bolty-listener-0.0.1.vsix \
- && rm bolty-listener-0.0.1.vsix
-
-
-RUN mkdir -p /home/coder/.local/share/code-server/User \
- && echo '{"workbench.colorTheme": "Dark+", "workbench.preferredDarkColorTheme": "Dark+"}' > /home/coder/.local/share/code-server/User/settings.json
-
-CMD ["code-server", "--auth", "none", "--bind-addr", "0.0.0.0:8080", "--disable-telemetry", "/app"]
diff --git a/mobile-magic/packages/db/index.ts b/mobile-magic/packages/db/index.ts
index 82e3022..11bbdfe 100644
--- a/mobile-magic/packages/db/index.ts
+++ b/mobile-magic/packages/db/index.ts
@@ -1,4 +1,3 @@
import { PrismaClient } from "@prisma/client";
export const prismaClient = new PrismaClient();
-
diff --git a/mobile-magic/packages/db/prisma/schema.prisma b/mobile-magic/packages/db/prisma/schema.prisma
index c8f151b..8f32458 100644
--- a/mobile-magic/packages/db/prisma/schema.prisma
+++ b/mobile-magic/packages/db/prisma/schema.prisma
@@ -21,13 +21,14 @@ model User {
}
model Project {
- id String @id @default(uuid())
+ id String @id @default(uuid())
description String?
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
prompt Prompt[]
actions Action[]
type ProjectType @default(NEXTJS)
+ onS3 Boolean @default(false)
userId String
}
@@ -38,14 +39,14 @@ enum ProjectType {
}
model Prompt {
- id String @id @default(uuid())
+ id String @id @default(uuid())
content String
type PromptType
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- project Project @relation(fields: [projectId], references: [id])
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ project Project @relation(fields: [projectId], references: [id])
projectId String
- actions Action[]
+ actions Action[]
}
model Action {
@@ -63,5 +64,3 @@ enum PromptType {
USER
SYSTEM
}
-
-