Working base server with migrations and build steps ironed out #1
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if the lint fix command fails
|
||||||
|
# If it does, exit with a non-zero status to prevent the commit.
|
||||||
|
|
||||||
|
echo "Running lint fix..."
|
||||||
|
# Replace with your actual lint fix command
|
||||||
|
# This is just an example, adapt it to your linter and project
|
||||||
|
npm run lint:fix # e.g., "eslint . --fix"
|
||||||
|
|
||||||
|
# Example: Capture the exit code of the command
|
||||||
|
lint_fix_result=$?
|
||||||
|
|
||||||
|
if [ $lint_fix_result -ne 0 ]; then
|
||||||
|
echo "Linting failed. Commit aborted."
|
||||||
|
exit 1 # Exit with a non-zero status to prevent the commit
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Lint fix completed successfully. Commit allowed."
|
||||||
|
exit 0 # Exit with a zero status to allow the commit
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Build and Push Image
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [closed]
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
if: gitea.event.pull_request.merged == true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Log in to Gitea Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: gitea.nelson-household.com # Replace with your Gitea domain
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.RUNNER_TOKEN }}
|
||||||
|
|
||||||
|
- name: Delete Old Images and Containers
|
||||||
|
run: |
|
||||||
|
docker ps -a -q -f "name=tcg-collectors-server" | xargs -I {} docker rm {} || true
|
||||||
|
docker images --format "{{.Repository}}:{{.Tag}}" | grep "tcg-collectors-server" | xargs -I {} docker rmi {} || true
|
||||||
|
|
||||||
|
- name: Build and Push Image
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
--build-arg DATABASE_URL=${{ secrets.DATABASE_URL }} \
|
||||||
|
-t gitea.nelson-household.com/hard-at-work/tcg-collectors-server/tcg-collectors-server:${{ github.sha }} .
|
||||||
|
docker push gitea.nelson-household.com/hard-at-work/tcg-collectors-server/tcg-collectors-server:${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Execute Migrations
|
||||||
|
run: |
|
||||||
|
docker run gitea.nelson-household.com/hard-at-work/tcg-collectors-server/tcg-collectors-server:${{ github.sha }} npm run migrate up
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
package-lock.json
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
ARG DATABASE_URL
|
||||||
|
|
||||||
|
ENV DATABASE_URL=${DATABASE_URL}
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN npm install --force
|
||||||
|
|
||||||
|
CMD ["npm", "run", "start"]
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
const express = require('express')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const authRoutes = require('./routes/auth')
|
||||||
|
const productsRoutes = require('./routes/products')
|
||||||
|
const usersRoutes = require('./routes/users')
|
||||||
|
|
||||||
|
const app = express()
|
||||||
|
const port = process.env.PORT || 3000
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
app.use(express.json()) // For parsing application/json
|
||||||
|
app.use(express.urlencoded({ extended: true })) // For parsing URL-encoded form data
|
||||||
|
|
||||||
|
// Static Files (Serving Frontend)
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')))
|
||||||
|
|
||||||
|
// Mount Routes
|
||||||
|
app.use('/auth', authRoutes)
|
||||||
|
app.use('/products', productsRoutes)
|
||||||
|
app.use('/users', usersRoutes)
|
||||||
|
|
||||||
|
// Default Route (Catch-all for undefined routes)
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
res.status(404).send('Sorry, the resource you requested could not be found.')
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Server listening on port ${port}`)
|
||||||
|
})
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// config/index.js
|
||||||
|
export default {
|
||||||
|
database: {
|
||||||
|
host: process.env.DB_HOST || 'localhost',
|
||||||
|
user: process.env.DB_USER || 'your_db_user',
|
||||||
|
password: process.env.DB_PASSWORD || 'your_db_password',
|
||||||
|
database: process.env.DB_NAME || 'your_db_name',
|
||||||
|
port: process.env.DB_PORT || 5432,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// eslint.config.js (Advanced alternative)
|
||||||
|
import prettierPlugin from 'eslint-plugin-prettier'
|
||||||
|
import prettierConfig from 'eslint-config-prettier'
|
||||||
|
import prettierOptions from './prettier.config.js' // Import your config directly
|
||||||
|
import importPlugin from 'eslint-plugin-import'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
prettier: prettierPlugin,
|
||||||
|
import: importPlugin,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...prettierConfig.rules,
|
||||||
|
'prettier/prettier': ['error', prettierOptions],
|
||||||
|
'no-sequences': 'off',
|
||||||
|
'no-console': 'warn',
|
||||||
|
'import/first': 'error',
|
||||||
|
'import/newline-after-import': 'error',
|
||||||
|
'import/no-duplicates': 'error',
|
||||||
|
'import/no-unresolved': 'error',
|
||||||
|
'import/no-unused-modules': ['warn', { missingExports: true }],
|
||||||
|
quotes: ['error', 'single'],
|
||||||
|
semi: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE images (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
file TEXT,
|
||||||
|
image BYTEA,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE images;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE collections (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
image_id UUID,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (image_id) REFERENCES images(id)
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE collections;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE items (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
collection_id UUID,
|
||||||
|
image_id UUID,
|
||||||
|
productId TEXT,
|
||||||
|
name TEXT,
|
||||||
|
cleanName TEXT,
|
||||||
|
extCardText TEXT,
|
||||||
|
marketPrice TEXT,
|
||||||
|
extRarity TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (collection_id) REFERENCES collections(id),
|
||||||
|
FOREIGN KEY (image_id) REFERENCES images(id)
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE items;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE locations (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE locations;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE sets (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
collection_id UUID NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
location_id UUID,
|
||||||
|
image_id UUID,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (collection_id) REFERENCES collections(id),
|
||||||
|
FOREIGN KEY (location_id) REFERENCES locations(id),
|
||||||
|
FOREIGN KEY (image_id) REFERENCES images(id)
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE sets;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE roles (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pmg) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE roles;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const up = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
CREATE TABLE users (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
username TEXT UNIQUE NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
role_id UUID,
|
||||||
|
email TEXT UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (role_id) REFERENCES roles(id)
|
||||||
|
);
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const down = (pgm) => {
|
||||||
|
pgm.sql(`
|
||||||
|
DROP TABLE users;
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "tcg-collectors-server",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A basic Express application with PostgreSQL integration.",
|
||||||
|
"main": "app.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node app.js",
|
||||||
|
"dev": "nodemon app.js",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"lint:fix": "eslint . --fix",
|
||||||
|
"format": "prettier --config prettier.config.js --write .",
|
||||||
|
"migrate": "node-pg-migrate"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"keywords": [
|
||||||
|
"express",
|
||||||
|
"node.js",
|
||||||
|
"postgres",
|
||||||
|
"postgresql",
|
||||||
|
"database"
|
||||||
|
],
|
||||||
|
"author": "Your Name",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"csv-parser": "^3.0.0",
|
||||||
|
"dotenv": "^16.0.3",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"node-pg": "^1.0.1",
|
||||||
|
"p-limit": "^7.3.0",
|
||||||
|
"pg": "^8.20.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^10.3.0",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"eslint-plugin-import": "^2.32.0",
|
||||||
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
|
"jest": "^29.0.0",
|
||||||
|
"node-pg-migrate": "^8.0.4",
|
||||||
|
"nodemon": "^3.0.0",
|
||||||
|
"prettier": "^3.8.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// prettier.config.js
|
||||||
|
export default {
|
||||||
|
trailingComma: 'es5',
|
||||||
|
tabWidth: 2,
|
||||||
|
semi: false, // Crucial: Sets semicolon removal.
|
||||||
|
useTabs: true,
|
||||||
|
singleQuote: true,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user