ruch
Version:
Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.
137 lines • 6.18 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.findMissingDomains = exports.parseExistingServiceContext = exports.getExistingDomains = exports.isDirectoryEntry = exports.filterValidDomains = exports.validateDomainStructure = exports.buildServiceContextTestFilePath = exports.buildServiceContextFilePath = exports.buildContextPath = exports.buildDomainsPath = exports.createDomainInfo = exports.capitalizeFirstLetter = void 0;
const path_1 = __importDefault(require("path"));
const file_operations_1 = require("./file-operations");
/**
* Pure function to capitalize first letter of a string
*/
const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
exports.capitalizeFirstLetter = capitalizeFirstLetter;
/**
* Pure function to create domain info from domain name
*/
const createDomainInfo = (domainName) => ({
name: domainName,
capitalizedName: (0, exports.capitalizeFirstLetter)(domainName)
});
exports.createDomainInfo = createDomainInfo;
/**
* Pure function to build domains directory path
*/
const buildDomainsPath = (projectRoot = process.cwd()) => path_1.default.join(projectRoot, 'src', 'domains');
exports.buildDomainsPath = buildDomainsPath;
/**
* Pure function to build context directory path
*/
const buildContextPath = (projectRoot = process.cwd()) => path_1.default.join(projectRoot, 'src', 'context');
exports.buildContextPath = buildContextPath;
/**
* Pure function to build service context file path
*/
const buildServiceContextFilePath = (projectRoot = process.cwd()) => path_1.default.join((0, exports.buildContextPath)(projectRoot), 'ServiceContext.tsx');
exports.buildServiceContextFilePath = buildServiceContextFilePath;
/**
* Pure function to build service context test file path
*/
const buildServiceContextTestFilePath = (projectRoot = process.cwd()) => path_1.default.join((0, exports.buildContextPath)(projectRoot), 'ServiceContext.test.tsx');
exports.buildServiceContextTestFilePath = buildServiceContextTestFilePath;
/**
* Pure function to validate if a domain has required structure
*/
const validateDomainStructure = async (fileSystem, domainPath, domainName) => {
const capitalizedName = (0, exports.capitalizeFirstLetter)(domainName);
const requiredFiles = [
path_1.default.join(domainPath, 'services', `${capitalizedName}Service.ts`),
path_1.default.join(domainPath, 'adapters', `${capitalizedName}Adapter.ts`)
];
const validationResults = await Promise.all(requiredFiles.map(filePath => (0, file_operations_1.validateFileExists)(fileSystem, filePath)));
return validationResults.every(exists => exists);
};
exports.validateDomainStructure = validateDomainStructure;
/**
* Pure function to filter valid domains from directory entries
*/
const filterValidDomains = async (fileSystem, domainsPath, directoryEntries) => {
const validationPromises = directoryEntries.map(async (entry) => {
const domainPath = path_1.default.join(domainsPath, entry);
const isDirectory = await (0, exports.isDirectoryEntry)(fileSystem, domainPath);
if (!isDirectory)
return null;
const hasValidStructure = await (0, exports.validateDomainStructure)(fileSystem, domainPath, entry);
return hasValidStructure ? entry : null;
});
const validationResults = await Promise.all(validationPromises);
return validationResults.filter((entry) => entry !== null);
};
exports.filterValidDomains = filterValidDomains;
/**
* Pure function to check if path is a directory
*/
const isDirectoryEntry = async (fileSystem, entryPath) => {
try {
const stats = await fileSystem.stat(entryPath);
return stats.isDirectory();
}
catch {
return false;
}
};
exports.isDirectoryEntry = isDirectoryEntry;
/**
* Get all valid domains from the domains directory
*/
const getExistingDomains = async (fileSystem, projectRoot = process.cwd()) => {
const domainsPath = (0, exports.buildDomainsPath)(projectRoot);
const domainsExist = await (0, file_operations_1.validateFileExists)(fileSystem, domainsPath);
if (!domainsExist) {
return [];
}
try {
const entries = await fileSystem.readdir(domainsPath);
const validDomainNames = await (0, exports.filterValidDomains)(fileSystem, domainsPath, entries);
return validDomainNames.map(exports.createDomainInfo);
}
catch {
return [];
}
};
exports.getExistingDomains = getExistingDomains;
/**
* Parse existing service context to extract current domains
*/
const parseExistingServiceContext = async (fileSystem, projectRoot = process.cwd()) => {
const contextFilePath = (0, exports.buildServiceContextFilePath)(projectRoot);
const contextExists = await (0, file_operations_1.validateFileExists)(fileSystem, contextFilePath);
if (!contextExists) {
return [];
}
try {
const content = await (0, file_operations_1.readFile)(fileSystem, contextFilePath, 'utf8');
const serviceMatches = content.match(/(\w+)Service:\s*\w+Service/g) || [];
const domainNames = serviceMatches
.map((match) => match.replace(/Service:\s*\w+Service/, ''))
.filter((name) => name.length > 0);
return domainNames.map(exports.createDomainInfo);
}
catch {
return [];
}
};
exports.parseExistingServiceContext = parseExistingServiceContext;
/**
* Find domains that are not yet in the service context
*/
const findMissingDomains = async (fileSystem, projectRoot = process.cwd()) => {
const [existingDomains, contextDomains] = await Promise.all([
(0, exports.getExistingDomains)(fileSystem, projectRoot),
(0, exports.parseExistingServiceContext)(fileSystem, projectRoot)
]);
const contextDomainNames = new Set(contextDomains.map(d => d.name));
return existingDomains.filter(domain => !contextDomainNames.has(domain.name));
};
exports.findMissingDomains = findMissingDomains;
//# sourceMappingURL=domain-analyzer.js.map