feat(api): implement secure portfolio history, daily FX and atomic backups
This commit is contained in:
1 parent
67220e38ed
commit
99174a3da5
25 files changed
+1750
-28
No files matched your search
@@ -0,0 +1,19 @@
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const command = process.argv[2];
|
||||
if (!['deploy', 'status'].includes(command)) process.exit(1);
|
||||
const p = spawnSync(
|
||||
process.execPath,
|
||||
[require.resolve('prisma/build/index.js'), 'migrate', command],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
// Prisma datasource lines can expose local connection metadata; omit them.
|
||||
const output = (p.stdout || '')
|
||||
.split(/\r?\n/)
|
||||
.filter((s) => !s.startsWith('Datasource ') && !s.includes('Environment variables'))
|
||||
.join('\n');
|
||||
if (p.status === 0) console.log(output);
|
||||
else
|
||||
console.error(
|
||||
'Database migration command failed. Check local database access and migration compatibility. No reset was performed.',
|
||||
);
|
||||
process.exitCode = p.status || 0;
|
||||
@@ -1,3 +1,40 @@
|
||||
require('dotenv').config({quiet:true});
|
||||
const mysql=require('mysql2/promise');
|
||||
(async()=>{let db;try {const u=new URL(process.env.DATABASE_URL);const name=u.pathname.slice(1);if(!/^[a-zA-Z0-9_]+$/.test(name))throw Error();db=await mysql.createConnection({host:u.hostname,port:Number(u.port||3306),user:decodeURIComponent(u.username),password:decodeURIComponent(u.password)});const [existing]=await db.execute('SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME=?',[name]);if(existing.length){const [tables]=await db.execute('SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=?',[name]);console.log('Database already exists; tables:',tables.map(t=>t.TABLE_NAME));}else {await db.query('CREATE DATABASE `'+name+'` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci');console.log('Created new empty project database.');}}catch(e){console.error('Database preflight failed:',e.code||'configuration error');process.exitCode=1;}finally{if(db)await db.end();}})();
|
||||
require('dotenv').config({ quiet: true });
|
||||
const mysql = require('mysql2/promise');
|
||||
(async () => {
|
||||
let db;
|
||||
try {
|
||||
const u = new URL(process.env.DATABASE_URL);
|
||||
const name = u.pathname.slice(1);
|
||||
if (!/^[a-zA-Z0-9_]+$/.test(name)) throw Error();
|
||||
db = await mysql.createConnection({
|
||||
host: u.hostname,
|
||||
port: Number(u.port || 3306),
|
||||
user: decodeURIComponent(u.username),
|
||||
password: decodeURIComponent(u.password),
|
||||
});
|
||||
const [existing] = await db.execute(
|
||||
'SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME=?',
|
||||
[name],
|
||||
);
|
||||
if (existing.length) {
|
||||
const [tables] = await db.execute(
|
||||
'SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=?',
|
||||
[name],
|
||||
);
|
||||
console.log(
|
||||
'Database already exists; tables:',
|
||||
tables.map((t) => t.TABLE_NAME),
|
||||
);
|
||||
} else {
|
||||
await db.query(
|
||||
'CREATE DATABASE `' + name + '` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci',
|
||||
);
|
||||
console.log('Created new empty project database.');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Database preflight failed:', e.code || 'configuration error');
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
if (db) await db.end();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,13 @@
|
||||
const { spawn, spawnSync } = require('node:child_process');
|
||||
const tsc = require.resolve('typescript/bin/tsc');
|
||||
if (spawnSync(process.execPath, [tsc], { stdio: 'inherit' }).status !== 0) process.exit(1);
|
||||
const children = [
|
||||
spawn(process.execPath, [tsc, '--watch', '--preserveWatchOutput'], { stdio: 'inherit' }),
|
||||
spawn(process.execPath, ['--watch', 'dist/main.js'], { stdio: 'inherit' }),
|
||||
];
|
||||
function stop() {
|
||||
for (const p of children) p.kill();
|
||||
process.exit();
|
||||
}
|
||||
process.on('SIGINT', stop);
|
||||
process.on('SIGTERM', stop);
|
||||
Reference in new issue
Block a user