First Commit
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import { Box, Card, Heading } from "@radix-ui/themes";
|
||||
|
||||
export default function Main() {
|
||||
return (
|
||||
<Card>
|
||||
<Box>
|
||||
<Heading size={"5"}>Home</Heading>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Box, Card, Heading } from "@radix-ui/themes";
|
||||
|
||||
export default function Main() {
|
||||
return (
|
||||
<Card className="max-w-4xl w-full xl:p-8">
|
||||
<Box>
|
||||
<Heading size={"5"}>Login</Heading>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import grabTurboCiConfig from "@/utils/grab-turboci-config";
|
||||
|
||||
export default async function cronCheckServices() {
|
||||
const config = grabTurboCiConfig();
|
||||
|
||||
for (let i = 0; i < config.services.length; i++) {
|
||||
const service = config.services[i];
|
||||
|
||||
if (!service.servers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let srv = 0; srv < service.servers.length; srv++) {
|
||||
const server = service.servers[srv];
|
||||
|
||||
console.log("service", service.service_name);
|
||||
console.log(server.private_ip);
|
||||
|
||||
if (service.healthcheck) {
|
||||
let cmd = ``;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { AppData } from "@/data/app-data";
|
||||
import cronCheckServices from "./functions/check-services";
|
||||
|
||||
while (true) {
|
||||
console.log(`Running Cron Services ...`);
|
||||
|
||||
await cronCheckServices();
|
||||
|
||||
await Bun.sleep(AppData["CronInterval"]);
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -0,0 +1,4 @@
|
||||
export const AppData = {
|
||||
TerminalBinName: "ttyd",
|
||||
CronInterval: 30000,
|
||||
} as const;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { BUN_SQLITE_DatabaseSchemaType } from "@moduletrace/bun-sqlite/dist/types";
|
||||
|
||||
const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
dbName: "test-db",
|
||||
tables: [
|
||||
{
|
||||
tableName: "users",
|
||||
fields: [
|
||||
{
|
||||
fieldName: "first_name",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
{
|
||||
fieldName: "last_name",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
{
|
||||
fieldName: "email",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
{
|
||||
fieldName: "image",
|
||||
dataType: "TEXT",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default schema;
|
||||
@@ -0,0 +1,24 @@
|
||||
export const BunSQLiteTables = [
|
||||
"users",
|
||||
] as const
|
||||
|
||||
export type BUN_SQLITE_TEST_DB_USERS = {
|
||||
/**
|
||||
* The unique identifier of the record.
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
* The time when the record was created. (Unix Timestamp)
|
||||
*/
|
||||
created_at?: number;
|
||||
/**
|
||||
* The time when the record was updated. (Unix Timestamp)
|
||||
*/
|
||||
updated_at?: number;
|
||||
first_name?: string;
|
||||
last_name?: string;
|
||||
email?: string;
|
||||
image?: string;
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_TEST_DB_ALL_TYPEDEFS = BUN_SQLITE_TEST_DB_USERS
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Box, Container, Section } from "@radix-ui/themes";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
type Props = PropsWithChildren & {};
|
||||
|
||||
export default function Layout({ children }: Props) {
|
||||
return (
|
||||
<Section className="w-screen h-screen flex flex-col items-center justify-center">
|
||||
<Container className="flex flex-col items-center justify-center">
|
||||
<Box>{children}</Box>
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import "@/styles/globals.css";
|
||||
import "@radix-ui/themes/styles.css";
|
||||
|
||||
import type { AppProps } from "next/app";
|
||||
import { Theme } from "@radix-ui/themes";
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<Theme>
|
||||
<Component {...pageProps} />
|
||||
</Theme>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Html, Head, Main, NextScript } from "next/document";
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body className="antialiased">
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type Data = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>,
|
||||
) {
|
||||
res.status(200).json({ name: "John Doe" });
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import Main from "@/components/pages/auth/login";
|
||||
import Layout from "@/layouts/login";
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<Layout>
|
||||
<Main />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import Main from "@/components/pages/home";
|
||||
import Layout from "@/layouts/login";
|
||||
import { Heading } from "@radix-ui/themes";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Layout>
|
||||
<Main />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
export const CloudProviders = [
|
||||
{
|
||||
title: "Hetzner",
|
||||
value: "hetzner",
|
||||
},
|
||||
{
|
||||
title: "Amazon Web Services",
|
||||
value: "aws",
|
||||
},
|
||||
{
|
||||
title: "Google Cloud Platform",
|
||||
value: "gcp",
|
||||
},
|
||||
{
|
||||
title: "Microsoft Azure",
|
||||
value: "azure",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type ParsedDeploymentServiceConfig = TCIConfigServiceConfig & {
|
||||
service_name: string;
|
||||
parent_service_name?: string;
|
||||
servers?: NormalizedServerObject[];
|
||||
};
|
||||
|
||||
export type NormalizedServerObject = {
|
||||
public_ip?: string;
|
||||
private_ip?: string;
|
||||
};
|
||||
|
||||
export type TCIConfig = {
|
||||
deployment_name: string;
|
||||
duplicate_deployment_name?: string;
|
||||
description?: string;
|
||||
location?: string;
|
||||
availability_zone?: string;
|
||||
provider: (typeof CloudProviders)[number]["value"];
|
||||
services: TCIConfigService;
|
||||
env?: { [k: string]: string };
|
||||
env_file?: string;
|
||||
pre_deployment?: TCIRunObj;
|
||||
};
|
||||
|
||||
export type TCIGlobalConfig = Omit<TCIConfig, "services"> & {
|
||||
services: ParsedDeploymentServiceConfig[];
|
||||
relay_server_ip?: string;
|
||||
};
|
||||
|
||||
export type TCIConfigService = {
|
||||
[k: string]: TCIConfigServiceConfig;
|
||||
};
|
||||
|
||||
export const TCIServiceTypes = [
|
||||
{
|
||||
title: "Default Service",
|
||||
value: "default",
|
||||
},
|
||||
{
|
||||
title: "Docker",
|
||||
value: "docker",
|
||||
},
|
||||
{
|
||||
title: "Load Balancer",
|
||||
value: "load_balancer",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const TCIServiceOS = [
|
||||
{
|
||||
title: "Debian 12 Bookworm",
|
||||
value: "debian_12",
|
||||
},
|
||||
{
|
||||
title: "Debian 13 Buster",
|
||||
value: "debian_13",
|
||||
},
|
||||
{
|
||||
title: "Ubuntu 23.0.4",
|
||||
value: "ubuntu_23_0_4",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const TCIServiceDependecyTypes = [
|
||||
{
|
||||
title: "Debian APT",
|
||||
value: "apt",
|
||||
},
|
||||
{
|
||||
title: "Turbo CI",
|
||||
value: "turboci",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type TCIConfigServiceConfig = {
|
||||
type?: (typeof TCIServiceTypes)[number]["value"];
|
||||
os?: string;
|
||||
server_type?: string;
|
||||
enable_public_ip?: boolean;
|
||||
instances?: number;
|
||||
clusters?: number;
|
||||
dir_mappings?: TCIConfigServiceConfigDirMApping[];
|
||||
dependencies?: {
|
||||
[k in (typeof TCIServiceDependecyTypes)[number]["value"]]?: string[];
|
||||
};
|
||||
env?: { [k: string]: string };
|
||||
env_file?: string;
|
||||
target_services?: TCIConfigServiceConfigLBTarget[];
|
||||
run?: TCIConfigServiceConfigRun;
|
||||
ssl?: TCIConfigServiceSSL;
|
||||
duplicate_service_name?: string;
|
||||
healthcheck?: TCIConfigServiceHealthcheck;
|
||||
/**
|
||||
* Commoands to Run on first run
|
||||
*/
|
||||
init?: string[];
|
||||
};
|
||||
|
||||
export type TCIConfigServiceHealthcheck = {
|
||||
cmd: string;
|
||||
test: string;
|
||||
};
|
||||
|
||||
export type TCIConfigServiceDomain = {
|
||||
domain_name: string;
|
||||
};
|
||||
|
||||
export type TCIConfigServiceSSL = {
|
||||
email: string;
|
||||
};
|
||||
|
||||
export type TCIConfigServiceConfigLBTarget = {
|
||||
service_name: string;
|
||||
port: number;
|
||||
weight?: number;
|
||||
backup?: boolean;
|
||||
domains?: (string | TCIConfigServiceDomain)[];
|
||||
};
|
||||
|
||||
export type TCIConfigServiceConfigRun = {
|
||||
preflight?: TCIRunObj;
|
||||
start?: TCIRunObj;
|
||||
postflight?: TCIRunObj;
|
||||
work_dir?: string;
|
||||
};
|
||||
|
||||
export type TCIRunObj = {
|
||||
cmds?: string[];
|
||||
work_dir?: string;
|
||||
file?: string;
|
||||
};
|
||||
|
||||
export type TCIConfigServiceConfigDirMApping = {
|
||||
src: string;
|
||||
dst: string;
|
||||
ignore_file?: string;
|
||||
ignore_patterns?: string[];
|
||||
use_gitignore?: boolean;
|
||||
relay_ignore?: string[];
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import { exec, execSync, type ExecSyncOptions } from "child_process";
|
||||
import grabSSHPrefix from "./grab-ssh-prefix";
|
||||
import _ from "lodash";
|
||||
|
||||
type Param = {
|
||||
cmd: string | string[];
|
||||
debug?: boolean;
|
||||
ip: string;
|
||||
user?: string;
|
||||
options?: ExecSyncOptions;
|
||||
detached?: boolean;
|
||||
return_cmd_only?: boolean;
|
||||
cmd_prefix?: string;
|
||||
};
|
||||
|
||||
export default async function execSSH(
|
||||
params: Param,
|
||||
): Promise<string | undefined> {
|
||||
const {
|
||||
cmd,
|
||||
debug,
|
||||
ip,
|
||||
user = "root",
|
||||
options,
|
||||
detached,
|
||||
return_cmd_only,
|
||||
cmd_prefix,
|
||||
} = params;
|
||||
|
||||
try {
|
||||
let cmdPrefix = cmd_prefix || grabSSHPrefix();
|
||||
|
||||
let finalCmd = `${cmdPrefix}`;
|
||||
finalCmd += ` ${user}@${ip}`;
|
||||
|
||||
const parsedCmd =
|
||||
typeof cmd == "string"
|
||||
? cmd
|
||||
: Array.isArray(cmd)
|
||||
? cmd.join("\n")
|
||||
: undefined;
|
||||
|
||||
finalCmd += ` << 'TURBOCIEXEC' \n${parsedCmd}\nTURBOCIEXEC`;
|
||||
|
||||
if (debug) {
|
||||
console.log("finalCmd", finalCmd);
|
||||
}
|
||||
|
||||
if (return_cmd_only) {
|
||||
return finalCmd;
|
||||
}
|
||||
|
||||
const str = detached
|
||||
? ""
|
||||
: execSync(finalCmd, {
|
||||
stdio: "pipe",
|
||||
...options,
|
||||
encoding: "utf-8",
|
||||
});
|
||||
|
||||
if (debug) {
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
if (detached) {
|
||||
exec(finalCmd);
|
||||
}
|
||||
|
||||
return str.trim();
|
||||
} catch (error: any) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import path from "path";
|
||||
|
||||
export default function grabDirNames() {
|
||||
const APP_DIR = path.resolve(__dirname, "../../");
|
||||
const TURBOCI_DIR = `/root/.turboci`;
|
||||
const TURBOCI_CONFIG_DIR = path.join(TURBOCI_DIR, ".config");
|
||||
const TURBOCI_CONFIG_JSON_FILE = path.join(
|
||||
TURBOCI_CONFIG_DIR,
|
||||
"turboci.json",
|
||||
);
|
||||
|
||||
const TURBOCI_SSH_DIR = path.join(TURBOCI_DIR, ".ssh");
|
||||
const TURBOCI_SSH_KEY_FILE = path.join(TURBOCI_SSH_DIR, "turboci");
|
||||
|
||||
return {
|
||||
APP_DIR,
|
||||
TURBOCI_CONFIG_DIR,
|
||||
TURBOCI_CONFIG_JSON_FILE,
|
||||
TURBOCI_DIR,
|
||||
TURBOCI_SSH_DIR,
|
||||
TURBOCI_SSH_KEY_FILE,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import grabDirNames from "./grab-dir-names";
|
||||
|
||||
type Params = {};
|
||||
|
||||
export default function grabSSHPrefix(params?: Params) {
|
||||
const { TURBOCI_SSH_KEY_FILE } = grabDirNames();
|
||||
return `ssh -i ${TURBOCI_SSH_KEY_FILE} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -C -c aes128-ctr`;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
type Params = {
|
||||
cmd: string;
|
||||
cwd?: string;
|
||||
flags?: string[];
|
||||
};
|
||||
|
||||
export default function grabTtydCmd({ cmd: ttydCmd, cwd, flags }: Params) {
|
||||
const port = 8080;
|
||||
|
||||
let cmd = ``;
|
||||
cmd += `${AppData["TerminalBinName"]}`;
|
||||
cmd += ` --writable --max-clients 1`;
|
||||
cmd += ` --client-option 'theme={"background":"#0c0e11"}'`;
|
||||
cmd += ` --client-option fontSize=14`;
|
||||
|
||||
if (cwd) {
|
||||
cmd += ` --cwd ${cwd}`;
|
||||
}
|
||||
|
||||
if (flags?.[0]) {
|
||||
for (let i = 0; i < flags.length; i++) {
|
||||
const flag = flags[i];
|
||||
cmd += ` ${flag}`;
|
||||
}
|
||||
}
|
||||
|
||||
cmd += ` -p ${port}`;
|
||||
cmd += ` ${ttydCmd}`;
|
||||
|
||||
return { cmd, port };
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import fs from "fs";
|
||||
import grabDirNames from "./grab-dir-names";
|
||||
import { TCIGlobalConfig } from "@/types";
|
||||
|
||||
export default function grabTurboCiConfig() {
|
||||
const { TURBOCI_CONFIG_JSON_FILE } = grabDirNames();
|
||||
|
||||
if (!fs.existsSync(TURBOCI_CONFIG_JSON_FILE)) {
|
||||
throw new Error(`TurboCI config JSON file not found!`);
|
||||
}
|
||||
|
||||
const config = JSON.parse(
|
||||
fs.readFileSync(TURBOCI_CONFIG_JSON_FILE, "utf-8"),
|
||||
) as TCIGlobalConfig;
|
||||
|
||||
return config;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import datasquirel from "@moduletrace/datasquirel";
|
||||
import { NextApiRequest } from "next";
|
||||
|
||||
type Params = {
|
||||
req: NextApiRequest;
|
||||
};
|
||||
|
||||
export default async function userAuth({ req }: Params) {
|
||||
const auth = datasquirel.user.auth.auth({ req });
|
||||
const user = auth.payload;
|
||||
return { user };
|
||||
}
|
||||
Reference in New Issue
Block a user