Move migrations to separate app
This commit is contained in:
parent
87724bb7b8
commit
c47223f5e9
21 changed files with 55 additions and 815 deletions
|
|
@ -6,7 +6,7 @@ RUN mkdir -p ${APP_DIR}/
|
|||
RUN npm i -g turbo
|
||||
WORKDIR ${APP_DIR}
|
||||
COPY . .
|
||||
RUN turbo prune --scope=@link-stack/bridge-frontend --docker
|
||||
RUN turbo prune --scope=@link-stack/bridge-frontend --scope=@link-stack/bridge-migrations --docker
|
||||
|
||||
FROM base AS installer
|
||||
ARG APP_DIR=/opt/bridge-frontend
|
||||
|
|
@ -18,7 +18,7 @@ RUN npm ci
|
|||
|
||||
COPY --from=builder ${APP_DIR}/out/full/ .
|
||||
RUN npm i -g turbo
|
||||
RUN turbo run build --filter=@link-stack/bridge-frontend
|
||||
RUN turbo run build --filter=@link-stack/bridge-frontend --filter=@link-stack/bridge-migrations
|
||||
|
||||
FROM base AS runner
|
||||
ARG APP_DIR=/opt/bridge-frontend
|
||||
|
|
@ -36,6 +36,7 @@ RUN mkdir -p ${APP_DIR}
|
|||
WORKDIR ${APP_DIR}
|
||||
COPY --from=installer ${APP_DIR}/node_modules/ ./node_modules/
|
||||
COPY --from=installer ${APP_DIR}/apps/bridge-frontend/ ./apps/bridge-frontend/
|
||||
COPY --from=installer ${APP_DIR}/apps/bridge-migrations/ ./apps/bridge-migrations/
|
||||
COPY --from=installer ${APP_DIR}/package.json ./package.json
|
||||
RUN chown -R node:node ${APP_DIR}/
|
||||
WORKDIR ${APP_DIR}/apps/bridge-frontend/
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
import * as path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { promises as fs } from "fs";
|
||||
import {
|
||||
Kysely,
|
||||
Migrator,
|
||||
MigrationResult,
|
||||
FileMigrationProvider,
|
||||
PostgresDialect,
|
||||
CamelCasePlugin,
|
||||
} from "kysely";
|
||||
import pkg from "pg";
|
||||
const { Pool } = pkg;
|
||||
import * as dotenv from "dotenv";
|
||||
|
||||
interface Database {}
|
||||
|
||||
export const migrate = async (arg: string) => {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
dotenv.config({ path: path.join(__dirname, "../.env.local") });
|
||||
}
|
||||
const db = new Kysely<Database>({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new Pool({
|
||||
host: process.env.DATABASE_HOST,
|
||||
database: process.env.DATABASE_NAME,
|
||||
port: parseInt(process.env.DATABASE_PORT!),
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
}),
|
||||
}),
|
||||
plugins: [new CamelCasePlugin()],
|
||||
});
|
||||
const migrator = new Migrator({
|
||||
db,
|
||||
provider: new FileMigrationProvider({
|
||||
fs,
|
||||
path,
|
||||
migrationFolder: path.join(__dirname, "migrations"),
|
||||
}),
|
||||
});
|
||||
|
||||
let error: any = null;
|
||||
let results: MigrationResult[] = [];
|
||||
|
||||
if (arg === "up:all") {
|
||||
const out = await migrator.migrateToLatest();
|
||||
results = out.results ?? [];
|
||||
error = out.error;
|
||||
} else if (arg === "up:one") {
|
||||
const out = await migrator.migrateUp();
|
||||
results = out.results ?? [];
|
||||
error = out.error;
|
||||
} else if (arg === "down:all") {
|
||||
const migrations = await migrator.getMigrations();
|
||||
for (const _ of migrations) {
|
||||
const out = await migrator.migrateDown();
|
||||
if (out.results) {
|
||||
results = results.concat(out.results);
|
||||
error = out.error;
|
||||
}
|
||||
}
|
||||
} else if (arg === "down:one") {
|
||||
const out = await migrator.migrateDown();
|
||||
if (out.results) {
|
||||
results = out.results ?? [];
|
||||
error = out.error;
|
||||
}
|
||||
}
|
||||
|
||||
results?.forEach((it) => {
|
||||
if (it.status === "Success") {
|
||||
console.log(
|
||||
`Migration "${it.migrationName} ${it.direction.toLowerCase()}" was executed successfully`,
|
||||
);
|
||||
} else if (it.status === "Error") {
|
||||
console.error(`Failed to execute migration "${it.migrationName}"`);
|
||||
}
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error("Failed to migrate");
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await db.destroy();
|
||||
};
|
||||
|
||||
const arg = process.argv.slice(2).pop();
|
||||
migrate(arg as string);
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("User")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("name", "text")
|
||||
.addColumn("email", "text", (col) => col.unique().notNull())
|
||||
.addColumn("emailVerified", "timestamptz")
|
||||
.addColumn("image", "text")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createTable("Account")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("userId", "uuid", (col) =>
|
||||
col.references("User.id").onDelete("cascade").notNull(),
|
||||
)
|
||||
.addColumn("type", "text", (col) => col.notNull())
|
||||
.addColumn("provider", "text", (col) => col.notNull())
|
||||
.addColumn("providerAccountId", "text", (col) => col.notNull())
|
||||
.addColumn("refresh_token", "text")
|
||||
.addColumn("access_token", "text")
|
||||
.addColumn("expires_at", "bigint")
|
||||
.addColumn("token_type", "text")
|
||||
.addColumn("scope", "text")
|
||||
.addColumn("id_token", "text")
|
||||
.addColumn("session_state", "text")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createTable("Session")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("userId", "uuid", (col) =>
|
||||
col.references("User.id").onDelete("cascade").notNull(),
|
||||
)
|
||||
.addColumn("sessionToken", "text", (col) => col.notNull().unique())
|
||||
.addColumn("expires", "timestamptz", (col) => col.notNull())
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createTable("VerificationToken")
|
||||
.addColumn("identifier", "text", (col) => col.notNull())
|
||||
.addColumn("token", "text", (col) => col.notNull().unique())
|
||||
.addColumn("expires", "timestamptz", (col) => col.notNull())
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("Account_userId_index")
|
||||
.on("Account")
|
||||
.column("userId")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("Session_userId_index")
|
||||
.on("Session")
|
||||
.column("userId")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("Account").ifExists().execute();
|
||||
await db.schema.dropTable("Session").ifExists().execute();
|
||||
await db.schema.dropTable("User").ifExists().execute();
|
||||
await db.schema.dropTable("VerificationToken").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("SignalBot")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("phone_number", "text")
|
||||
.addColumn("token", "text", (col) => col.unique().notNull())
|
||||
.addColumn("user_id", "uuid")
|
||||
.addColumn("name", "text")
|
||||
.addColumn("description", "text")
|
||||
.addColumn("qr_code", "text")
|
||||
.addColumn("verified", "boolean", (col) => col.notNull().defaultTo(false))
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("SignalBotToken")
|
||||
.on("SignalBot")
|
||||
.column("token")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("SignalBot").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("WhatsappBot")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("phone_number", "text")
|
||||
.addColumn("token", "text", (col) => col.unique().notNull())
|
||||
.addColumn("user_id", "uuid")
|
||||
.addColumn("name", "text")
|
||||
.addColumn("description", "text")
|
||||
.addColumn("qr_code", "text")
|
||||
.addColumn("verified", "boolean", (col) => col.notNull().defaultTo(false))
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("WhatsappBotToken")
|
||||
.on("WhatsappBot")
|
||||
.column("token")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("WhatsappBot").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("VoiceProvider")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("kind", "text", (col) => col.notNull())
|
||||
.addColumn("name", "text", (col) => col.notNull())
|
||||
.addColumn("description", "text")
|
||||
.addColumn("credentials", "jsonb", (col) => col.notNull())
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("VoiceProviderName")
|
||||
.on("VoiceProvider")
|
||||
.column("name")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createTable("VoiceLine")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("provider_id", "uuid", (col) =>
|
||||
col.notNull().references("VoiceProvider.id").onDelete("cascade"),
|
||||
)
|
||||
.addColumn("provider_line_sid", "text", (col) => col.notNull())
|
||||
.addColumn("number", "text", (col) => col.notNull())
|
||||
.addColumn("name", "text", (col) => col.notNull())
|
||||
.addColumn("description", "text")
|
||||
.addColumn("language", "text", (col) => col.notNull())
|
||||
.addColumn("voice", "text", (col) => col.notNull())
|
||||
.addColumn("prompt_text", "text")
|
||||
.addColumn("prompt_audio", "jsonb")
|
||||
.addColumn("audio_prompt_enabled", "boolean", (col) =>
|
||||
col.notNull().defaultTo(false),
|
||||
)
|
||||
.addColumn("audio_converted_at", "timestamptz")
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("VoiceLineProviderId")
|
||||
.on("VoiceLine")
|
||||
.column("provider_id")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("VoiceLineProviderLineSid")
|
||||
.on("VoiceLine")
|
||||
.column("provider_line_sid")
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("VoiceLineNumber")
|
||||
.on("VoiceLine")
|
||||
.column("number")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("VoiceLine").ifExists().execute();
|
||||
await db.schema.dropTable("VoiceProvider").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("FacebookBot")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("name", "text")
|
||||
.addColumn("description", "text")
|
||||
.addColumn("token", "text")
|
||||
.addColumn("page_access_token", "text")
|
||||
.addColumn("app_secret", "text")
|
||||
.addColumn("verify_token", "text")
|
||||
.addColumn("page_id", "text")
|
||||
.addColumn("app_id", "text")
|
||||
.addColumn("user_id", "uuid")
|
||||
.addColumn("verified", "boolean", (col) => col.notNull().defaultTo(false))
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("FacebookBotToken")
|
||||
.on("FacebookBot")
|
||||
.column("token")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("FacebookBot").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("Webhook")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("name", "text", (col) => col.notNull())
|
||||
.addColumn("description", "text")
|
||||
.addColumn("backend_type", "text", (col) => col.notNull())
|
||||
.addColumn("backend_id", "uuid", (col) => col.notNull())
|
||||
.addColumn("endpoint_url", "text", (col) =>
|
||||
col.notNull().check(sql`endpoint_url ~ '^https?://[^/]+'`),
|
||||
)
|
||||
.addColumn("http_method", "text", (col) =>
|
||||
col
|
||||
.notNull()
|
||||
.defaultTo("post")
|
||||
.check(sql`http_method in ('post', 'put')`),
|
||||
)
|
||||
.addColumn("headers", "jsonb")
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("WebhookBackendTypeBackendId")
|
||||
.on("Webhook")
|
||||
.column("backend_type")
|
||||
.column("backend_id")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("Webhook").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import { Kysely, sql } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema
|
||||
.createTable("Setting")
|
||||
.addColumn("id", "uuid", (col) =>
|
||||
col.primaryKey().defaultTo(sql`gen_random_uuid()`),
|
||||
)
|
||||
.addColumn("name", "text")
|
||||
.addColumn("value", "jsonb")
|
||||
.addColumn("created_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.addColumn("updated_at", "timestamptz", (col) =>
|
||||
col.notNull().defaultTo(sql`now()`),
|
||||
)
|
||||
.execute();
|
||||
|
||||
await db.schema
|
||||
.createIndex("SettingName")
|
||||
.on("Setting")
|
||||
.column("name")
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable("Setting").ifExists().execute();
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import { Kysely } from "kysely";
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.alterTable("User").addColumn("role", "text").execute();
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.alterTable("User").dropColumn("role").execute();
|
||||
}
|
||||
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
set -e
|
||||
echo "running migrations"
|
||||
npm run migrate:up:all
|
||||
(cd ../bridge-migrations/ && npm run migrate:up:all)
|
||||
echo "starting bridge-frontend"
|
||||
exec dumb-init npm run start
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue