Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e43fc9cd9 | |||
| f053f42b6d |
@@ -1,39 +0,0 @@
|
||||
name: Mirror to GitHub (Archive Method)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
mirror:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Mirror using git archive
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Configure git
|
||||
git config --global user.name "Gitea Mirror Bot"
|
||||
git config --global user.email "bot@noreply.gitea.local"
|
||||
|
||||
# Copy gitattributes
|
||||
cp .gitattributes-github .gitattributes
|
||||
|
||||
# Create archive excluding files
|
||||
git archive --format=tar HEAD | tar -x -C /tmp/export
|
||||
|
||||
# Initialize new repo in export directory
|
||||
cd /tmp/export
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Mirror from Gitea: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
# Push to GitHub
|
||||
git remote add origin https://x-access-token:${GITHUB_TOKEN}@github.com/YOUR_GITHUB_USERNAME/YOUR_REPO_NAME.git
|
||||
git push -f origin main
|
||||
@@ -1,42 +0,0 @@
|
||||
name: Mirror to GitHub (Rsync Method)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
mirror:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare mirror directory
|
||||
run: |
|
||||
# Create mirror directory
|
||||
mkdir -p /tmp/github-mirror
|
||||
|
||||
# Use rsync to copy files, excluding sensitive ones
|
||||
rsync -av --exclude-from='.github-mirror-exclude' ./ /tmp/github-mirror/
|
||||
|
||||
- name: Push to GitHub
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cd /tmp/github-mirror
|
||||
|
||||
# Initialize git repo
|
||||
git init
|
||||
git config user.name "Gitea Mirror Bot"
|
||||
git config user.email "bot@noreply.gitea.local"
|
||||
|
||||
# Add all files and commit
|
||||
git add .
|
||||
git commit -m "Mirror from Gitea: $(git --git-dir=$GITHUB_WORKSPACE/.git log -1 --format='%h %s')"
|
||||
|
||||
# Push to GitHub
|
||||
git remote add origin https://x-access-token:${GITHUB_TOKEN}@github.com/YOUR_GITHUB_USERNAME/YOUR_REPO_NAME.git
|
||||
git push -f origin main
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Push to GitHub
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
|
||||
GITHUBTOKEN: ${{ secrets.GITHUBTOKEN }}
|
||||
run: |
|
||||
# Add GitHub remote
|
||||
git remote add github https://x-access-token:${GITHUBTOKEN}@github.com/the-luap/picpeak.git
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Ensure PostgreSQL compatibility for all insert operations
|
||||
* This migration doesn't change the schema but ensures all tables
|
||||
* are compatible with .returning() syntax
|
||||
*/
|
||||
|
||||
exports.up = async function(knex) {
|
||||
// This migration is informational only
|
||||
// All insert operations should use .returning('id') going forward
|
||||
|
||||
console.log('PostgreSQL compatibility check:');
|
||||
console.log('- All INSERT operations should use .returning("id")');
|
||||
console.log('- All date operations should use ISO strings');
|
||||
console.log('- Boolean values are handled automatically by Knex');
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
exports.down = async function(knex) {
|
||||
// No rollback needed
|
||||
return Promise.resolve();
|
||||
};
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.5.16",
|
||||
"archiver": "^5.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "picpeak-backend",
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"description": "Backend for PicPeak event photo sharing platform",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -36,7 +36,8 @@ async function createTestEvent() {
|
||||
await db('events').where('slug', eventData.slug).delete();
|
||||
|
||||
// Insert new event
|
||||
const [eventId] = await db('events').insert(eventData);
|
||||
const insertResult = await db('events').insert(eventData).returning('id');
|
||||
const eventId = insertResult[0]?.id || insertResult[0];
|
||||
console.log('Event created with ID:', eventId);
|
||||
|
||||
console.log('\nTest event created successfully!');
|
||||
|
||||
@@ -211,12 +211,14 @@ router.post('/:id/restore', adminAuth, async (req, res) => {
|
||||
categoriesMap.set(categoryName, existingCategory.id);
|
||||
} else {
|
||||
// Create the category if it doesn't exist
|
||||
const [newCategoryId] = await db('photo_categories').insert({
|
||||
const insertResult = await db('photo_categories').insert({
|
||||
event_id: archive.id,
|
||||
name: categoryName,
|
||||
slug: categoryName.toLowerCase().replace(/[^a-z0-9]/g, '-'),
|
||||
created_at: new Date()
|
||||
});
|
||||
}).returning('id');
|
||||
|
||||
const newCategoryId = insertResult[0]?.id || insertResult[0];
|
||||
categoriesMap.set(categoryName, newCategoryId);
|
||||
}
|
||||
}
|
||||
@@ -266,6 +268,9 @@ router.post('/:id/restore', adminAuth, async (req, res) => {
|
||||
}
|
||||
|
||||
// Update event status
|
||||
const thirtyDaysFromNow = new Date();
|
||||
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
|
||||
|
||||
await db('events')
|
||||
.where('id', req.params.id)
|
||||
.update({
|
||||
@@ -273,7 +278,7 @@ router.post('/:id/restore', adminAuth, async (req, res) => {
|
||||
is_active: true,
|
||||
archive_path: null,
|
||||
archived_at: null,
|
||||
expires_at: db.raw("datetime('now', '+30 days')") // Reset expiration
|
||||
expires_at: thirtyDaysFromNow.toISOString() // Reset expiration - works on both DBs
|
||||
});
|
||||
|
||||
// Log activity
|
||||
|
||||
@@ -83,7 +83,7 @@ router.post('/', adminAuth, [
|
||||
await fs.mkdir(path.join(eventPath, 'individual'), { recursive: true });
|
||||
|
||||
// Insert into database
|
||||
const [eventId] = await db('events').insert({
|
||||
const insertResult = await db('events').insert({
|
||||
slug,
|
||||
event_type,
|
||||
event_name,
|
||||
@@ -99,7 +99,10 @@ router.post('/', adminAuth, [
|
||||
created_at: new Date().toISOString(),
|
||||
allow_user_uploads,
|
||||
upload_category_id
|
||||
});
|
||||
}).returning('id');
|
||||
|
||||
// Handle both PostgreSQL (returns array of objects) and SQLite (returns array of IDs)
|
||||
const eventId = insertResult[0]?.id || insertResult[0];
|
||||
|
||||
// Log activity
|
||||
await logActivity('event_created',
|
||||
|
||||
@@ -64,7 +64,7 @@ router.post('/', adminAuth, [
|
||||
await fs.mkdir(path.join(eventPath, 'individual'), { recursive: true });
|
||||
|
||||
// Insert into database
|
||||
const [eventId] = await db('events').insert({
|
||||
const insertResult = await db('events').insert({
|
||||
slug,
|
||||
event_type,
|
||||
event_name,
|
||||
@@ -76,7 +76,10 @@ router.post('/', adminAuth, [
|
||||
color_theme,
|
||||
share_link: shareLink,
|
||||
expires_at
|
||||
});
|
||||
}).returning('id');
|
||||
|
||||
// Handle both PostgreSQL (returns array of objects) and SQLite (returns array of IDs)
|
||||
const eventId = insertResult[0]?.id || insertResult[0];
|
||||
|
||||
// Queue creation email
|
||||
const { queueEmail } = require('../services/emailProcessor');
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Database Compatibility Utilities
|
||||
* Handles differences between PostgreSQL and SQLite
|
||||
*/
|
||||
|
||||
const { db } = require('../database/db');
|
||||
|
||||
/**
|
||||
* Get database client type
|
||||
* @returns {string} 'pg' or 'sqlite3'
|
||||
*/
|
||||
function getDbClient() {
|
||||
return process.env.DATABASE_CLIENT || 'sqlite3';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if using PostgreSQL
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isPostgreSQL() {
|
||||
return getDbClient() === 'pg';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle insert operations that return IDs
|
||||
* Works with both PostgreSQL and SQLite
|
||||
* @param {object} query - Knex query builder
|
||||
* @returns {Promise<number>} The inserted ID
|
||||
*/
|
||||
async function insertAndGetId(query) {
|
||||
const result = await query.returning('id');
|
||||
|
||||
// PostgreSQL returns array of objects [{id: 1}]
|
||||
// SQLite returns array of IDs [1]
|
||||
return result[0]?.id || result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date for database compatibility
|
||||
* @param {Date} date - JavaScript Date object
|
||||
* @returns {string} ISO string format that works on both databases
|
||||
*/
|
||||
function formatDateForDB(date) {
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add days to a date (database agnostic)
|
||||
* @param {Date} date - Starting date
|
||||
* @param {number} days - Number of days to add
|
||||
* @returns {Date} New date
|
||||
*/
|
||||
function addDays(date, days) {
|
||||
const result = new Date(date);
|
||||
result.setDate(result.getDate() + days);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date extraction SQL that works on both databases
|
||||
* @param {string} column - Column name
|
||||
* @returns {object} Knex raw query
|
||||
*/
|
||||
function dateExtractSQL(column) {
|
||||
if (isPostgreSQL()) {
|
||||
return db.raw(`DATE(${column})`);
|
||||
} else {
|
||||
// SQLite uses date() function
|
||||
return db.raw(`date(${column})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database size query
|
||||
* @param {string} dbName - Database name
|
||||
* @returns {Promise<number>} Size in bytes
|
||||
*/
|
||||
async function getDatabaseSize(dbName) {
|
||||
if (isPostgreSQL()) {
|
||||
const result = await db.raw('SELECT pg_database_size(?) as size', [dbName]);
|
||||
return result.rows[0]?.size || 0;
|
||||
} else {
|
||||
// For SQLite, check file size
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const dbPath = process.env.DATABASE_PATH || path.join(__dirname, '../../data/photo_sharing.db');
|
||||
try {
|
||||
const stats = await fs.stat(dbPath);
|
||||
return stats.size;
|
||||
} catch (error) {
|
||||
console.error('Error getting SQLite database size:', error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle boolean values for database compatibility
|
||||
* @param {boolean} value - Boolean value
|
||||
* @returns {any} Database-appropriate boolean representation
|
||||
*/
|
||||
function formatBoolean(value) {
|
||||
if (isPostgreSQL()) {
|
||||
return value;
|
||||
} else {
|
||||
// SQLite stores booleans as 0/1
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse boolean from database
|
||||
* @param {any} value - Database boolean value
|
||||
* @returns {boolean} JavaScript boolean
|
||||
*/
|
||||
function parseBoolean(value) {
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDbClient,
|
||||
isPostgreSQL,
|
||||
insertAndGetId,
|
||||
formatDateForDB,
|
||||
addDays,
|
||||
dateExtractSQL,
|
||||
getDatabaseSize,
|
||||
formatBoolean,
|
||||
parseBoolean
|
||||
};
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "picpeak-frontend",
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "picpeak-frontend",
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.0.0",
|
||||
"@tiptap/extension-link": "^2.25.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "picpeak-frontend",
|
||||
"private": true,
|
||||
"version": "1.0.26",
|
||||
"version": "1.0.27",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user