@salla.sa/ecommerce-events-base
Version:
Base types and utilities for Salla ecommerce event tracking
123 lines (118 loc) • 4.68 kB
JavaScript
// src/ecommerce-event-discover.ts
import { readdir, readFile } from "fs/promises";
import { join, resolve } from "path";
function AutoRegistryEventsPlugin() {
return {
name: "AutoRegistryEventsPlugin",
// Add configResolved hook to run earlier
configResolved(config) {
console.log("\u{1F527} Config resolved, mode:", config.command);
},
// Add buildStart hook
async buildStart() {
console.log("\u{1F680} BuildStart hook triggered");
await generateRegistryFile();
},
// Add configureServer hook for dev mode
configureServer(server) {
console.log("\u{1F527} Configure server hook triggered");
generateRegistryFile().catch(console.error);
},
// Add resolveId hook to handle the import
resolveId(id, importer) {
if (id === "./auto-listeners-registry" && importer?.includes("src/index.ts")) {
console.log("\u{1F50D} Resolving auto-listeners-registry import");
const registryPath = resolve(process.cwd(), "src/auto-listeners-registry.ts");
return registryPath;
}
}
};
}
async function generateRegistryFile() {
console.log("\u{1F50D} Discovering event listeners...");
const listenersDir = resolve(process.cwd(), "src/listeners");
const listeners = await discoverListeners(listenersDir);
console.log(`\u{1F4E6} Found ${listeners.length} event listeners`);
const registryCode = generateAutoRegistry(listeners);
const registryPath = resolve(process.cwd(), "src/auto-listeners-registry.ts");
const fs = await import("fs/promises");
await fs.writeFile(registryPath, registryCode);
console.log("\u2705 Auto-registry file generated at:", registryPath);
}
async function discoverListeners(listenersDir) {
const listeners = [];
try {
const files = await readdir(listenersDir);
const tsFiles = files.filter((file) => file.endsWith(".ts") && !file.endsWith(".d.ts"));
for (const file of tsFiles) {
const filePath = join(listenersDir, file);
const content = await readFile(filePath, "utf-8");
const eventNameMatch = content.match(/export const eventName = (EcommerceEvents\.\w+);/);
const hasDefaultExport = content.includes("export default (payload:");
if (eventNameMatch && hasDefaultExport) {
if (hasActualLogic(content)) {
const eventName = eventNameMatch[1];
const importPath = `./listeners/${file.replace(".ts", "")}`;
const fileName = file.replace(".ts", "");
listeners.push({
eventName,
importPath,
fileName
});
} else {
console.log(`\u23ED\uFE0F Skipping listener ${file} - no meaningful logic detected`);
}
}
}
} catch (error) {
console.warn("Warning: Could not discover listeners:", error);
}
return listeners;
}
function hasActualLogic(content) {
const defaultExportMatch = content.match(/export default \(payload:[^)]+\):[^{]*{([^}]*)}/s);
if (!defaultExportMatch) {
return false;
}
const functionBody = defaultExportMatch[1];
const cleanBody = functionBody.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").trim();
if (!cleanBody) {
return false;
}
const consoleLogRegex = /console\.(log|warn|error|info|debug)\s*\([^)]*\)\s*;?/g;
const bodyWithoutConsoleLogs = cleanBody.replace(consoleLogRegex, "").trim();
if (!bodyWithoutConsoleLogs) {
return false;
}
const placeholderPatterns = [
/add\s+your\s+custom\s+tracking\s+logic\s+here/i,
/todo/i,
/implement\s+your\s+logic/i,
/your\s+code\s+here/i
];
const hasOnlyPlaceholders = placeholderPatterns.some(
(pattern) => pattern.test(bodyWithoutConsoleLogs) && bodyWithoutConsoleLogs.replace(pattern, "").trim() === ""
);
return !hasOnlyPlaceholders;
}
function generateAutoRegistry(listeners) {
const toCamelCase = (str) => str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
const imports = listeners.map((listener) => {
const camelCaseName = toCamelCase(listener.fileName);
return `import ${camelCaseName}Handler, { eventName as ${camelCaseName}EventName } from '${listener.importPath}';`;
}).join("\n");
const registrations = listeners.map((listener) => {
const camelCaseName = toCamelCase(listener.fileName);
return `listeners.set(${camelCaseName}EventName, ${camelCaseName}Handler);`;
}).join("\n");
return `// Auto-generated listeners registry - DO NOT EDIT MANUALLY
// This file is generated by the Vite listeners plugin
${imports}
const listeners: Map<string, (payload: any) => void> = new Map();
${registrations}
export { listeners };
`;
}
export {
AutoRegistryEventsPlugin
};