deduplicate json config file access

This commit is contained in:
yml
2026-05-21 18:54:41 +08:00
parent 17a615b8de
commit 589de4b50b
6 changed files with 79 additions and 86 deletions
@@ -1,7 +1,7 @@
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { PROJECT_ROOT } from '../../config/runtime.js' import { PROJECT_ROOT } from '../../config/runtime.js'
import { readJsonFile, writeJsonFile } from '../../utils/json-file-store.js'
const NOTIFICATION_CONFIG_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'notification-config.json') const NOTIFICATION_CONFIG_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'notification-config.json')
const DEFAULT_BARK_SERVER_URL = 'https://api.day.app' const DEFAULT_BARK_SERVER_URL = 'https://api.day.app'
@@ -17,10 +17,7 @@ export function getNotificationConfig() {
} }
export function saveNotificationConfig(rawValue: unknown) { export function saveNotificationConfig(rawValue: unknown) {
const normalized = normalizeNotificationConfig(rawValue) return writeJsonFile(NOTIFICATION_CONFIG_FILE_PATH, rawValue, normalizeNotificationConfig)
fs.mkdirSync(path.dirname(NOTIFICATION_CONFIG_FILE_PATH), { recursive: true })
fs.writeFileSync(NOTIFICATION_CONFIG_FILE_PATH, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
return normalized
} }
export function listEnabledBarkRecipients(config: JsonObject = getNotificationConfig()) { export function listEnabledBarkRecipients(config: JsonObject = getNotificationConfig()) {
@@ -33,16 +30,11 @@ export function listEnabledBarkRecipients(config: JsonObject = getNotificationCo
} }
function loadNotificationConfigFromFile() { function loadNotificationConfigFromFile() {
if (!fs.existsSync(NOTIFICATION_CONFIG_FILE_PATH)) { return readJsonFile(
return createDefaultNotificationConfig() NOTIFICATION_CONFIG_FILE_PATH,
} createDefaultNotificationConfig,
normalizeNotificationConfig,
try { )
const rawText = fs.readFileSync(NOTIFICATION_CONFIG_FILE_PATH, 'utf8')
return normalizeNotificationConfig(JSON.parse(rawText))
} catch {
return createDefaultNotificationConfig()
}
} }
function normalizeNotificationConfig(rawValue: unknown) { function normalizeNotificationConfig(rawValue: unknown) {
@@ -1,7 +1,7 @@
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { PROJECT_ROOT } from '../../config/runtime.js' import { PROJECT_ROOT } from '../../config/runtime.js'
import { readJsonFile, writeJsonFile } from '../../utils/json-file-store.js'
const ORDER_FULFILLMENT_BINDINGS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'order-fulfillment-bindings.json') const ORDER_FULFILLMENT_BINDINGS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'order-fulfillment-bindings.json')
@@ -20,28 +20,19 @@ export function getLegacyOrderFulfillmentBindingConfigs() {
} }
export function saveOrderFulfillmentBindingConfigs(rawValue) { export function saveOrderFulfillmentBindingConfigs(rawValue) {
const normalized = normalizeOrderFulfillmentBindingConfigs(rawValue) return writeJsonFile(
fs.mkdirSync(path.dirname(ORDER_FULFILLMENT_BINDINGS_FILE_PATH), { recursive: true })
fs.writeFileSync(
ORDER_FULFILLMENT_BINDINGS_FILE_PATH, ORDER_FULFILLMENT_BINDINGS_FILE_PATH,
`${JSON.stringify(normalized, null, 2)}\n`, rawValue,
'utf8', normalizeOrderFulfillmentBindingConfigs,
) )
return normalized
} }
function loadOrderFulfillmentBindingConfigsFromFile() { function loadOrderFulfillmentBindingConfigsFromFile() {
if (!fs.existsSync(ORDER_FULFILLMENT_BINDINGS_FILE_PATH)) { return readJsonFile(
return [] ORDER_FULFILLMENT_BINDINGS_FILE_PATH,
} [],
normalizeOrderFulfillmentBindingConfigs,
try { )
const rawText = fs.readFileSync(ORDER_FULFILLMENT_BINDINGS_FILE_PATH, 'utf8')
const parsed = JSON.parse(rawText)
return normalizeOrderFulfillmentBindingConfigs(parsed)
} catch {
return []
}
} }
function normalizeOrderFulfillmentBindingConfigs(rawValue) { function normalizeOrderFulfillmentBindingConfigs(rawValue) {
@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import { PROJECT_ROOT } from "../../config/runtime.js"; import { PROJECT_ROOT } from "../../config/runtime.js";
import { readJsonFile, writeJsonFile } from "../../utils/json-file-store.js";
import { resolveKuaishouEticketShopConfig } from "../platforms/kuaishou-eticket/source-config-service.js"; import { resolveKuaishouEticketShopConfig } from "../platforms/kuaishou-eticket/source-config-service.js";
const KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH = path.join( const KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH = path.join(
@@ -21,16 +21,11 @@ export function getKuaishouCloudFulfillmentConfig() {
} }
export function saveKuaishouCloudFulfillmentConfig(rawValue) { export function saveKuaishouCloudFulfillmentConfig(rawValue) {
const normalized = normalizeKuaishouCloudFulfillmentConfig(rawValue); return writeJsonFile(
fs.mkdirSync(path.dirname(KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH), {
recursive: true,
});
fs.writeFileSync(
KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH, KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH,
`${JSON.stringify(normalized, null, 2)}\n`, rawValue,
"utf8" normalizeKuaishouCloudFulfillmentConfig
); );
return normalized;
} }
export function mapKuaishouCloudFulfillmentItemsToBindings(config: JsonObject = {}) { export function mapKuaishouCloudFulfillmentItemsToBindings(config: JsonObject = {}) {
@@ -92,20 +87,11 @@ export function mapKuaishouCloudFulfillmentItemsToBindings(config: JsonObject =
} }
function loadKuaishouCloudFulfillmentConfigFromFile() { function loadKuaishouCloudFulfillmentConfigFromFile() {
if (!fs.existsSync(KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH)) { return readJsonFile(
return normalizeKuaishouCloudFulfillmentConfig({}); KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH,
} () => normalizeKuaishouCloudFulfillmentConfig({}),
normalizeKuaishouCloudFulfillmentConfig
try { );
const rawText = fs.readFileSync(
KUAISHOU_CLOUD_FULFILLMENT_FILE_PATH,
"utf8"
);
const parsed = JSON.parse(rawText);
return normalizeKuaishouCloudFulfillmentConfig(parsed);
} catch {
return normalizeKuaishouCloudFulfillmentConfig({});
}
} }
function normalizeKuaishouCloudFulfillmentConfig(rawValue) { function normalizeKuaishouCloudFulfillmentConfig(rawValue) {
@@ -1,7 +1,7 @@
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { PROJECT_ROOT } from '../../../config/runtime.js' import { PROJECT_ROOT } from '../../../config/runtime.js'
import { readJsonFile, writeJsonFile } from '../../../utils/json-file-store.js'
const KUAISHOU_ETICKET_SOURCE_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'kuaishou-eticket-source.json') const KUAISHOU_ETICKET_SOURCE_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'kuaishou-eticket-source.json')
const DEFAULT_BASE_URL = 'https://s.kwaixiaodian.com' const DEFAULT_BASE_URL = 'https://s.kwaixiaodian.com'
@@ -31,10 +31,11 @@ export function getKuaishouEticketSourceConfig(): KuaishouEticketSourceConfig {
} }
export function saveKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticketSourceConfig { export function saveKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticketSourceConfig {
const normalized = normalizeKuaishouEticketSourceConfig(rawValue) return writeJsonFile(
fs.mkdirSync(path.dirname(KUAISHOU_ETICKET_SOURCE_FILE_PATH), { recursive: true }) KUAISHOU_ETICKET_SOURCE_FILE_PATH,
fs.writeFileSync(KUAISHOU_ETICKET_SOURCE_FILE_PATH, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8') rawValue,
return normalized normalizeKuaishouEticketSourceConfig,
)
} }
export function listKuaishouEticketShopConfigs(source: KuaishouEticketSourceConfig = getKuaishouEticketSourceConfig()): KuaishouEticketShopConfig[] { export function listKuaishouEticketShopConfigs(source: KuaishouEticketSourceConfig = getKuaishouEticketSourceConfig()): KuaishouEticketShopConfig[] {
@@ -81,16 +82,11 @@ export function getFirstAvailableKuaishouEticketShop(source: KuaishouEticketSour
} }
function loadKuaishouEticketSourceConfigFromFile(): KuaishouEticketSourceConfig { function loadKuaishouEticketSourceConfigFromFile(): KuaishouEticketSourceConfig {
if (!fs.existsSync(KUAISHOU_ETICKET_SOURCE_FILE_PATH)) { return readJsonFile(
return createDefaultKuaishouEticketSourceConfig() KUAISHOU_ETICKET_SOURCE_FILE_PATH,
} createDefaultKuaishouEticketSourceConfig,
normalizeKuaishouEticketSourceConfig,
try { )
const rawText = fs.readFileSync(KUAISHOU_ETICKET_SOURCE_FILE_PATH, 'utf8')
return normalizeKuaishouEticketSourceConfig(JSON.parse(rawText))
} catch {
return createDefaultKuaishouEticketSourceConfig()
}
} }
function normalizeKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticketSourceConfig { function normalizeKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticketSourceConfig {
@@ -1,7 +1,7 @@
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { PROJECT_ROOT } from '../../config/runtime.js' import { PROJECT_ROOT } from '../../config/runtime.js'
import { readJsonFile, writeJsonFile } from '../../utils/json-file-store.js'
const SCHEDULED_JOBS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'scheduled-jobs.json') const SCHEDULED_JOBS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'scheduled-jobs.json')
const CLOUDTENTACLES_HEALTH_JOB_ID = 'cloudtentacles-health' const CLOUDTENTACLES_HEALTH_JOB_ID = 'cloudtentacles-health'
@@ -17,10 +17,7 @@ export function getScheduledJobsConfig() {
} }
export function saveScheduledJobsConfig(rawValue: unknown) { export function saveScheduledJobsConfig(rawValue: unknown) {
const normalized = normalizeScheduledJobsConfig(rawValue) return writeJsonFile(SCHEDULED_JOBS_FILE_PATH, rawValue, normalizeScheduledJobsConfig)
fs.mkdirSync(path.dirname(SCHEDULED_JOBS_FILE_PATH), { recursive: true })
fs.writeFileSync(SCHEDULED_JOBS_FILE_PATH, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
return normalized
} }
export function getCloudtentaclesHealthJob(config: JsonObject = getScheduledJobsConfig()) { export function getCloudtentaclesHealthJob(config: JsonObject = getScheduledJobsConfig()) {
@@ -30,16 +27,11 @@ export function getCloudtentaclesHealthJob(config: JsonObject = getScheduledJobs
} }
function loadScheduledJobsConfigFromFile() { function loadScheduledJobsConfigFromFile() {
if (!fs.existsSync(SCHEDULED_JOBS_FILE_PATH)) { return readJsonFile(
return createDefaultScheduledJobsConfig() SCHEDULED_JOBS_FILE_PATH,
} createDefaultScheduledJobsConfig,
normalizeScheduledJobsConfig,
try { )
const rawText = fs.readFileSync(SCHEDULED_JOBS_FILE_PATH, 'utf8')
return normalizeScheduledJobsConfig(JSON.parse(rawText))
} catch {
return createDefaultScheduledJobsConfig()
}
} }
function normalizeScheduledJobsConfig(rawValue: unknown) { function normalizeScheduledJobsConfig(rawValue: unknown) {
+36
View File
@@ -0,0 +1,36 @@
import fs from 'node:fs'
import path from 'node:path'
type NormalizeJsonValue<T> = (value: unknown) => T
export function readJsonFile<T>(
filePath: string,
fallback: T | (() => T),
normalize: NormalizeJsonValue<T>,
): T {
if (!fs.existsSync(filePath)) {
return resolveFallback(fallback)
}
try {
const rawText = fs.readFileSync(filePath, 'utf8')
return normalize(JSON.parse(rawText))
} catch {
return resolveFallback(fallback)
}
}
export function writeJsonFile<T>(
filePath: string,
value: unknown,
normalize: NormalizeJsonValue<T>,
): T {
const normalized = normalize(value)
fs.mkdirSync(path.dirname(filePath), { recursive: true })
fs.writeFileSync(filePath, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
return normalized
}
function resolveFallback<T>(fallback: T | (() => T)): T {
return typeof fallback === 'function' ? (fallback as () => T)() : fallback
}