From fa044a77ab42e45f03b00cd7588d014827f0379d Mon Sep 17 00:00:00 2001 From: Iaroslav Gryshaiev Date: Tue, 28 Jan 2025 19:19:28 +0100 Subject: [PATCH] feat(deployment): adds deployment setting table refs #714 --- apps/api/drizzle.config.ts | 2 +- apps/api/drizzle/0008_amused_magdalene.sql | 17 + apps/api/drizzle/meta/0008_snapshot.json | 388 ++++++++++++++++++ apps/api/drizzle/meta/_journal.json | 7 + .../src/core/providers/postgres.provider.ts | 3 +- .../deployment-setting.schema.ts | 22 + .../api/src/deployment/model-schemas/index.ts | 1 + 7 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 apps/api/drizzle/0008_amused_magdalene.sql create mode 100644 apps/api/drizzle/meta/0008_snapshot.json create mode 100644 apps/api/src/deployment/model-schemas/deployment-setting/deployment-setting.schema.ts create mode 100644 apps/api/src/deployment/model-schemas/index.ts diff --git a/apps/api/drizzle.config.ts b/apps/api/drizzle.config.ts index 135f1d065..acf861cbc 100644 --- a/apps/api/drizzle.config.ts +++ b/apps/api/drizzle.config.ts @@ -5,7 +5,7 @@ import { defineConfig } from "drizzle-kit"; import { config } from "./src/core/config"; export default defineConfig({ - schema: ["./src/billing/model-schemas", "./src/user/model-schemas"], + schema: ["billing", "user", "deployment"].map(schema => `./src/${schema}/model-schemas`), out: "./drizzle", dialect: "postgresql", dbCredentials: { diff --git a/apps/api/drizzle/0008_amused_magdalene.sql b/apps/api/drizzle/0008_amused_magdalene.sql new file mode 100644 index 000000000..8e6ac7ad2 --- /dev/null +++ b/apps/api/drizzle/0008_amused_magdalene.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS "deployment_settings" ( + "id" serial PRIMARY KEY NOT NULL, + "user_id" uuid NOT NULL, + "dseq" varchar NOT NULL, + "address" varchar NOT NULL, + "auto_top_up_enabled" boolean DEFAULT false NOT NULL, + "predicted_closed_height" bigint NOT NULL, + "created_at" timestamp DEFAULT now(), + "updated_at" timestamp DEFAULT now(), + CONSTRAINT "dseq_address_idx" UNIQUE("dseq","address") +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "deployment_settings" ADD CONSTRAINT "deployment_settings_user_id_userSetting_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."userSetting"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/apps/api/drizzle/meta/0008_snapshot.json b/apps/api/drizzle/meta/0008_snapshot.json new file mode 100644 index 000000000..f8add720f --- /dev/null +++ b/apps/api/drizzle/meta/0008_snapshot.json @@ -0,0 +1,388 @@ +{ + "id": "bde9844d-17e8-42b2-9b5e-343025b6bf67", + "prevId": "7b2b63b9-6539-46b0-ae35-88893697cfde", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.user_wallets": { + "name": "user_wallets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "address": { + "name": "address", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "deployment_allowance": { + "name": "deployment_allowance", + "type": "numeric(20, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0.00'" + }, + "fee_allowance": { + "name": "fee_allowance", + "type": "numeric(20, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0.00'" + }, + "trial": { + "name": "trial", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_wallets_user_id_userSetting_id_fk": { + "name": "user_wallets_user_id_userSetting_id_fk", + "tableFrom": "user_wallets", + "tableTo": "userSetting", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_wallets_user_id_unique": { + "name": "user_wallets_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + }, + "user_wallets_address_unique": { + "name": "user_wallets_address_unique", + "nullsNotDistinct": false, + "columns": [ + "address" + ] + } + } + }, + "public.checkout_sessions": { + "name": "checkout_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "uuid_generate_v4()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "checkout_sessions_user_id_userSetting_id_fk": { + "name": "checkout_sessions_user_id_userSetting_id_fk", + "tableFrom": "checkout_sessions", + "tableTo": "userSetting", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "checkout_sessions_session_id_unique": { + "name": "checkout_sessions_session_id_unique", + "nullsNotDistinct": false, + "columns": [ + "session_id" + ] + } + } + }, + "public.userSetting": { + "name": "userSetting", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "uuid_generate_v4()" + }, + "userId": { + "name": "userId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "emailVerified": { + "name": "emailVerified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "stripeCustomerId": { + "name": "stripeCustomerId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscribedToNewsletter": { + "name": "subscribedToNewsletter", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "youtubeUsername": { + "name": "youtubeUsername", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "twitterUsername": { + "name": "twitterUsername", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "githubUsername": { + "name": "githubUsername", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "last_ip": { + "name": "last_ip", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "last_user_agent": { + "name": "last_user_agent", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "last_fingerprint": { + "name": "last_fingerprint", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "userSetting_userId_unique": { + "name": "userSetting_userId_unique", + "nullsNotDistinct": false, + "columns": [ + "userId" + ] + }, + "userSetting_username_unique": { + "name": "userSetting_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + } + }, + "public.deployment_settings": { + "name": "deployment_settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "dseq": { + "name": "dseq", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "auto_top_up_enabled": { + "name": "auto_top_up_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "predicted_closed_height": { + "name": "predicted_closed_height", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_settings_user_id_userSetting_id_fk": { + "name": "deployment_settings_user_id_userSetting_id_fk", + "tableFrom": "deployment_settings", + "tableTo": "userSetting", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "dseq_address_idx": { + "name": "dseq_address_idx", + "nullsNotDistinct": false, + "columns": [ + "dseq", + "address" + ] + } + } + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/api/drizzle/meta/_journal.json b/apps/api/drizzle/meta/_journal.json index 51273d550..6d7ec4819 100644 --- a/apps/api/drizzle/meta/_journal.json +++ b/apps/api/drizzle/meta/_journal.json @@ -57,6 +57,13 @@ "when": 1732626493525, "tag": "0007_lethal_masked_marvel", "breakpoints": true + }, + { + "idx": 8, + "version": "7", + "when": 1738088327324, + "tag": "0008_amused_magdalene", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/src/core/providers/postgres.provider.ts b/apps/api/src/core/providers/postgres.provider.ts index caea10879..0ba721079 100644 --- a/apps/api/src/core/providers/postgres.provider.ts +++ b/apps/api/src/core/providers/postgres.provider.ts @@ -8,13 +8,14 @@ import { container, inject } from "tsyringe"; import * as billingSchemas from "@src/billing/model-schemas"; import { config } from "@src/core/config"; import { PostgresLoggerService } from "@src/core/services/postgres-logger/postgres-logger.service"; +import * as deploymentSchemas from "@src/deployment/model-schemas"; import * as userSchemas from "@src/user/model-schemas"; const logger = LoggerService.forContext("POSTGRES"); const migrationClient = postgres(config.POSTGRES_DB_URI, { max: 1, onnotice: logger.info.bind(logger) }); const appClient = postgres(config.POSTGRES_DB_URI, { max: config.POSTGRES_MAX_CONNECTIONS, onnotice: logger.info.bind(logger) }); -const schema = { ...userSchemas, ...billingSchemas }; +const schema = { ...userSchemas, ...billingSchemas, ...deploymentSchemas }; const drizzleOptions = { logger: new DefaultLogger({ writer: new PostgresLoggerService({ useFormat: config.SQL_LOG_FORMAT === "pretty" }) }), schema }; const pgMigrationDatabase = drizzle(migrationClient, drizzleOptions); diff --git a/apps/api/src/deployment/model-schemas/deployment-setting/deployment-setting.schema.ts b/apps/api/src/deployment/model-schemas/deployment-setting/deployment-setting.schema.ts new file mode 100644 index 000000000..d316f9676 --- /dev/null +++ b/apps/api/src/deployment/model-schemas/deployment-setting/deployment-setting.schema.ts @@ -0,0 +1,22 @@ +import { bigint, boolean, pgTable, serial, timestamp, unique, uuid, varchar } from "drizzle-orm/pg-core"; + +import { Users } from "@src/user/model-schemas"; + +export const DeploymentSettings = pgTable( + "deployment_settings", + { + id: serial("id").primaryKey(), + userId: uuid("user_id") + .references(() => Users.id, { onDelete: "cascade" }) + .notNull(), + dseq: varchar("dseq").notNull(), + address: varchar("address").notNull(), + autoTopUpEnabled: boolean("auto_top_up_enabled").notNull().default(false), + predictedClosedHeight: bigint("predicted_closed_height", { mode: "number" }).notNull(), + createdAt: timestamp("created_at").defaultNow(), + updatedAt: timestamp("updated_at").defaultNow() + }, + table => ({ + dseqAddressIdx: unique("dseq_address_idx").on(table.dseq, table.address) + }) +); diff --git a/apps/api/src/deployment/model-schemas/index.ts b/apps/api/src/deployment/model-schemas/index.ts new file mode 100644 index 000000000..ce76a6b80 --- /dev/null +++ b/apps/api/src/deployment/model-schemas/index.ts @@ -0,0 +1 @@ +export * from "./deployment-setting/deployment-setting.schema";