Publish Progress (#1)

Reviewed-on: #1
This commit is contained in:
Hyperling 2025-01-04 09:00:19 -07:00
parent d69a6b2e71
commit 9169b06caf
15 changed files with 3907 additions and 0 deletions

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# my additions
logs
dist
db/main
*deleteme*
*fortesting*

View File

@ -1,2 +1,43 @@
# food_diary
Food Diary UI
## What
Simple application for entering food choices and whether they caused any issues
such as headaches, migraines, upset digestion, etc.
## Installation / How To Run
This project assumes an apt-based OS. It is currently being developed on Ubuntu.
Clone the project:
`git clone https://github.com/Hyperling/food_diary food_diary_app`
Move into the directory:
`cd food_diary_app`
Run the project:
`./run.sh`
### Different Environments
The project can also safely run the project from another directory so that it's
safe to be called from things like cron or if you're feeling lazy and don't want
to move your terminal location.
Such as something like this for doing development testing:
`bash ~/Projects/git/food_diary_app`
Or maybe something like these in a more production-like environment:
`bash /opt/FoodDiary/run.sh`
`bash /usr/local/src/food_diary_app/run.sh`
#### Caveat
These create `package*.json` files in the local directory which will need
cleaned or ignored. The `node_modules` folder is moved to the project directory.
## Testing
`test.sh` has been provided for showing how to interact with the APIs.

8
db/DDL/journal.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE TABLE journal (
user_id INTEGER NOT NULL,
cal_date TEXT NOT NULL,
meal TEXT NOT NULL,
food TEXT NOT NULL,
caused_issue INTEGER NOT NULL,
comments TEXT
) STRICT;

3442
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

26
package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "food_diary",
"version": "0.0.1",
"description": "Food Diary UI for researching dietary sensitivities.",
"repository": {
"type": "git",
"url": "git+https://github.com/Hyperling/food_diary.git"
},
"author": "Hyperling",
"license": "MIT",
"bugs": {
"url": "https://github.com/Hyperling/food_diary/issues"
},
"homepage": "https://github.com/Hyperling/food_diary#readme",
"dependencies": {
"@types/node": "^18.14.6",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"package.json": "^2.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sqlite3": "^5.1.4",
"typescript": "^4.9.5"
},
"removedDependencies": {}
}

80
run.sh Executable file
View File

@ -0,0 +1,80 @@
#!/bin/bash
# Date: 2023-03-07
# Developer: Hyperling
# Purpose: Install all dependencies and run the project.
DIR=`dirname $0`
PROG=`basename $0`
if [[ $DIR == "." ]]; then
DIR="`pwd`"
echo $DIR/$PROG
fi
## Install any system packages. ##
if [[ -z `which npm` || -z `which tsc` || -z `which sqlite` ]]; then
echo "A dependency is missing, going through install process."
sudo apt install npm node-typescript sqlite
else
echo "All packages are available."
fi
## Install/update any project modules. ##
# Ensure it is safe to be running an npm nstall.
if [[ `pwd` != $DIR && -e package.json ]]; then
cat <<- EOF
WARNING: It seems you are currently in a different JS project which already
has a package.json. Cannot guarantee safety of installing $DIR. Please
make sure you understand what you're doing before continuing.
EOF
printf "Would you like to continue? [N/y]: "
typeset -u continue
read continue
if [[ $continue != Y* ]]; then
echo "Good choice, exiting application."
exit 1
fi
fi
# Use package.json in project directory to evaluate if any modules need added.
echo "Refreshing NPM packages."
npm install $DIR
## Main ##
# Create any non-git directories.
mkdir -p $DIR/logs
# Ensure all DB patches are applied.
bash $DIR/setup_db.sh
# Compile the Javascript portion of the application.
echo "Compiling..."
touch $DIR/dist &&
sh -c "rm -rv $DIR/dist" &&
tsc --project $DIR &&
ls -l $DIR/dist &&
echo "Success!" || {
echo "ERROR: Failed to compile."
exit 1
}
# Start backend in a forked process.
echo "Starting back-end in a child process and sleeping for 5 seconds."
mkdir -p $DIR/db
node $DIR/dist/server.js "$DIR" >>$DIR/logs/server.log 2>&1 &
sleep 5
# Start frontend.
# ??? $DIR/dist/index.js >$DIR/logs/ui.log 2>&1
echo "Started front-end successfully!" ||
echo "Failed to start front-end."
echo "Front-end service has stopped."
## Finish ##
# If we've reached this point then the front-end has been terminated and the
# back-end needs to be stopped as well. use the helper script to do it
echo "Finishing the back-end as well."
$DIR/stop.sh

78
setup_db.sh Executable file
View File

@ -0,0 +1,78 @@
#!/bin/bash
# Date: 2023-03-22
# Developer: Hyperling
# Purpose: Check if tables exist and if not then creates them
DIR=`dirname $0`
PROG=`basename $0`
if [[ $DIR == "." ]]; then
DIR="`pwd`"
echo $DIR/$PROG
fi
DB="$DIR/db/main"
DEBUG="$1"
## Functions ##
function check_table {
# Validate that the table exists in the database. If so then sqlite returns
# the DDL used to create it and we return success (0). Otherwise fail (1).
table_name="$1"
echo "Checking for $table_name..."
typeset -l result
result=`
sqlite3 $DB <<- EOF
.schema $table_name
EOF
`
[[ -n $DEBUG ]] && echo $result
if [[ $result == *"create table $table_name"* ]]; then
echo "Found it!"
return 0
fi
echo "Table not found."
return 1
}
function run_ddl {
#
file_name="$1"
echo "Running $file_name..."
sqlite3 $DB <<- EOF
.echo on
.read $file_name
EOF
}
function list_ddl {
# List the full path of the table files which need to be run.
ls $DIR/db/DDL/*
}
## Main ##
echo "Ensuring DDL is applied and all patches are complete."
# Lop through tables and their DDL.
list_ddl | while read table_file; do
echo "*** $table_file ***"
# Get the name of the table based on the filename with no extension.
table=`basename $table_file`
table=${table//.sql/}
# Check for the table.
check_table $table || {
# If the check fails, run the create statement.
run_ddl $table_file && {
# If the create succeeds, check for the table.
check_table $table || {
# If the check fails (again), throw an error and quit.
echo "ERROR: Could not create $table!"
exit 1
}
}
}
echo "Success!"
done
exit 0

17
src/functions.ts Normal file
View File

@ -0,0 +1,17 @@
/*
// Date: 2023-03-07
// Developer: Hyperling
// Purpose: Keep main file clean by holding helper functions here.
*/
import "objects.ts";
// Retrieve data from a connected database.
function select_db () {
null;
}
// Send data to a connected database.
function post_db () {
null;
}

7
src/includes.ts Normal file
View File

@ -0,0 +1,7 @@
/*
// Date: 2023-03-07
// Developer: Hyperling
// Purpose: Keep main file clean by making sure all source code is available.
*/
import "functions.ts";

13
src/index.tsx Normal file
View File

@ -0,0 +1,13 @@
/*
// Date: 2023-03-07
// Developer: Hyperling
// Purpose: Provide a UI for folks to log a food diary, providing a simple way
// to enter the data and an easy way to filter/sort what caused issues.
// Resources: Most helpful tutorials when learning Typescript and React.
// https://blog.logrocket.com/how-use-typescript-react-tutorial-examples/
*/
// Attach all the needed helpers.
import "includes.ts";
/* Main, UI */

14
src/objects.ts Normal file
View File

@ -0,0 +1,14 @@
/*
// Date: 2023-03-07
// Developer: Hyperling
// Purpose: Keep main file clean by holding types (interfaces and vars) here.
*/
interface record {
user_id: number;
cal_date: string;
meal: string; // Only wants options: Breakfast, Lunch, Dinner, Snack.
food: string;
caused_issue: boolean; // 0 for true and 1 for false like Shell?
comments: string;
}

57
src/server.js Normal file
View File

@ -0,0 +1,57 @@
/*
// Date: 2023-03-07
// Developer: Hyperling
// Purpose: Provide an API for the UI to hit, decoupling the DB code.
*/
"use strict";
/* Usage */
function usage (exit_code) {
console.log(
process.argv[1] + " is used to expose the SQLite backend to React.\n" +
" It accepts the following parameters: \n" +
" -h or --help: Display this usage text.\n" +
" /path/to/project: Where the project lives and the db + scripts exist."
);
process.exit(exit_code);
}
/* Arguments */
let DIR = "";
if (process.argv.length == 2 || process.argv.length >= 4 || process.argv[2] == undefined) {
console.log('Expected one argument!');
usage(1);
} else if (process.argv[2] === "-h" || process.argv[2] === "--help") {
usage(0);
} else {
DIR = process.argv[2];
console.log("Successfully got DIR: ", DIR);
}
/* Setup */
const sqlite3 = require('sqlite3').verbose();
async function finish () {
await db.close();
}
/* Main Program */
async function main() {
console.log("Connecting to DB "+DIR+"/db/main");
let db = await new sqlite3.Database(DIR+"/db/main");
console.log(db);
try {
let r = await db.run(`
SELECT count(*) FROM journal
`);
} catch (e) {
console.log("ERROR: The journal table could not be selected ", e);
}
console.log("The journal table current contains", r, " records.")
}
main();

40
stop.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash
# Date: 2023-03-07
# Developer: Hyperling
# Purpose: Turn off the project since the subprocesses run as forks.
DIR=`dirname $0`
PROG=`basename $0`
if [[ $DIR == "." ]]; then
DIR="`pwd`"
echo $DIR/$PROG
fi
## Stop Frontend Services ##
# Kill the frontend if it's still rnning for some reason.
# ???
## Stop Backend Services ##
# Let backend know it's time to close then loop over status until it stops.
echo "Stopping the backend service."
# curl POST localhost:8080/stop
count=1
still_up="Y"
while [[ $still_up == "Y" ]]; do
echo "Check #$count"
if (( $count >= 20 )); then
# Force kill backend if we have gone through 20 rounds.
killall $DIR/dist/server.js
fi
# curl GET localhost:8080/check_status
status=$?
if [[ $status != 0 ]]; then
still_up="N"
fi
count=$(( count + 1 ))
sleep 1
done

43
test.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
# Date: 2023-03-07
# Developer: Hyperling
# Purpose: Create a test user and some test data.
DIR=`dirname $0`
PROG=`basename $0`
if [[ $DIR == "." ]]; then
DIR="`pwd`"
echo $DIR/$PROG
fi
## Create Test User ##
# insert into user values (-1, 'Hyperling', 'SuperSecretPassword')
## Create Entries ##
# Manually
sqlite3 $DIR/db/main <<- EOF
.headers on
.echo on
delete from journal where user_id = -1;
insert into journal (user_id, cal_date, meal, food, caused_issue, comments)
values (-1, '2023-03-22', 'Breakfast', 'Mango', '1', null);
insert into journal (user_id, cal_date, meal, food, caused_issue, comments)
values (-1, '2023-03-22', 'Lunch', 'Greasy restaurant food', '0', null);
insert into journal (user_id, cal_date, meal, food, caused_issue, comments)
values (-1, '2023-03-22', 'Snack', 'Rice and beans', '1', null);
insert into journal (user_id, cal_date, meal, food, caused_issue, comments)
values (-1, '2023-03-22', 'Dinner', 'Rice and beans', '1', null);
select * from journal where user_id = -1;
EOF
## Via the API
# curl POST test_user 2023-03-07 "Mangoes and rice" FALSE "Yummy!"
## Remove any old test logs.
rm -rfv $DIR/logs

11
tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"outDir": "dist/",
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node",
}
}