diff --git a/apps/api/env/.env.functional.test b/apps/api/env/.env.functional.test index 9c441a76a..060a5554f 100644 --- a/apps/api/env/.env.functional.test +++ b/apps/api/env/.env.functional.test @@ -1,5 +1,4 @@ -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@localhost:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@localhost:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-users MASTER_WALLET_MNEMONIC="motion isolate mother convince snack twenty tumble boost elbow bundle modify balcony" UAKT_TOP_UP_MASTER_WALLET_MNEMONIC="since bread kind field rookie stairs elephant tent horror rice gain tongue collect goose rural garment cover client biology toe ability boat afford mind" @@ -23,4 +22,6 @@ ALLOWED_CHECKOUT_REFERRERS=["http://localhost:3000"] STRIPE_CHECKOUT_REDIRECT_URL=http://localhost:3000 AUTH0_M2M_DOMAIN=AUTH0_M2M_DOMAIN AUTH0_M2M_SECRET=AUTH0_SECRET -AUTH0_M2M_CLIENT_ID=AUTH0_CLIENT_ID \ No newline at end of file +AUTH0_M2M_CLIENT_ID=AUTH0_CLIENT_ID +STD_OUT_LOG_FORMAT=pretty +SQL_LOG_FORMAT=pretty \ No newline at end of file diff --git a/apps/api/env/.env.local.sample b/apps/api/env/.env.local.sample index 2a0f14599..65252a7cb 100644 --- a/apps/api/env/.env.local.sample +++ b/apps/api/env/.env.local.sample @@ -1,8 +1,6 @@ NETWORK=sandbox DB_HOST_WITH_DEFAULT=${DB_HOST:-localhost} -AKASH_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-users ANONYMOUS_USER_TOKEN_SECRET=ANONYMOUS_USER_TOKEN_SECRET MASTER_WALLET_MNEMONIC=MASTER_WALLET_MNEMONIC diff --git a/apps/api/env/.env.sample b/apps/api/env/.env.sample index e7ed98cb2..df72596f9 100644 --- a/apps/api/env/.env.sample +++ b/apps/api/env/.env.sample @@ -1,15 +1,14 @@ # Secrets -AKASH_DATABASE_CS= +POSTGRES_DB_URI= +CHAIN_INDEXER_POSTGRES_DB_URI= GITHUB_PAT= ANONYMOUS_USER_TOKEN_SECRET= HealthChecks_SyncAKTMarketData= MASTER_WALLET_MNEMONIC= -POSTGRES_DB_URI= SECRET_TOKEN= SENTRY_DSN= STRIPE_SECRET_KEY= STRIPE_PRODUCT_ID= -USER_DATABASE_CS= # Configuration CORS_WEBSITE_URLS= diff --git a/apps/api/env/.env.unit.test b/apps/api/env/.env.unit.test index 1abebe90f..20c1a9062 100644 --- a/apps/api/env/.env.unit.test +++ b/apps/api/env/.env.unit.test @@ -1,5 +1,4 @@ -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@localhost:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@localhost:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-users MASTER_WALLET_MNEMONIC="motion isolate mother convince snack twenty tumble boost elbow bundle modify balcony" UAKT_TOP_UP_MASTER_WALLET_MNEMONIC="since bread kind field rookie stairs elephant tent horror rice gain tongue collect goose rural garment cover client biology toe ability boat afford mind" diff --git a/apps/api/jest.config.js b/apps/api/jest.config.js index ebaac8ad9..cf4b99b15 100644 --- a/apps/api/jest.config.js +++ b/apps/api/jest.config.js @@ -5,7 +5,7 @@ const MAP_ALIASES = { const common = { transform: { - "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "./tsconfig.json" }] + "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "./test/tsconfig.json" }] }, rootDir: ".", moduleNameMapper: { diff --git a/apps/api/package.json b/apps/api/package.json index ea399587c..fad291dd2 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -23,8 +23,8 @@ "prod": "doppler run -- node dist/server.js", "release": "release-it", "start": "webpack --config webpack.dev.js --watch", - "test": "jest --selectProjects unit functional", - "test:cov": "jest --selectProjects unit functional --coverage", + "test": "jest --selectProjects unit functional --runInBand", + "test:cov": "jest --selectProjects unit functional --coverage --runInBand", "test:functional": "jest --selectProjects functional --runInBand", "test:functional:cov": "npm run test:functional -- --coverage", "test:functional:watch": "npm run test:functional -- --watch", diff --git a/apps/api/src/chain/config/env.config.ts b/apps/api/src/chain/config/env.config.ts new file mode 100644 index 000000000..ee2b04216 --- /dev/null +++ b/apps/api/src/chain/config/env.config.ts @@ -0,0 +1,5 @@ +import { z } from "zod"; + +export const envSchema = z.object({ + CHAIN_INDEXER_POSTGRES_DB_URI: z.string() +}); diff --git a/apps/api/src/chain/services/chain-config/chain-config.service.ts b/apps/api/src/chain/services/chain-config/chain-config.service.ts new file mode 100644 index 000000000..fd5bc7763 --- /dev/null +++ b/apps/api/src/chain/services/chain-config/chain-config.service.ts @@ -0,0 +1,11 @@ +import { singleton } from "tsyringe"; + +import { envSchema } from "@src/chain/config/env.config"; +import { ConfigService } from "@src/core/services/config/config.service"; + +@singleton() +export class ChainConfigService extends ConfigService { + constructor() { + super({ envSchema }); + } +} diff --git a/apps/api/src/core/config/env.config.ts b/apps/api/src/core/config/env.config.ts index 58d3b8395..0ea37a5bc 100644 --- a/apps/api/src/core/config/env.config.ts +++ b/apps/api/src/core/config/env.config.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -const envSchema = z.object({ +export const envSchema = z.object({ LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).optional().default("info"), STD_OUT_LOG_FORMAT: z.enum(["json", "pretty"]).optional().default("json"), SQL_LOG_FORMAT: z.enum(["raw", "pretty"]).optional().default("raw"), diff --git a/apps/api/src/core/services/core-config/core-config.service.ts b/apps/api/src/core/services/core-config/core-config.service.ts new file mode 100644 index 000000000..21b5adb42 --- /dev/null +++ b/apps/api/src/core/services/core-config/core-config.service.ts @@ -0,0 +1,11 @@ +import { singleton } from "tsyringe"; + +import { envSchema } from "@src/core/config/env.config"; +import { ConfigService } from "@src/core/services/config/config.service"; + +@singleton() +export class CoreConfigService extends ConfigService { + constructor() { + super({ envSchema }); + } +} diff --git a/apps/api/src/db/dbConnection.ts b/apps/api/src/db/dbConnection.ts index be9581578..5ce25d29d 100644 --- a/apps/api/src/db/dbConnection.ts +++ b/apps/api/src/db/dbConnection.ts @@ -1,37 +1,23 @@ -import { chainDefinitions } from "@akashnetwork/database/chainDefinitions"; -import { chainModels, getChainModels, userModels } from "@akashnetwork/database/dbSchemas"; +import { chainModels, userModels } from "@akashnetwork/database/dbSchemas"; import { Template, TemplateFavorite, UserSetting } from "@akashnetwork/database/dbSchemas/user"; import pg from "pg"; import { Transaction as DbTransaction } from "sequelize"; import { Sequelize } from "sequelize-typescript"; +import { container } from "tsyringe"; -import { config } from "@src/core/config"; +import { ChainConfigService } from "@src/chain/services/chain-config/chain-config.service"; +import { CoreConfigService } from "@src/core/services/core-config/core-config.service"; import { PostgresLoggerService } from "@src/core/services/postgres-logger/postgres-logger.service"; -import { env } from "@src/utils/env"; -function isValidNetwork(network: string): network is keyof typeof csMap { - return network in csMap; -} - -const csMap = { - mainnet: env.AKASH_DATABASE_CS, - testnet: env.AKASH_TESTNET_DATABASE_CS, - sandbox: env.AKASH_SANDBOX_DATABASE_CS -}; - -if (!isValidNetwork(env.NETWORK)) { - throw new Error(`Invalid network: ${env.NETWORK}`); -} +const indexerDbUri = container.resolve(ChainConfigService).get("CHAIN_INDEXER_POSTGRES_DB_URI"); +const coreConfig = container.resolve(CoreConfigService); +const dbUri = coreConfig.get("POSTGRES_DB_URI"); -if (!csMap[env.NETWORK]) { - throw new Error(`Missing connection string for network: ${env.NETWORK}`); -} - -const logger = new PostgresLoggerService({ orm: "sequelize", useFormat: config.SQL_LOG_FORMAT === "pretty" }); +const logger = new PostgresLoggerService({ orm: "sequelize", useFormat: coreConfig.get("SQL_LOG_FORMAT") === "pretty" }); const logging = (msg: string) => logger.write(msg); pg.defaults.parseInt8 = true; -export const chainDb = new Sequelize(csMap[env.NETWORK], { +export const chainDb = new Sequelize(indexerDbUri, { dialectModule: pg, logging, logQueryParameters: true, @@ -43,28 +29,7 @@ export const chainDb = new Sequelize(csMap[env.NETWORK], { models: chainModels }); -export const chainDbs: { [key: string]: Sequelize } = Object.keys(chainDefinitions) - .filter(x => chainDefinitions[x].connectionString) - .reduce( - (obj, chain) => ({ - ...obj, - [chain]: new Sequelize(chainDefinitions[chain].connectionString, { - dialectModule: pg, - logging, - logQueryParameters: true, - repositoryMode: true, - transactionType: DbTransaction.TYPES.IMMEDIATE, - define: { - timestamps: false, - freezeTableName: true - }, - models: getChainModels(chain) - }) - }), - {} - ); - -export const userDb = new Sequelize(env.USER_DATABASE_CS, { +export const userDb = new Sequelize(dbUri, { dialectModule: pg, logging, logQueryParameters: true, @@ -82,4 +47,4 @@ export async function syncUserSchema() { await TemplateFavorite.sync(); } -export const closeConnections = async () => await Promise.all([chainDb.close(), userDb.close(), ...Object.values(chainDbs).map(db => db.close())]); +export const closeConnections = async () => await Promise.all([chainDb.close(), userDb.close()]); diff --git a/apps/api/src/utils/env.ts b/apps/api/src/utils/env.ts index 4e5cccafd..64d212d0f 100644 --- a/apps/api/src/utils/env.ts +++ b/apps/api/src/utils/env.ts @@ -5,10 +5,7 @@ export const env = z CORS_WEBSITE_URLS: z.string().optional(), NODE_ENV: z.string().optional(), HEALTHCHECKS_ENABLED: z.string().optional(), - AKASH_DATABASE_CS: z.string().optional(), - AKASH_TESTNET_DATABASE_CS: z.string().optional(), - AKASH_SANDBOX_DATABASE_CS: z.string().optional(), - USER_DATABASE_CS: z.string().optional(), + CHAIN_INDEXER_POSTGRES_DB_URI: z.string(), NETWORK: z.string().default("mainnet"), REST_API_NODE_URL: z.string().optional(), SERVER_ORIGIN: z.string().optional().default("http://localhost:3080"),