fix(api): allow nest build of program-settings and cleaner replica --check

Cast stored JSON through asSettingsArray so tsc accepts the snapshot payload, and strip Prisma ?schema= from DATABASE_URL before psql.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-17 16:01:55 +03:30
co-authored by Cursor
parent f2cf8c9035
commit 25c0a4e941
3 changed files with 27 additions and 5 deletions
+3 -1
View File
@@ -1,6 +1,8 @@
# Copy to deploy/replicas.env on the publisher host (gitignored — holds passwords).
#
# Every logical-replication subscriber of superadmin_pub, space/comma/newline separated.
# One DSN per line (or comma). Do not put spaces between URLs.
# Prefer URI form. Password must not contain @ : / # ? — or URL-encode it.
# Keyword form (host=...) is OK only because the script splits on newlines, not spaces.
# The user must be able to run ALTER TABLE (table owner or superuser).
REPLICA_DSNS="postgresql://USER:PASSWORD@SLAVE_1_IP:5433/superadmin
postgresql://USER:PASSWORD@SLAVE_2_IP:5432/superadmin"
+21 -3
View File
@@ -47,7 +47,10 @@ if [[ -z "${DATABASE_URL:-}" && -f "$API_DIR/.env" ]]; then
set -a && source "$API_DIR/.env" && set +a
fi
read -r -a REPLICAS <<< "$(tr ',\n' ' ' <<< "$REPLICA_DSNS")"
# One DSN per line or comma (NOT spaces — keyword conninfo has spaces).
mapfile -t REPLICAS < <(
printf '%s\n' "$REPLICA_DSNS" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$'
)
# psql would otherwise swallow the loop input it is called from
run_psql() {
@@ -56,7 +59,16 @@ run_psql() {
# host:port/db only — DSNs carry passwords
label() {
sed -E 's#^[a-z]+://([^@]*@)?##; s#\?.*$##' <<< "$1"
local dsn="$1"
if [[ "$dsn" == *"://"* ]]; then
sed -E 's#^[a-z]+://([^@]*@)?##; s#\?.*$##' <<< "$dsn"
return
fi
local host port db
host="$(sed -nE 's/.*host=([^ ]+).*/\1/p' <<< "$dsn")"
port="$(sed -nE 's/.*port=([^ ]+).*/\1/p' <<< "$dsn")"
db="$(sed -nE 's/.*dbname=([^ ]+).*/\1/p' <<< "$dsn")"
echo "${host:-?}:${port:-5432}/${db:-?}"
}
# every list feeding comm is sorted with the same collation
@@ -97,13 +109,19 @@ apply_migration() {
}
column_fingerprint() {
run_psql "$1" -v ON_ERROR_STOP=1 -At -c "
run_psql "$(libpq_dsn "$1")" -v ON_ERROR_STOP=1 -At -c "
SELECT table_name || '.' || column_name
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name NOT IN ('_replica_ddl_applied')" | LC_ALL=C sort
}
# Prisma DATABASE_URL uses ?schema=public; libpq rejects that query param.
libpq_dsn() {
local u="$1"
echo "${u%%\?*}"
}
if [[ "$MODE" == "--check" ]]; then
for dsn in "${REPLICAS[@]}"; do
echo "== $(label "$dsn")"
@@ -144,7 +144,9 @@ export class ProgramSettingsService {
importedAt: '',
source: 'khanegi_admin',
apiBase: '',
items: raw.filter((row) => this.isSystemSetting(row as ProgramSettingRow)),
items: this.asSettingsArray(raw).filter((row) =>
this.isSystemSetting(row),
),
};
}
return null;