81 lines
2.8 KiB
JavaScript
81 lines
2.8 KiB
JavaScript
export function readConfig(env = process.env) {
|
|
const rawRetentionDays = integer(env.GELIOS_RAW_RETENTION_DAYS, 14, 1, 3650);
|
|
|
|
return {
|
|
nodeEnv: string(env.NODE_ENV, "development"),
|
|
port: integer(env.PORT, 18105, 1, 65535),
|
|
databaseUrl: required(env.DATABASE_URL, "DATABASE_URL"),
|
|
databasePoolSize: integer(env.GELIOS_DATABASE_POOL_SIZE, 10, 1, 50),
|
|
internalAccessToken: optional(env.NODEDC_INTERNAL_ACCESS_TOKEN),
|
|
tenantId: slug(required(env.GELIOS_TENANT_ID, "GELIOS_TENANT_ID"), "GELIOS_TENANT_ID"),
|
|
connectionId: slug(required(env.GELIOS_CONNECTION_ID, "GELIOS_CONNECTION_ID"), "GELIOS_CONNECTION_ID"),
|
|
unitScope: collectionScope(env.GELIOS_UNIT_SCOPE),
|
|
allowedUnitIds: intList(env.GELIOS_ALLOWED_UNIT_IDS),
|
|
intakeEnabled: boolean(env.GELIOS_INTAKE_ENABLED, false),
|
|
rawRetentionDays,
|
|
positionStaleAfterMs: integer(env.GELIOS_POSITION_STALE_AFTER_MS, 300_000, 1_000, 86_400_000),
|
|
};
|
|
}
|
|
|
|
function collectionScope(value) {
|
|
const candidate = optional(value).toLowerCase() || "allowlist";
|
|
if (["allowlist", "all"].includes(candidate)) return candidate;
|
|
throw new Error("GELIOS_UNIT_SCOPE_must_be_allowlist_or_all");
|
|
}
|
|
|
|
export function unitIsInScope(config, sourceUnitId) {
|
|
return config?.unitScope === "all" || config?.allowedUnitIds?.includes(sourceUnitId) === true;
|
|
}
|
|
|
|
function required(value, name) {
|
|
const normalized = optional(value);
|
|
if (!normalized) throw new Error(`${name}_required`);
|
|
return normalized;
|
|
}
|
|
|
|
function optional(value) {
|
|
const normalized = String(value ?? "").trim();
|
|
return normalized || "";
|
|
}
|
|
|
|
function string(value, fallback) {
|
|
return optional(value) || fallback;
|
|
}
|
|
|
|
function integer(value, fallback, min, max) {
|
|
const candidate = optional(value);
|
|
if (!candidate) return fallback;
|
|
const number = Number.parseInt(candidate, 10);
|
|
if (!Number.isInteger(number) || number < min || number > max) {
|
|
throw new Error(`invalid_integer:${candidate}`);
|
|
}
|
|
return number;
|
|
}
|
|
|
|
function boolean(value, fallback) {
|
|
const candidate = optional(value).toLowerCase();
|
|
if (!candidate) return fallback;
|
|
if (["1", "true", "yes", "on"].includes(candidate)) return true;
|
|
if (["0", "false", "no", "off"].includes(candidate)) return false;
|
|
throw new Error(`invalid_boolean:${candidate}`);
|
|
}
|
|
|
|
function intList(value) {
|
|
const values = optional(value)
|
|
.split(",")
|
|
.map((item) => item.trim())
|
|
.filter(Boolean)
|
|
.map((item) => Number.parseInt(item, 10));
|
|
if (values.some((item) => !Number.isInteger(item) || item <= 0)) {
|
|
throw new Error("GELIOS_ALLOWED_UNIT_IDS_must_contain_positive_integers");
|
|
}
|
|
return [...new Set(values)].sort((left, right) => left - right);
|
|
}
|
|
|
|
function slug(value, name) {
|
|
if (!/^[a-z0-9][a-z0-9_-]{0,95}$/i.test(value)) {
|
|
throw new Error(`${name}_invalid`);
|
|
}
|
|
return value;
|
|
}
|