Datepicker redesign + DB connection fixes for Prod
This commit is contained in:
29
server/check_adapter_props.js
Normal file
29
server/check_adapter_props.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const { PrismaBetterSqlite3 } = require('@prisma/adapter-better-sqlite3');
|
||||
const path = require('path');
|
||||
|
||||
async function check() {
|
||||
console.log('--- Prisma Adapter Diagnostic ---');
|
||||
const factory = new PrismaBetterSqlite3({ url: 'file:./dev.db' });
|
||||
|
||||
console.log('Factory Properties:');
|
||||
console.log(Object.keys(factory));
|
||||
console.log('Factory.adapterName:', factory.adapterName);
|
||||
console.log('Factory.provider:', factory.provider);
|
||||
|
||||
try {
|
||||
const adapter = await factory.connect();
|
||||
console.log('\nAdapter Properties:');
|
||||
console.log(Object.keys(adapter));
|
||||
console.log('Adapter name:', adapter.adapterName);
|
||||
console.log('Adapter provider:', adapter.provider);
|
||||
|
||||
// Also check if there are hidden/prototype properties
|
||||
let proto = Object.getPrototypeOf(adapter);
|
||||
console.log('Adapter Prototype Properties:', Object.getOwnPropertyNames(proto));
|
||||
|
||||
} catch (e) {
|
||||
console.error('Failed to connect:', e);
|
||||
}
|
||||
}
|
||||
|
||||
check();
|
||||
45
server/check_db_perms.js
Normal file
45
server/check_db_perms.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const dbPath = path.resolve(__dirname, 'prod.db');
|
||||
const dirPath = __dirname;
|
||||
|
||||
console.log('--- GymFlow Database Permission Check ---');
|
||||
console.log(`Checking directory: ${dirPath}`);
|
||||
console.log(`Checking file: ${dbPath}`);
|
||||
|
||||
// 1. Check Directory
|
||||
try {
|
||||
fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
|
||||
console.log('✅ Directory is readable and writable.');
|
||||
} catch (err) {
|
||||
console.error('❌ Directory is NOT writable! SQLite needs directory write access to create temporary files.');
|
||||
}
|
||||
|
||||
// 2. Check File
|
||||
if (fs.existsSync(dbPath)) {
|
||||
try {
|
||||
fs.accessSync(dbPath, fs.constants.R_OK | fs.constants.W_OK);
|
||||
console.log('✅ Database file is readable and writable.');
|
||||
} catch (err) {
|
||||
console.error('❌ Database file is NOT writable!');
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ Database file does not exist yet.');
|
||||
}
|
||||
|
||||
// 3. Try to write a test file in the directory
|
||||
const testFile = path.join(dirPath, '.write_test');
|
||||
try {
|
||||
fs.writeFileSync(testFile, 'test');
|
||||
fs.unlinkSync(testFile);
|
||||
console.log('✅ Successfully performed a test write in the directory.');
|
||||
} catch (err) {
|
||||
console.error(`❌ Failed test write in directory: ${err.message}`);
|
||||
}
|
||||
|
||||
console.log('\n--- Recommendation ---');
|
||||
console.log('If any checks failed, run these commands on your NAS (in the gymflow/server folder):');
|
||||
console.log('1. sudo chmod 777 .');
|
||||
console.log('2. sudo chmod 666 prod.db');
|
||||
console.log('\nAlternatively, ensure your Docker container is running with a user that owns these files.');
|
||||
Binary file not shown.
BIN
server/prod.db
BIN
server/prod.db
Binary file not shown.
@@ -54,10 +54,33 @@ async function resetDb() {
|
||||
// 4. Create the Admin user
|
||||
console.log(`Creating fresh admin user...`);
|
||||
|
||||
// In Prisma 7, we must use the adapter for better-sqlite3
|
||||
// In Prisma 7, PrismaBetterSqlite3 is a factory.
|
||||
// We use the factory to create the adapter, then we access the internal client
|
||||
// to disable WAL mode for NAS/Network share compatibility (journal_mode = DELETE).
|
||||
const { PrismaBetterSqlite3 } = require('@prisma/adapter-better-sqlite3');
|
||||
const adapter = new PrismaBetterSqlite3({ url: dbPath });
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
const factory = new PrismaBetterSqlite3({ url: dbPath });
|
||||
|
||||
const adapterWrapper = {
|
||||
provider: 'sqlite',
|
||||
adapterName: '@prisma/adapter-better-sqlite3',
|
||||
async connect() {
|
||||
const adapter = await factory.connect();
|
||||
if (adapter.client) {
|
||||
console.log(`Setting journal_mode = DELETE for NAS compatibility`);
|
||||
adapter.client.pragma('journal_mode = DELETE');
|
||||
}
|
||||
return adapter;
|
||||
},
|
||||
async connectToShadowDb() {
|
||||
const adapter = await factory.connectToShadowDb();
|
||||
if (adapter.client) {
|
||||
adapter.client.pragma('journal_mode = DELETE');
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
};
|
||||
|
||||
const prisma = new PrismaClient({ adapter: adapterWrapper });
|
||||
|
||||
try {
|
||||
const hashedPassword = await bcrypt.hash(adminPassword, 10);
|
||||
|
||||
@@ -35,13 +35,36 @@ console.log('Initializing Prisma Client with database:', dbPath);
|
||||
|
||||
let prisma: PrismaClient;
|
||||
|
||||
// In Prisma 7, PrismaBetterSqlite3 is a factory.
|
||||
// We use a wrapper to intercept the connection and disable WAL mode
|
||||
// for NAS/Network share compatibility (journal_mode = DELETE).
|
||||
try {
|
||||
const adapter = new PrismaBetterSqlite3({ url: dbPath });
|
||||
const factory = new PrismaBetterSqlite3({ url: dbPath });
|
||||
|
||||
const adapterWrapper = {
|
||||
provider: 'sqlite',
|
||||
adapterName: '@prisma/adapter-better-sqlite3',
|
||||
async connect() {
|
||||
const adapter = (await factory.connect()) as any;
|
||||
if (adapter.client) {
|
||||
console.log('[Prisma] Setting journal_mode = DELETE for NAS compatibility');
|
||||
adapter.client.pragma('journal_mode = DELETE');
|
||||
}
|
||||
return adapter;
|
||||
},
|
||||
async connectToShadowDb() {
|
||||
const adapter = (await factory.connectToShadowDb()) as any;
|
||||
if (adapter.client) {
|
||||
adapter.client.pragma('journal_mode = DELETE');
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
};
|
||||
|
||||
prisma =
|
||||
global.prisma ||
|
||||
new PrismaClient({
|
||||
adapter: adapter as any,
|
||||
adapter: adapterWrapper as any,
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.error('Failed to initialize Prisma Client:', e.message);
|
||||
|
||||
Reference in New Issue
Block a user