@salla.sa/ecommerce-events-base
Version:
Base types and utilities for Salla ecommerce event tracking
160 lines (153 loc) • 6.44 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/plugin.ts
var plugin_exports = {};
__export(plugin_exports, {
AutoRegistryEventsPlugin: () => AutoRegistryEventsPlugin
});
module.exports = __toCommonJS(plugin_exports);
// src/ecommerce-event-discover.ts
var import_promises = require("fs/promises");
var import_path = require("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 = (0, import_path.resolve)(process.cwd(), "src/auto-listeners-registry.ts");
return registryPath;
}
}
};
}
async function generateRegistryFile() {
console.log("\u{1F50D} Discovering event listeners...");
const listenersDir = (0, import_path.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 = (0, import_path.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 (0, import_promises.readdir)(listenersDir);
const tsFiles = files.filter((file) => file.endsWith(".ts") && !file.endsWith(".d.ts"));
for (const file of tsFiles) {
const filePath = (0, import_path.join)(listenersDir, file);
const content = await (0, import_promises.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 };
`;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AutoRegistryEventsPlugin
});