Files
saleor-core-extensions/src/lib/settings.ts
T
Unchained 41fd8a5099 feat: add settings UI for webhook toggles
- Add settings store (src/lib/settings.ts) for persistent configuration
- Add settings API route for CRUD operations
- Add settings page with webhook toggles for order events
- Update webhook handlers to check settings before sending emails
- Settings include: webhook enable/disable, admin/customer notification toggles
- Email configuration: from name, from email, admin emails, store/dashboard URLs
2026-03-27 07:16:03 +02:00

134 lines
3.5 KiB
TypeScript

import { promises as fs } from "fs";
import path from "path";
export interface WebhookSettings {
orderCreated: {
enabled: boolean;
sendAdminNotification: boolean;
sendCustomerNotification: boolean;
};
orderFulfilled: {
enabled: boolean;
sendAdminNotification: boolean;
sendCustomerNotification: boolean;
};
orderCancelled: {
enabled: boolean;
sendAdminNotification: boolean;
sendCustomerNotification: boolean;
};
}
export interface EmailSettings {
fromEmail: string;
fromName: string;
adminEmails: string[];
siteUrl: string;
dashboardUrl: string;
}
export interface AppSettings {
webhooks: WebhookSettings;
email: EmailSettings;
updatedAt: string;
}
const DEFAULT_SETTINGS: AppSettings = {
webhooks: {
orderCreated: {
enabled: true,
sendAdminNotification: true,
sendCustomerNotification: true,
},
orderFulfilled: {
enabled: true,
sendAdminNotification: true,
sendCustomerNotification: true,
},
orderCancelled: {
enabled: true,
sendAdminNotification: true,
sendCustomerNotification: true,
},
},
email: {
fromEmail: process.env.FROM_EMAIL || "support@mail.manoonoils.com",
fromName: process.env.FROM_NAME || "ManoonOils",
adminEmails: process.env.ADMIN_EMAILS?.split(",").map((e) => e.trim()).filter(Boolean) || [],
siteUrl: process.env.SITE_URL || "https://manoonoils.com",
dashboardUrl: process.env.DASHBOARD_URL || "https://dashboard.manoonoils.com",
},
updatedAt: new Date().toISOString(),
};
class SettingsStore {
private filePath: string;
private settings: AppSettings | null = null;
constructor() {
this.filePath = process.env.SETTINGS_FILE_PATH || "/tmp/.app-settings.json";
}
private async ensureFileExists(): Promise<void> {
try {
await fs.access(this.filePath);
} catch {
const dir = path.dirname(this.filePath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(this.filePath, JSON.stringify(DEFAULT_SETTINGS, null, 2));
}
}
async get(): Promise<AppSettings> {
if (this.settings) {
return this.settings;
}
try {
await this.ensureFileExists();
const data = await fs.readFile(this.filePath, "utf-8");
this.settings = JSON.parse(data) as AppSettings;
return this.settings!;
} catch (error) {
console.error("Error reading settings:", error);
this.settings = DEFAULT_SETTINGS;
return this.settings;
}
}
async set(newSettings: Partial<AppSettings>): Promise<AppSettings> {
const current = await this.get();
const updated: AppSettings = {
...current,
...newSettings,
updatedAt: new Date().toISOString(),
};
try {
await fs.writeFile(this.filePath, JSON.stringify(updated, null, 2));
this.settings = updated;
return updated;
} catch (error) {
console.error("Error writing settings:", error);
throw error;
}
}
async isWebhookEnabled(webhook: keyof WebhookSettings): Promise<boolean> {
const settings = await this.get();
return settings.webhooks[webhook].enabled;
}
async shouldSendAdminNotification(webhook: keyof WebhookSettings): Promise<boolean> {
const settings = await this.get();
return settings.webhooks[webhook].sendAdminNotification;
}
async shouldSendCustomerNotification(webhook: keyof WebhookSettings): Promise<boolean> {
const settings = await this.get();
return settings.webhooks[webhook].sendCustomerNotification;
}
}
export const settingsStore = new SettingsStore();