Skip to content

Commit

Permalink
Code Refactored and modularized (DiceDB#9)
Browse files Browse the repository at this point in the history
Co-authored-by: root <root@N3XT>
Co-authored-by: pshubham <[email protected]>
  • Loading branch information
3 people authored Oct 1, 2024
1 parent f4055a7 commit bd8499c
Show file tree
Hide file tree
Showing 9 changed files with 810 additions and 45 deletions.
681 changes: 678 additions & 3 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"autoprefixer": "^10.4.20",
"lucide-react": "^0.446.0",
"next": "14.2.13",
"package.json": "^2.0.1",
"react": "^18",
"react-dom": "^18",
"react-terminal-ui": "^1.3.0"
Expand Down
39 changes: 6 additions & 33 deletions src/components/CLI/CLI.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// src/components/CLI/CLI.tsx

'use client';

import React, { useEffect, useRef, useState } from 'react';
import { handleCommand } from '@/shared/utils/cliUtils';

interface CliProps {
decreaseCommandsLeft: () => void;
Expand All @@ -11,40 +14,10 @@ export default function Cli({ decreaseCommandsLeft }: CliProps) {
const [output, setOutput] = useState<string[]>([]);
const terminalRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [store, setStore] = useState<{ [key: string]: string }>({});

const handleCommand = (e: React.KeyboardEvent<HTMLInputElement>) => {
const handleCommandWrapper = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
const newOutput = `dice ~$ ${command}`;
let result = "";
const [cmd, ...args] = command.split(" ");

switch (cmd.toUpperCase()) {
case "GET":
result = store[args[0]] || "(nil)";
break;
case "SET":
if (args.length === 2) {
const [key, value] = args;
setStore((prevStore) => ({ ...prevStore, [key]: value }));
result = "OK";
} else {
result = "Invalid command. Usage: SET key value";
}
break;
case "CLEAR":
setOutput([]);
setCommand("");
return;
case "":
setCommand("");
return;
default:
setCommand("");
return;
}

setOutput((prevOutput) => [...prevOutput, newOutput, result]);
handleCommand({ command, setOutput });
setCommand("");
decreaseCommandsLeft();
}
Expand All @@ -68,7 +41,7 @@ export default function Cli({ decreaseCommandsLeft }: CliProps) {

const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleCommand(e);
handleCommandWrapper(e);
}
};

Expand Down
9 changes: 3 additions & 6 deletions src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// src/app/Playground.tsx

"use client";

import Image from "next/image";
import React, { useState, useEffect } from "react";
import Cli from "@/components/CLI/CLI";
import SearchBox from "@/components/Search/SearchBox";
import { Dice1, Dice3, Dice5 } from "lucide-react";
import { formatTime } from "@/shared/utils/commonUtils";

export default function Playground() {
const [search, setSearch] = useState("");
Expand All @@ -19,12 +22,6 @@ export default function Playground() {
return () => clearInterval(timer);
}, []);

const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds < 10 ? "0" : ""}${remainingSeconds}`;
};

const decreaseCommandsLeft = () => {
setCommandsLeft((prev) => (prev > 0 ? prev - 1 : 0));
};
Expand Down
33 changes: 32 additions & 1 deletion src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
// This is likely to hold api fucntion calls
// src/lib/api.ts
import { CLI_COMMAND_URL } from "@/shared/constants/apiEndpoints";

export const executeCLICommandOnServer = async (cmd: string, cmdOptions: object): Promise<string> => {
try {
const response = await fetch(`${CLI_COMMAND_URL}/${cmd}`, {
method: 'POST',
body: JSON.stringify(cmdOptions),
headers: {
'Content-Type': 'application/json',
},
});

// TODO: This needs to be looked at
const data = await response.json();
if (Object.prototype.hasOwnProperty.call(data, 'data')) {
return data.data;
}
else if (Object.prototype.hasOwnProperty.call(data, 'error')) {
return data.error;
}

if (!response.ok) {
throw new Error('Network response was not ok');
}

return data;
} catch (error: unknown) {
console.error('Error executing command:', error);
return `Error: ${error}`;
}
};
3 changes: 2 additions & 1 deletion src/shared/constants/apiEndpoints.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
// This folder will contain or hold constants. For example in this particular file we can store the api endpoints as constants
// This folder will contain or hold constants. For example in this particular file we can store the api endpoints as constants
export const CLI_COMMAND_URL="http://localhost:8080/cli"
77 changes: 77 additions & 0 deletions src/shared/utils/cliUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// src/shared/utils/cliUtils.ts

import { executeCLICommandOnServer } from "@/lib/api";
import { CommandHandler } from "@/types";

export const handleCommand = async ({
command,
setOutput,
}: CommandHandler) => {
const newOutput = `dice > ${command}`;
let result: string;

const [cmd, ...args] = command.split(" ");

switch (cmd.toUpperCase()) {
case "GET":
if (args.length < 1) {
result = "Invalid command. Usage: GET key";
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
return;
}

try {
const [key] = args;
const cmdOptions = { key: key };
result = await executeCLICommandOnServer(cmd, cmdOptions);
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
} catch (error: unknown) {
console.error('Error executing command:', error);
result = 'Error executing command';
return `Error: ${String(error)}`;
}
break;

case "SET":
if (args.length === 2) {
const [key, value] = args;
try {
const cmdOptions = { key: key, value: value };
result = await executeCLICommandOnServer(cmd, cmdOptions);
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
} catch (error: unknown) {
console.error('Error executing command:', error);
result = 'Error executing command';
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
return `Error: ${String((error as Error).message || error)}`;
}
} else {
result = "Invalid command. Usage: SET key value";
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
}
break;

case "DEL":
if (args.length <= 1) {
const [keys] = args;
try {
const cmdOptions = { keys: [keys]};
result = await executeCLICommandOnServer(cmd, cmdOptions);
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
} catch (error: unknown) {
console.error('Error executing command:', error);
result = 'Error executing command';
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
return `Error: ${String((error as Error).message || error)}`;
}
} else {
result = "Invalid command. Usage: DEL key1 key2 ....";
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
}
break;

default:
result = `Unknown command: ${cmd}`;
setOutput((prevOutput) => [...prevOutput, newOutput, result]);
}
};
5 changes: 5 additions & 0 deletions src/shared/utils/commonUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds < 10 ? "0" : ""}${remainingSeconds}`;
};
7 changes: 6 additions & 1 deletion src/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
// This file will contain the type definitions
import * as React from 'react';

export interface CommandHandler {
command: string;
setOutput: React.Dispatch<React.SetStateAction<string[]>>;
}

0 comments on commit bd8499c

Please sign in to comment.