initial commit

This commit is contained in:
Josh Myers
2026-04-09 20:36:10 -07:00
commit 4681b1a3c8
248 changed files with 97032 additions and 0 deletions

63
scripts/dev-https.js Normal file
View File

@@ -0,0 +1,63 @@
/**
* Local HTTPS development server.
*
* Creates an HTTPS proxy in front of Next.js dev server so that
* the EVE SSO callback URL (https://localhost:3000/...) works locally.
*
* Usage: node scripts/dev-https.js
* (or: npm run dev:https)
*
* Prerequisites:
* 1. Run ./scripts/generate-cert.sh to create certs/
* 2. Trust the self-signed cert in your OS/browser
*/
const { createServer } = require("https");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");
const path = require("path");
const dev = process.env.NODE_ENV !== "production";
const hostname = "localhost";
const port = parseInt(process.env.PORT || "3000", 10);
const certDir = path.join(__dirname, "..", "certs");
const keyPath = path.join(certDir, "localhost-key.pem");
const certPath = path.join(certDir, "localhost.pem");
if (!fs.existsSync(keyPath) || !fs.existsSync(certPath)) {
console.error(
"Self-signed certificates not found.\n" +
"Run: ./scripts/generate-cert.sh\n" +
"Then try again."
);
process.exit(1);
}
const httpsOptions = {
key: fs.readFileSync(keyPath),
cert: fs.readFileSync(certPath),
};
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();
app.prepare().then(() => {
createServer(httpsOptions, async (req, res) => {
try {
const parsedUrl = parse(req.url, true);
await handle(req, res, parsedUrl);
} catch (err) {
console.error("Error handling request:", err);
res.statusCode = 500;
res.end("Internal Server Error");
}
}).listen(port, () => {
console.log(`\n ▶ HTTPS server running at https://${hostname}:${port}\n`);
console.log(` EVE SSO Login: https://${hostname}:${port}/api/auth/eve-sso`);
console.log(` EVE SSO Callback: https://${hostname}:${port}/api/auth/callback/eve-sso`);
console.log(` Sync trigger: POST https://${hostname}:${port}/api/eve/sync`);
console.log(` Sync status: GET https://${hostname}:${port}/api/eve/sync\n`);
});
});

40
scripts/generate-cert.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Generate a self-signed certificate for local HTTPS development.
# EVE SSO requires HTTPS for the callback URL.
#
# Usage: ./scripts/generate-cert.sh
#
# This creates:
# certs/localhost-key.pem — Private key
# certs/localhost.pem — Self-signed certificate
#
# The cert is valid for 365 days and covers localhost + 127.0.0.1.
set -euo pipefail
CERT_DIR="certs"
mkdir -p "$CERT_DIR"
echo "Generating self-signed certificate for localhost..."
openssl req -x509 \
-newkey rsa:2048 \
-keyout "$CERT_DIR/localhost-key.pem" \
-out "$CERT_DIR/localhost.pem" \
-days 365 \
-nodes \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
echo ""
echo "Certificate generated:"
echo " Key: $CERT_DIR/localhost-key.pem"
echo " Cert: $CERT_DIR/localhost.pem"
echo ""
echo "To trust this certificate on macOS:"
echo " sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $CERT_DIR/localhost.pem"
echo ""
echo "To trust on Windows (PowerShell as Admin):"
echo ' Import-Certificate -FilePath "certs\localhost.pem" -CertStoreLocation Cert:\LocalMachine\Root'
echo ""
echo "Then run: npm run dev:https"

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env node
/**
* Migration runner for new module tables.
* Run from project root: node scripts/migrate-new-modules.js
*
* Alternative: npx prisma db push (which reads from schema.prisma)
*/
const { PrismaClient } = require('@prisma/client');
const fs = require('fs');
const path = require('path');
async function main() {
const prisma = new PrismaClient();
try {
console.log('Connecting to database...');
await prisma.$connect();
console.log('Connected.');
const sqlPath = path.join(__dirname, '..', 'prisma', 'migrations', 'add_new_modules', 'migration.sql');
const sql = fs.readFileSync(sqlPath, 'utf-8');
// Split by semicolons and execute each statement
const statements = sql
.split(';')
.map(s => s.trim())
.filter(s => s.length > 0 && !s.startsWith('--'));
console.log(`Executing ${statements.length} SQL statements...`);
for (let i = 0; i < statements.length; i++) {
const stmt = statements[i];
try {
await prisma.$executeRawUnsafe(stmt);
console.log(` [${i + 1}/${statements.length}] OK`);
} catch (err) {
// Ignore "already exists" errors
if (err.message.includes('already exists')) {
console.log(` [${i + 1}/${statements.length}] Already exists (skipped)`);
} else {
console.error(` [${i + 1}/${statements.length}] ERROR: ${err.message}`);
}
}
}
console.log('\nMigration complete!');
console.log('Next step: run "npx prisma generate" to update the Prisma client types.');
} catch (err) {
console.error('Migration failed:', err.message);
process.exit(1);
} finally {
await prisma.$disconnect();
}
}
main();