This commit is contained in:
2026-08-28 17:31:02 +02:00
commit 2b30e8bd39
694 changed files with 49243 additions and 0 deletions
+224
View File
@@ -0,0 +1,224 @@
import {
AppConfig,
CoingeckoConfig,
EncryptionConfig,
InvoiceConfig,
JwtConfig,
KrakenConfig,
MulterConfig,
OrderConfig,
PostgresConfig,
ShopSettingsConfig
} from '../types/Config';
import { MoneroNetwork } from '../types/MoneroNetwork';
import { MoneroWalletConfig } from '../types/MoneroWalletConfig';
import { MoneroConfirmationTier } from '../types/MoneroConfirmationTier';
import { NodeEnv } from '../types/NodeEnv';
import { ShopFiatCurrency } from '../types/ShopFiatCurrency';
import { PaymentMethod } from '../modules/payment/types/PaymentMethod';
import { SimplexConfig } from '../types/SimplexConfig';
const env = (key: string): string => process.env[key] || '';
const envInt = (key: string): number => parseInt(env(key), 10);
const isEnabled = (key: string): boolean => env(key) === 'true';
export const getPostgresConfig = (): PostgresConfig => {
return {
type: 'postgres',
url: `postgres://${env('POSTGRES_USER')}:${env('POSTGRES_PASSWORD')}@${env('POSTGRES_HOST')}:${env('POSTGRES_PORT')}/${env('POSTGRES_DB')}`,
host: env('POSTGRES_HOST'),
username: env('POSTGRES_USER'),
password: env('POSTGRES_PASSWORD'),
port: envInt('POSTGRES_PORT'),
database: env('POSTGRES_DB'),
entities: [__dirname + '/../modules/**/entities/*{.ts,.js}'],
migrations: [__dirname + '/../database/migrations/*{.ts,.js}'],
migrationsRun: isEnabled('POSTGRES_MIGRATIONS_RUN')
};
};
export const getAppConfig = (): AppConfig => {
const rawOrigins = env('CORS_ORIGINS');
return {
port: envInt('BACKEND_PORT'),
nodeEnv: env('NODE_ENV') as NodeEnv,
corsOrigins: rawOrigins
.split(',')
.map(o => o.trim())
.filter(Boolean),
cmsPassword: env('CMS_PASSWORD'),
captcha: {
length: envInt('CAPTCHA_LENGTH')
},
throttle: {
ttlMs: envInt('THROTTLE_TTL_MS'),
limit: envInt('THROTTLE_LIMIT')
},
signedCookie: {
jwtSecret: env('SIGNED_COOKIE_JWT_SECRET'),
feedback: {
cookieName: env('SIGNED_COOKIE_FEEDBACK_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_FEEDBACK_EXPIRES_IN_MS')
},
cart: {
cookieName: env('SIGNED_COOKIE_CART_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_CART_EXPIRES_IN_MS')
},
captcha: {
cookieName: env('SIGNED_COOKIE_CAPTCHA_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_CAPTCHA_EXPIRES_IN_MS')
},
discount: {
cookieName: env('SIGNED_COOKIE_DISCOUNT_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_DISCOUNT_EXPIRES_IN_MS')
},
error: {
cookieName: env('SIGNED_COOKIE_ERROR_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_ERROR_EXPIRES_IN_MS')
},
checkoutSession: {
cookieName: env('SIGNED_COOKIE_CHECKOUT_SESSION_NAME'),
expiresInMs: envInt('ORDER_CHECKOUT_VALIDITY_MS')
},
orderAuth: {
cookieName: env('SIGNED_COOKIE_ORDER_AUTH_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_ORDER_AUTH_EXPIRES_IN_MS')
},
theme: {
cookieName: env('SIGNED_COOKIE_THEME_NAME'),
expiresInMs: envInt('SIGNED_COOKIE_THEME_EXPIRES_IN_MS')
}
},
validation: {
productTitleMaxLength: envInt('VALIDATION_PRODUCT_TITLE_MAX_LENGTH'),
categoryNameMaxLength: envInt('VALIDATION_CATEGORY_NAME_MAX_LENGTH'),
discountCodeMaxLength: envInt('VALIDATION_DISCOUNT_CODE_MAX_LENGTH'),
variantImagesMax: envInt('VALIDATION_VARIANT_IMAGES_MAX'),
digitalStockAttachmentsMax: envInt('VALIDATION_DIGITAL_STOCK_ATTACHMENTS_MAX'),
shippingNoteMinLength: envInt('VALIDATION_SHIPPING_NOTE_MIN_LENGTH'),
shippingNoteMaxLength: envInt('VALIDATION_SHIPPING_NOTE_MAX_LENGTH'),
orderMessageMaxLength: envInt('VALIDATION_ORDER_MESSAGE_MAX_LENGTH')
}
};
};
export const getJwtConfig = (): JwtConfig => {
return {
secret: env('JWT_SECRET'),
expiresInMs: envInt('JWT_EXPIRES_IN_MS')
};
};
export const getProductThumbMulterConfig = (): MulterConfig => {
const allowedMimes = env('MULTER_PRODUCT_THUMB_ALLOWED_MIMES')
.split(',')
.map(v => v.trim())
.filter(Boolean);
const maxFileBytes = envInt('MULTER_PRODUCT_THUMB_MAX_FILE_BYTES');
return { allowedMimes, maxFileBytes };
};
export const getShopLogoMulterConfig = (): MulterConfig => {
const allowedMimes = env('MULTER_SHOP_LOGO_ALLOWED_MIMES')
.split(',')
.map(v => v.trim())
.filter(Boolean);
const maxFileBytes = envInt('MULTER_SHOP_LOGO_MAX_FILE_BYTES');
return { allowedMimes, maxFileBytes };
};
export const getShopFaviconMulterConfig = (): MulterConfig => {
const allowedMimes = env('MULTER_SHOP_FAVICON_ALLOWED_MIMES')
.split(',')
.map(v => v.trim())
.filter(Boolean);
const maxFileBytes = envInt('MULTER_SHOP_FAVICON_MAX_FILE_BYTES');
return { allowedMimes, maxFileBytes };
};
export const getDigitalStockAttachmentMulterConfig = (): MulterConfig => {
const allowedMimes = env('MULTER_DIGITAL_STOCK_ATTACHMENT_ALLOWED_MIMES')
.split(',')
.map(v => v.trim())
.filter(Boolean);
const maxFileBytes = envInt('MULTER_DIGITAL_STOCK_ATTACHMENT_MAX_FILE_BYTES');
return { allowedMimes, maxFileBytes };
};
export const getCoingeckoConfig = (): CoingeckoConfig => {
return {
apiBaseUrl: env('COINGECKO_API_BASE_URL'),
xmrRateFetchTimeoutMs: envInt('COINGECKO_XMR_RATE_FETCH_TIMEOUT_MS')
};
};
export const getKrakenConfig = (): KrakenConfig => {
return {
apiBaseUrl: env('KRAKEN_API_BASE_URL'),
xmrRateFetchTimeoutMs: envInt('KRAKEN_XMR_RATE_FETCH_TIMEOUT_MS')
};
};
export const getEncryptionConfig = (): EncryptionConfig => ({
keyBase64: env('BASE64_ENCRYPTION_KEY')
});
export const getShopSettingsConfig = (): ShopSettingsConfig => ({
shopName: env('SHOP_NAME'),
shopFiatCurrency: env('SHOP_FIAT_CURRENCY') as ShopFiatCurrency,
monero: {
confirmationTiers: JSON.parse(env('MONERO_CONFIRMATION_TIERS')) as MoneroConfirmationTier[]
}
});
export const getOrderConfig = (): OrderConfig => ({
checkoutValidityMs: envInt('ORDER_CHECKOUT_VALIDITY_MS'),
shippingPaymentValidityMs: envInt('ORDER_SHIPPING_PAYMENT_VALIDITY_MS'),
checkoutStatusRefreshSec: envInt('ORDER_CHECKOUT_STATUS_REFRESH_SEC'),
dataRetentionDays: envInt('ORDER_DATA_RETENTION_DAYS')
});
export const getInvoiceConfig = (): InvoiceConfig => ({
minByMethod: {
[PaymentMethod.Xmr]: String(envInt('MONERO_MIN_INCOMING_ATOMIC'))
}
});
export const getMoneroWalletConfig = (): MoneroWalletConfig => ({
network: env('MONERO_NETWORK') as MoneroNetwork,
rpcUrl: `http://${env('MONERO_WALLET_RPC_HOST')}:${envInt('MONERO_WALLET_RPC_PORT')}/json_rpc`,
daemonRpcUrl: `http://${env('MONERO_DAEMON_ADDRESS')}/json_rpc`,
username: env('MONERO_WALLET_RPC_USERNAME'),
password: env('MONERO_WALLET_RPC_PASSWORD'),
rpcTimeoutMs: envInt('MONERO_WALLET_RPC_TIMEOUT_MS')
});
export const getSimplexConfig = (): SimplexConfig => ({
wsUrl: env('SIMPLEX_WS_URL'),
botDisplayName: env('SIMPLEX_BOT_DISPLAY_NAME')
});
export default () => ({
postgres: getPostgresConfig(),
app: getAppConfig(),
jwt: getJwtConfig(),
coingecko: getCoingeckoConfig(),
kraken: getKrakenConfig(),
encryption: getEncryptionConfig(),
shopSettings: getShopSettingsConfig(),
order: getOrderConfig(),
invoice: getInvoiceConfig(),
moneroWallet: getMoneroWalletConfig(),
simplex: getSimplexConfig()
});