add project

This commit is contained in:
ZOMBIIIIIII
2026-04-08 14:11:27 +03:00
parent bfa95223a0
commit a81e29807c
115 changed files with 18413 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
import type { Knex } from 'knex';
import path from 'path';
import dotenv from 'dotenv';
// Load .env from repo root when running migrations directly
dotenv.config({ path: path.resolve(__dirname, '../../../../.env') });
const config: Knex.Config = {
client: 'pg',
connection: {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
user: process.env.DB_USER || 'postgres',
password: process.env.DB_PASSWORD || 'postgres',
database: process.env.DB_NAME || 'cryptowallet_v2',
},
migrations: {
directory: path.resolve(__dirname, 'migrations'),
extension: __filename.endsWith('.js') ? 'js' : 'ts',
},
};
export default config;

View File

@@ -0,0 +1,28 @@
import type { Knex } from 'knex';
export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable('users', (t) => {
t.string('id', 26).primary();
t.string('email', 255).notNullable().unique();
t.string('password_hash', 255).notNullable();
t.string('last_name', 128).nullable();
t.string('first_name', 128).nullable();
t.string('middle_name', 128).nullable();
t.date('birth_date').nullable();
t.string('crypto_wallet', 255).nullable();
t.string('phone', 16).nullable();
t.string('bik', 9).nullable();
t.string('account_number', 20).nullable();
t.string('card_number', 19).nullable();
t.string('inn', 12).nullable();
t.boolean('kyc_verified').notNullable().defaultTo(false);
t.timestamp('kyc_verified_at', { useTz: true }).nullable();
t.boolean('is_deleted').notNullable().defaultTo(false);
t.timestamp('created_at', { useTz: true }).notNullable().defaultTo(knex.fn.now());
t.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(knex.fn.now());
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists('users');
}

View File

@@ -0,0 +1,20 @@
import type { Knex } from 'knex';
export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable('wallets', (t) => {
t.string('id', 26).primary();
t.string('user_id', 26).notNullable().references('id').inTable('users').onDelete('CASCADE');
t.string('chain', 10).notNullable();
t.string('address', 256).notNullable();
t.string('derivation_path', 64).notNullable();
t.timestamp('created_at', { useTz: true }).notNullable().defaultTo(knex.fn.now());
t.unique(['user_id', 'chain']);
});
await knex.schema.raw('CREATE INDEX idx_wallets_user_id ON wallets(user_id)');
await knex.schema.raw('CREATE INDEX idx_wallets_address ON wallets(address)');
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists('wallets');
}

View File

@@ -0,0 +1,26 @@
import type { Knex } from 'knex';
export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable('sessions', (t) => {
t.string('id', 26).primary();
t.string('sid', 26).notNullable().unique();
t.string('user_id', 26).notNullable().references('id').inTable('users').onDelete('CASCADE');
t.string('device_id', 26).nullable();
t.string('user_agent', 500).nullable();
t.string('first_ip', 64).nullable();
t.string('last_ip', 64).nullable();
t.timestamp('last_seen_at', { useTz: true }).nullable();
t.timestamp('revoked_at', { useTz: true }).nullable();
t.string('refresh_jti_hash', 255).nullable();
t.timestamp('refresh_expires_at', { useTz: true }).nullable();
t.timestamp('created_at', { useTz: true }).notNullable().defaultTo(knex.fn.now());
t.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(knex.fn.now());
});
await knex.schema.raw('CREATE INDEX idx_sessions_user_id ON sessions(user_id)');
await knex.schema.raw('CREATE INDEX idx_sessions_sid ON sessions(sid)');
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists('sessions');
}