Compare commits

..

14 Commits

Author SHA1 Message Date
Owen Schwartz
b6c9046405 New translations en-us.json (Spanish) 2026-03-21 10:56:55 -07:00
Owen Schwartz
ea2ec84f08 New translations en-us.json (Norwegian Bokmal) 2026-03-21 10:56:54 -07:00
Owen Schwartz
40a14ac5f6 New translations en-us.json (Chinese Simplified) 2026-03-21 10:56:53 -07:00
Owen Schwartz
78169f087f New translations en-us.json (Turkish) 2026-03-21 10:56:51 -07:00
Owen Schwartz
4021107d08 New translations en-us.json (Russian) 2026-03-21 10:56:50 -07:00
Owen Schwartz
e78aaeb344 New translations en-us.json (Portuguese) 2026-03-21 10:56:48 -07:00
Owen Schwartz
0087ca997d New translations en-us.json (Polish) 2026-03-21 10:56:47 -07:00
Owen Schwartz
61d4d314d6 New translations en-us.json (Dutch) 2026-03-21 10:56:46 -07:00
Owen Schwartz
2e8b4ddbdb New translations en-us.json (Korean) 2026-03-21 10:56:44 -07:00
Owen Schwartz
3996b86f14 New translations en-us.json (Italian) 2026-03-21 10:56:43 -07:00
Owen Schwartz
7388ef8588 New translations en-us.json (German) 2026-03-21 10:56:42 -07:00
Owen Schwartz
bb2edb23e5 New translations en-us.json (Czech) 2026-03-21 10:56:40 -07:00
Owen Schwartz
4cad384476 New translations en-us.json (Bulgarian) 2026-03-21 10:56:39 -07:00
Owen Schwartz
ba07eb1303 New translations en-us.json (French) 2026-03-21 10:56:37 -07:00
18 changed files with 43 additions and 113 deletions

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Въведете конфигурационния токен от сървърната конзола.", "setupTokenDescription": "Въведете конфигурационния токен от сървърната конзола.",
"setupTokenRequired": "Необходим е конфигурационен токен", "setupTokenRequired": "Необходим е конфигурационен токен",
"actionUpdateSite": "Актуализиране на сайт", "actionUpdateSite": "Актуализиране на сайт",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Изброяване на позволените роли за сайта", "actionListSiteRoles": "Изброяване на позволените роли за сайта",
"actionCreateResource": "Създаване на ресурс", "actionCreateResource": "Създаване на ресурс",
"actionDeleteResource": "Изтриване на ресурс", "actionDeleteResource": "Изтриване на ресурс",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Zadejte nastavovací token z konzole serveru.", "setupTokenDescription": "Zadejte nastavovací token z konzole serveru.",
"setupTokenRequired": "Je vyžadován token nastavení", "setupTokenRequired": "Je vyžadován token nastavení",
"actionUpdateSite": "Aktualizovat stránku", "actionUpdateSite": "Aktualizovat stránku",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Seznam povolených rolí webu", "actionListSiteRoles": "Seznam povolených rolí webu",
"actionCreateResource": "Vytvořit zdroj", "actionCreateResource": "Vytvořit zdroj",
"actionDeleteResource": "Odstranit dokument", "actionDeleteResource": "Odstranit dokument",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Geben Sie das Setup-Token von der Serverkonsole ein.", "setupTokenDescription": "Geben Sie das Setup-Token von der Serverkonsole ein.",
"setupTokenRequired": "Setup-Token ist erforderlich", "setupTokenRequired": "Setup-Token ist erforderlich",
"actionUpdateSite": "Standorte aktualisieren", "actionUpdateSite": "Standorte aktualisieren",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Erlaubte Standort-Rollen auflisten", "actionListSiteRoles": "Erlaubte Standort-Rollen auflisten",
"actionCreateResource": "Ressource erstellen", "actionCreateResource": "Ressource erstellen",
"actionDeleteResource": "Ressource löschen", "actionDeleteResource": "Ressource löschen",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Ingrese el token de configuración desde la consola del servidor.", "setupTokenDescription": "Ingrese el token de configuración desde la consola del servidor.",
"setupTokenRequired": "Se requiere el token de configuración", "setupTokenRequired": "Se requiere el token de configuración",
"actionUpdateSite": "Actualizar sitio", "actionUpdateSite": "Actualizar sitio",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Lista de roles permitidos del sitio", "actionListSiteRoles": "Lista de roles permitidos del sitio",
"actionCreateResource": "Crear Recurso", "actionCreateResource": "Crear Recurso",
"actionDeleteResource": "Eliminar Recurso", "actionDeleteResource": "Eliminar Recurso",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Entrez le jeton de configuration depuis la console du serveur.", "setupTokenDescription": "Entrez le jeton de configuration depuis la console du serveur.",
"setupTokenRequired": "Le jeton de configuration est requis.", "setupTokenRequired": "Le jeton de configuration est requis.",
"actionUpdateSite": "Mettre à jour un site", "actionUpdateSite": "Mettre à jour un site",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Lister les rôles autorisés du site", "actionListSiteRoles": "Lister les rôles autorisés du site",
"actionCreateResource": "Créer une ressource", "actionCreateResource": "Créer une ressource",
"actionDeleteResource": "Supprimer une ressource", "actionDeleteResource": "Supprimer une ressource",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Inserisci il token di configurazione dalla console del server.", "setupTokenDescription": "Inserisci il token di configurazione dalla console del server.",
"setupTokenRequired": "Il token di configurazione è richiesto", "setupTokenRequired": "Il token di configurazione è richiesto",
"actionUpdateSite": "Aggiorna Sito", "actionUpdateSite": "Aggiorna Sito",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Elenca Ruoli Sito Consentiti", "actionListSiteRoles": "Elenca Ruoli Sito Consentiti",
"actionCreateResource": "Crea Risorsa", "actionCreateResource": "Crea Risorsa",
"actionDeleteResource": "Elimina Risorsa", "actionDeleteResource": "Elimina Risorsa",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "서버 콘솔에서 설정 토큰 입력.", "setupTokenDescription": "서버 콘솔에서 설정 토큰 입력.",
"setupTokenRequired": "설정 토큰이 필요합니다", "setupTokenRequired": "설정 토큰이 필요합니다",
"actionUpdateSite": "사이트 업데이트", "actionUpdateSite": "사이트 업데이트",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "허용된 사이트 역할 목록", "actionListSiteRoles": "허용된 사이트 역할 목록",
"actionCreateResource": "리소스 생성", "actionCreateResource": "리소스 생성",
"actionDeleteResource": "리소스 삭제", "actionDeleteResource": "리소스 삭제",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Skriv inn oppsetttoken fra serverkonsollen.", "setupTokenDescription": "Skriv inn oppsetttoken fra serverkonsollen.",
"setupTokenRequired": "Oppsetttoken er nødvendig", "setupTokenRequired": "Oppsetttoken er nødvendig",
"actionUpdateSite": "Oppdater område", "actionUpdateSite": "Oppdater område",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "List opp tillatte områderoller", "actionListSiteRoles": "List opp tillatte områderoller",
"actionCreateResource": "Opprett ressurs", "actionCreateResource": "Opprett ressurs",
"actionDeleteResource": "Slett ressurs", "actionDeleteResource": "Slett ressurs",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Voer het setup-token in vanaf de serverconsole.", "setupTokenDescription": "Voer het setup-token in vanaf de serverconsole.",
"setupTokenRequired": "Setup-token is vereist", "setupTokenRequired": "Setup-token is vereist",
"actionUpdateSite": "Site bijwerken", "actionUpdateSite": "Site bijwerken",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Toon toegestane sitenollen", "actionListSiteRoles": "Toon toegestane sitenollen",
"actionCreateResource": "Bron maken", "actionCreateResource": "Bron maken",
"actionDeleteResource": "Document verwijderen", "actionDeleteResource": "Document verwijderen",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Wprowadź token konfiguracji z konsoli serwera.", "setupTokenDescription": "Wprowadź token konfiguracji z konsoli serwera.",
"setupTokenRequired": "Wymagany jest token konfiguracji", "setupTokenRequired": "Wymagany jest token konfiguracji",
"actionUpdateSite": "Aktualizuj witrynę", "actionUpdateSite": "Aktualizuj witrynę",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Lista dozwolonych ról witryny", "actionListSiteRoles": "Lista dozwolonych ról witryny",
"actionCreateResource": "Utwórz zasób", "actionCreateResource": "Utwórz zasób",
"actionDeleteResource": "Usuń zasób", "actionDeleteResource": "Usuń zasób",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Digite o token de configuração do console do servidor.", "setupTokenDescription": "Digite o token de configuração do console do servidor.",
"setupTokenRequired": "Token de configuração é necessário", "setupTokenRequired": "Token de configuração é necessário",
"actionUpdateSite": "Atualizar Site", "actionUpdateSite": "Atualizar Site",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Listar Funções Permitidas do Site", "actionListSiteRoles": "Listar Funções Permitidas do Site",
"actionCreateResource": "Criar Recurso", "actionCreateResource": "Criar Recurso",
"actionDeleteResource": "Eliminar Recurso", "actionDeleteResource": "Eliminar Recurso",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Введите токен настройки из консоли сервера.", "setupTokenDescription": "Введите токен настройки из консоли сервера.",
"setupTokenRequired": "Токен настройки обязателен", "setupTokenRequired": "Токен настройки обязателен",
"actionUpdateSite": "Обновить сайт", "actionUpdateSite": "Обновить сайт",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "Список разрешенных ролей сайта", "actionListSiteRoles": "Список разрешенных ролей сайта",
"actionCreateResource": "Создать ресурс", "actionCreateResource": "Создать ресурс",
"actionDeleteResource": "Удалить ресурс", "actionDeleteResource": "Удалить ресурс",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "Sunucu konsolundan kurulum simgesini girin.", "setupTokenDescription": "Sunucu konsolundan kurulum simgesini girin.",
"setupTokenRequired": "Kurulum simgesi gerekli", "setupTokenRequired": "Kurulum simgesi gerekli",
"actionUpdateSite": "Siteyi Güncelle", "actionUpdateSite": "Siteyi Güncelle",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "İzin Verilen Site Rolleri Listele", "actionListSiteRoles": "İzin Verilen Site Rolleri Listele",
"actionCreateResource": "Kaynak Oluştur", "actionCreateResource": "Kaynak Oluştur",
"actionDeleteResource": "Kaynağı Sil", "actionDeleteResource": "Kaynağı Sil",

View File

@@ -1119,6 +1119,7 @@
"setupTokenDescription": "从服务器控制台输入设置令牌。", "setupTokenDescription": "从服务器控制台输入设置令牌。",
"setupTokenRequired": "需要设置令牌", "setupTokenRequired": "需要设置令牌",
"actionUpdateSite": "更新站点", "actionUpdateSite": "更新站点",
"actionResetSiteBandwidth": "Reset Organization Bandwidth",
"actionListSiteRoles": "允许站点角色列表", "actionListSiteRoles": "允许站点角色列表",
"actionCreateResource": "创建资源", "actionCreateResource": "创建资源",
"actionDeleteResource": "删除资源", "actionDeleteResource": "删除资源",

View File

@@ -1,7 +1,7 @@
import { drizzle as DrizzlePostgres } from "drizzle-orm/node-postgres"; import { drizzle as DrizzlePostgres } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { readConfigFile } from "@server/lib/readConfigFile"; import { readConfigFile } from "@server/lib/readConfigFile";
import { withReplicas } from "drizzle-orm/pg-core"; import { withReplicas } from "drizzle-orm/pg-core";
import { createPool } from "./poolConfig";
function createDb() { function createDb() {
const config = readConfigFile(); const config = readConfigFile();
@@ -39,17 +39,12 @@ function createDb() {
// Create connection pools instead of individual connections // Create connection pools instead of individual connections
const poolConfig = config.postgres.pool; const poolConfig = config.postgres.pool;
const maxConnections = poolConfig?.max_connections || 20; const primaryPool = new Pool({
const idleTimeoutMs = poolConfig?.idle_timeout_ms || 30000;
const connectionTimeoutMs = poolConfig?.connection_timeout_ms || 5000;
const primaryPool = createPool(
connectionString, connectionString,
maxConnections, max: poolConfig?.max_connections || 20,
idleTimeoutMs, idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
connectionTimeoutMs, connectionTimeoutMillis: poolConfig?.connection_timeout_ms || 5000
"primary" });
);
const replicas = []; const replicas = [];
@@ -60,16 +55,14 @@ function createDb() {
}) })
); );
} else { } else {
const maxReplicaConnections =
poolConfig?.max_replica_connections || 20;
for (const conn of replicaConnections) { for (const conn of replicaConnections) {
const replicaPool = createPool( const replicaPool = new Pool({
conn.connection_string, connectionString: conn.connection_string,
maxReplicaConnections, max: poolConfig?.max_replica_connections || 20,
idleTimeoutMs, idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
connectionTimeoutMs, connectionTimeoutMillis:
"replica" poolConfig?.connection_timeout_ms || 5000
); });
replicas.push( replicas.push(
DrizzlePostgres(replicaPool, { DrizzlePostgres(replicaPool, {
logger: process.env.QUERY_LOGGING == "true" logger: process.env.QUERY_LOGGING == "true"

View File

@@ -1,9 +1,9 @@
import { drizzle as DrizzlePostgres } from "drizzle-orm/node-postgres"; import { drizzle as DrizzlePostgres } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { readConfigFile } from "@server/lib/readConfigFile"; import { readConfigFile } from "@server/lib/readConfigFile";
import { withReplicas } from "drizzle-orm/pg-core"; import { withReplicas } from "drizzle-orm/pg-core";
import { build } from "@server/build"; import { build } from "@server/build";
import { db as mainDb, primaryDb as mainPrimaryDb } from "./driver"; import { db as mainDb, primaryDb as mainPrimaryDb } from "./driver";
import { createPool } from "./poolConfig";
function createLogsDb() { function createLogsDb() {
// Only use separate logs database in SaaS builds // Only use separate logs database in SaaS builds
@@ -42,17 +42,12 @@ function createLogsDb() {
// Create separate connection pool for logs database // Create separate connection pool for logs database
const poolConfig = logsConfig?.pool || config.postgres?.pool; const poolConfig = logsConfig?.pool || config.postgres?.pool;
const maxConnections = poolConfig?.max_connections || 20; const primaryPool = new Pool({
const idleTimeoutMs = poolConfig?.idle_timeout_ms || 30000;
const connectionTimeoutMs = poolConfig?.connection_timeout_ms || 5000;
const primaryPool = createPool(
connectionString, connectionString,
maxConnections, max: poolConfig?.max_connections || 20,
idleTimeoutMs, idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
connectionTimeoutMs, connectionTimeoutMillis: poolConfig?.connection_timeout_ms || 5000
"logs-primary" });
);
const replicas = []; const replicas = [];
@@ -63,16 +58,14 @@ function createLogsDb() {
}) })
); );
} else { } else {
const maxReplicaConnections =
poolConfig?.max_replica_connections || 20;
for (const conn of replicaConnections) { for (const conn of replicaConnections) {
const replicaPool = createPool( const replicaPool = new Pool({
conn.connection_string, connectionString: conn.connection_string,
maxReplicaConnections, max: poolConfig?.max_replica_connections || 20,
idleTimeoutMs, idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
connectionTimeoutMs, connectionTimeoutMillis:
"logs-replica" poolConfig?.connection_timeout_ms || 5000
); });
replicas.push( replicas.push(
DrizzlePostgres(replicaPool, { DrizzlePostgres(replicaPool, {
logger: process.env.QUERY_LOGGING == "true" logger: process.env.QUERY_LOGGING == "true"

View File

@@ -1,63 +0,0 @@
import { Pool, PoolConfig } from "pg";
import logger from "@server/logger";
export function createPoolConfig(
connectionString: string,
maxConnections: number,
idleTimeoutMs: number,
connectionTimeoutMs: number
): PoolConfig {
return {
connectionString,
max: maxConnections,
idleTimeoutMillis: idleTimeoutMs,
connectionTimeoutMillis: connectionTimeoutMs,
// TCP keepalive to prevent silent connection drops by NAT gateways,
// load balancers, and other intermediate network devices (e.g. AWS
// NAT Gateway drops idle TCP connections after ~350s)
keepAlive: true,
keepAliveInitialDelayMillis: 10000, // send first keepalive after 10s of idle
// Allow connections to be released and recreated more aggressively
// to avoid stale connections building up
allowExitOnIdle: false
};
}
export function attachPoolErrorHandlers(pool: Pool, label: string): void {
pool.on("error", (err) => {
// This catches errors on idle clients in the pool. Without this
// handler an unexpected disconnect would crash the process.
logger.error(
`Unexpected error on idle ${label} database client: ${err.message}`
);
});
pool.on("connect", (client) => {
// Set a statement timeout on every new connection so a single slow
// query can't block the pool forever
client.query("SET statement_timeout = '30s'").catch((err: Error) => {
logger.warn(
`Failed to set statement_timeout on ${label} client: ${err.message}`
);
});
});
}
export function createPool(
connectionString: string,
maxConnections: number,
idleTimeoutMs: number,
connectionTimeoutMs: number,
label: string
): Pool {
const pool = new Pool(
createPoolConfig(
connectionString,
maxConnections,
idleTimeoutMs,
connectionTimeoutMs
)
);
attachPoolErrorHandlers(pool, label);
return pool;
}

View File

@@ -275,8 +275,6 @@ export default function Page() {
} }
} }
const disabled = !isPaidUser(tierMatrix.orgOidc);
return ( return (
<> <>
<div className="flex justify-between"> <div className="flex justify-between">
@@ -294,9 +292,6 @@ export default function Page() {
</Button> </Button>
</div> </div>
<PaidFeaturesAlert tiers={tierMatrix.orgOidc} />
<fieldset disabled={disabled} className={disabled ? "opacity-50 pointer-events-none" : ""}>
<SettingsContainer> <SettingsContainer>
<SettingsSection> <SettingsSection>
<SettingsSectionHeader> <SettingsSectionHeader>
@@ -817,10 +812,9 @@ export default function Page() {
</Button> </Button>
<Button <Button
type="submit" type="submit"
disabled={createLoading || disabled} disabled={createLoading || !isPaidUser(tierMatrix.orgOidc)}
loading={createLoading} loading={createLoading}
onClick={() => { onClick={() => {
if (disabled) return;
// log any issues with the form // log any issues with the form
console.log(form.formState.errors); console.log(form.formState.errors);
form.handleSubmit(onSubmit)(); form.handleSubmit(onSubmit)();
@@ -829,7 +823,6 @@ export default function Page() {
{t("idpSubmit")} {t("idpSubmit")}
</Button> </Button>
</div> </div>
</fieldset>
</> </>
); );
} }