Skip to content

Commit

Permalink
chore: Update knex migration files and reorganize project structure
Browse files Browse the repository at this point in the history
  • Loading branch information
wajeht committed Aug 8, 2024
1 parent db2ec9f commit 8e4c14e
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ TWILIO_AUTH_TOKEN=
TWILIO_FROM_PHONE_NUMBER=
TWILIO_PHONE_NUMBER=

# discord
DISCORD_WEBHOOK_URL=

# caprover
CAPROVER_DOMAIN=
CAPROVER_APP_TOKEN=
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
"format": "prettier --write --cache . > /dev/null",
"lint:check": "eslint .",
"lint": "eslint --fix --cache .",
"migrate:make": "tsx ./node_modules/knex/bin/cli.js migrate:make --knexfile=./src/database/knexfile.ts",
"migrate:latest:prod": "knex migrate:latest --knexfile=./dist/src/database/knexfile.js",
"migrate:latest": "tsx ./node_modules/knex/bin/cli.js migrate:latest --knexfile=./src/database/knexfile.ts",
"migrate:rollback": "tsx ./node_modules/knex/bin/cli.js migrate:rollback --knexfile=./src/database/knexfile.ts",
"migrate:rollback:prod": "knex migrate:rollback --knexfile=./dist/src/database/knexfile.js",
"seed:make": "tsx ./node_modules/knex/bin/cli.js seed:make --knexfile=./src/database/knexfile.ts",
"seed:run": "tsx ./node_modules/knex/bin/cli.js seed:run --knexfile=./src/database/knexfile.ts",
"seed:run:prod": "knex seed:run --knexfile=./dist/src/database/knexfile.js"
"migrate:make": "tsx ./node_modules/knex/bin/cli.js migrate:make --knexfile=./src/db/knexfile.ts",
"migrate:latest:prod": "knex migrate:latest --knexfile=./dist/src/db/knexfile.js",
"migrate:latest": "tsx ./node_modules/knex/bin/cli.js migrate:latest --knexfile=./src/db/knexfile.ts",
"migrate:rollback": "tsx ./node_modules/knex/bin/cli.js migrate:rollback --knexfile=./src/db/knexfile.ts",
"migrate:rollback:prod": "knex migrate:rollback --knexfile=./dist/src/db/knexfile.js",
"seed:make": "tsx ./node_modules/knex/bin/cli.js seed:make --knexfile=./src/db/knexfile.ts",
"seed:run": "tsx ./node_modules/knex/bin/cli.js seed:run --knexfile=./src/db/knexfile.ts",
"seed:run:prod": "knex seed:run --knexfile=./dist/src/db/knexfile.js"
},
"keywords": [
"discord",
Expand Down
151 changes: 151 additions & 0 deletions src/db/migrations/20240807213915_create_tables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import type { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema
.createTable('users', (table) => {
table.increments('id').primary();
table.string('email').unique().notNullable();
table.string('password').notNullable();
table.boolean('is_verified').defaultTo(false);
table.string('verification_token').nullable();
table.timestamp('verification_token_expires_at').nullable();
table.string('reset_password_token').nullable();
table.timestamp('reset_password_token_expires_at').nullable();
table.timestamps(true, true);

table.index('email');
table.index('is_verified');
table.index('verification_token');
table.index('reset_password_token');
})
.createTable('apps', (table) => {
table.increments('id').primary();
table.integer('user_id').unsigned().references('id').inTable('users').onDelete('CASCADE');
table.string('name').notNullable();
table.timestamps(true, true);

table.index('user_id');
table.index('name');
})
.createTable('channel_types', (table) => {
table.increments('id').primary();
table.string('name').unique().notNullable();
table.timestamps(true, true);

table.index('name');
})
.createTable('app_channels', (table) => {
table.increments('id').primary();
table.integer('app_id').unsigned().references('id').inTable('apps').onDelete('CASCADE');
table
.integer('channel_type_id')
.unsigned()
.references('id')
.inTable('channel_types')
.onDelete('CASCADE');
table.string('name').notNullable();
table.boolean('is_active').defaultTo(true);
table.timestamps(true, true);

table.index('app_id');
table.index('channel_type_id');
table.index('is_active');
table.unique(['app_id', 'name']);
})
.createTable('email_configs', (table) => {
table
.integer('app_channel_id')
.unsigned()
.references('id')
.inTable('app_channels')
.onDelete('CASCADE')
.primary();
table.string('host').notNullable();
table.integer('port').notNullable();
table.string('alias').notNullable();
table.string('auth_email').notNullable();
table.string('auth_pass').notNullable();

table.index('host');
table.index('auth_email');
})
.createTable('sms_configs', (table) => {
table
.integer('app_channel_id')
.unsigned()
.references('id')
.inTable('app_channels')
.onDelete('CASCADE')
.primary();
table.string('account_sid').notNullable();
table.string('auth_token').notNullable();
table.string('from_phone_number').notNullable();
table.string('phone_number').notNullable();

table.index('account_sid');
table.index('from_phone_number');
table.index('phone_number');
})
.createTable('discord_configs', (table) => {
table
.integer('app_channel_id')
.unsigned()
.references('id')
.inTable('app_channels')
.onDelete('CASCADE')
.primary();
table.string('webhook_url').notNullable();
table.index('webhook_url');
})
.createTable('notifications', (table) => {
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid()'));
table.integer('app_id').unsigned().references('id').inTable('apps').onDelete('CASCADE');
table.text('message').notNullable();
table.jsonb('details').nullable();
table.timestamps(true, true);

table.index('app_id');
table.index('created_at');
})
.createTable('jobs', (table) => {
table.increments('id').primary();
table.uuid('notification_id').references('id').inTable('notifications').onDelete('CASCADE');
table
.integer('app_channel_id')
.unsigned()
.references('id')
.inTable('app_channels')
.onDelete('CASCADE');
table
.enu('status', ['pending', 'processing', 'completed', 'failed', 'retrying'])
.notNullable()
.defaultTo('pending');
table.integer('attempts').defaultTo(0);
table.timestamp('processed_at').nullable();
table.text('error_message').nullable();
table.jsonb('result').nullable();
table.timestamps(true, true);

table.index('notification_id');
table.index('app_channel_id');
table.index('status');
table.index('created_at');
table.index('attempts');
});

// Insert default channel types
await knex('channel_types').insert([{ name: 'email' }, { name: 'sms' }, { name: 'discord' }]);
}

export async function down(knex: Knex): Promise<void> {
await knex.schema
.dropTableIfExists('jobs')
.dropTableIfExists('notifications')
.dropTableIfExists('discord_configs')
.dropTableIfExists('sms_configs')
.dropTableIfExists('email_configs')
.dropTableIfExists('app_channels')
.dropTableIfExists('channel_types')
.dropTableIfExists('apps')
.dropTableIfExists('users');
}
19 changes: 0 additions & 19 deletions src/db/migrations/20240807213915_create_users_table.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export function getHealthzHandler() {
export function postNotificationHandler() {
return async (req: Request, res: Response) => {
console.log(req.body);
// {
// "success": true,
// "message": "Notification created and queued successfully",
// "notificationId": "generated_uuid",
// "jobId": "generated_job_id",
// "channels": ["email", "sms"]
// }
res.json({ message: 'ok' });
};
}
2 changes: 1 addition & 1 deletion src/jobs/email.job.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Queue, Worker } from 'bullmq';
import { redis } from '../db/db';
import { sendEmail } from './utils/email';
import { sendEmail } from './channel/email';

const queueName = 'sendEmailQueue';

Expand Down

0 comments on commit 8e4c14e

Please sign in to comment.