@posthog/wizard
Version:
The PostHog wizard helps you to configure your project
180 lines • 7.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GLOBAL_IGNORE_PATTERN = void 0;
exports.getAllFilesInProject = getAllFilesInProject;
exports.getDotGitignore = getDotGitignore;
exports.updateFile = updateFile;
exports.getFilesToChange = getFilesToChange;
exports.generateFileContent = generateFileContent;
exports.generateFileChangesForIntegration = generateFileChangesForIntegration;
exports.getRelevantFilesForIntegration = getRelevantFilesForIntegration;
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const clack_1 = __importDefault(require("./clack"));
const zod_1 = __importDefault(require("zod"));
const query_1 = require("./query");
const fast_glob_1 = __importDefault(require("fast-glob"));
const analytics_1 = require("./analytics");
const clack_utils_1 = require("./clack-utils");
const config_1 = require("../lib/config");
const prompts_1 = require("../lib/prompts");
exports.GLOBAL_IGNORE_PATTERN = [
'node_modules',
'dist',
'build',
'public',
'static',
'.git',
'.next',
];
async function getAllFilesInProject(dir) {
let results = [];
const entries = await fs_1.default.promises.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path_1.default.join(dir, entry.name);
if (exports.GLOBAL_IGNORE_PATTERN.some((pattern) => fullPath.includes(pattern))) {
continue;
}
if (entry.isDirectory()) {
// Recursively get files from subdirectories
const subDirFiles = await getAllFilesInProject(fullPath);
results = results.concat(subDirFiles);
}
else {
results.push(fullPath);
}
}
return results;
}
function getDotGitignore({ installDir, }) {
const gitignorePath = path_1.default.join(installDir, '.gitignore');
const gitignoreExists = fs_1.default.existsSync(gitignorePath);
if (gitignoreExists) {
return gitignorePath;
}
return undefined;
}
async function updateFile(change, { installDir }) {
const dir = path_1.default.dirname(path_1.default.join(installDir, change.filePath));
await fs_1.default.promises.mkdir(dir, { recursive: true });
await fs_1.default.promises.writeFile(path_1.default.join(installDir, change.filePath), change.newContent);
}
async function getFilesToChange({ integration, relevantFiles, documentation, accessToken, cloudRegion, projectId, }) {
const filterFilesSpinner = clack_1.default.spinner();
filterFilesSpinner.start('Selecting files to change...');
const filterFilesResponseSchmea = zod_1.default.object({
files: zod_1.default.array(zod_1.default.string()),
});
const prompt = await prompts_1.baseFilterFilesPromptTemplate.format({
documentation,
file_list: relevantFiles.join('\n'),
integration_name: integration,
integration_rules: config_1.INTEGRATION_CONFIG[integration].filterFilesRules,
});
const filterFilesResponse = await (0, query_1.query)({
message: prompt,
schema: filterFilesResponseSchmea,
accessToken,
region: cloudRegion,
projectId,
});
const filesToChange = filterFilesResponse.files;
filterFilesSpinner.stop(`Found ${filesToChange.length} files to change`);
analytics_1.analytics.capture('wizard interaction', {
action: 'detected files to change',
integration,
files: filesToChange,
});
return filesToChange;
}
async function generateFileContent({ prompt, accessToken, cloudRegion, projectId, }) {
const response = await (0, query_1.query)({
message: prompt,
schema: zod_1.default.object({
newContent: zod_1.default.string(),
}),
accessToken: accessToken,
region: cloudRegion,
projectId,
});
return response.newContent;
}
async function generateFileChangesForIntegration({ integration, filesToChange, accessToken, documentation, installDir, cloudRegion, projectId, }) {
const changes = [];
for (const filePath of filesToChange) {
const fileChangeSpinner = clack_1.default.spinner();
analytics_1.analytics.capture('wizard interaction', {
action: 'processing file',
integration,
file: filePath,
});
try {
let oldContent = undefined;
try {
oldContent = await fs_1.default.promises.readFile(path_1.default.join(installDir, filePath), 'utf8');
}
catch (readError) {
if (readError.code !== 'ENOENT') {
await (0, clack_utils_1.abort)(`Error reading file ${filePath}`);
continue;
}
}
fileChangeSpinner.start(`${oldContent ? 'Updating' : 'Creating'} file ${filePath}`);
const unchangedFiles = filesToChange.filter((filePath) => !changes.some((change) => change.filePath === filePath));
const prompt = await prompts_1.baseGenerateFileChangesPromptTemplate.format({
file_content: oldContent,
file_path: filePath,
documentation,
integration_name: config_1.INTEGRATION_CONFIG[integration].name,
integration_rules: config_1.INTEGRATION_CONFIG[integration].generateFilesRules,
changed_files: changes
.map((change) => `${change.filePath}\n${change.newContent}`)
.join('\n'),
unchanged_files: unchangedFiles,
});
const newContent = await generateFileContent({
prompt,
accessToken,
cloudRegion,
projectId,
});
if (newContent !== oldContent) {
await updateFile({ filePath, oldContent, newContent }, { installDir });
changes.push({ filePath, oldContent, newContent });
}
fileChangeSpinner.stop(`${oldContent ? 'Updated' : 'Created'} file ${filePath}`);
analytics_1.analytics.capture('wizard interaction', {
action: 'processed file',
integration,
file: filePath,
});
}
catch (error) {
await (0, clack_utils_1.abort)(`Error processing file ${filePath}`);
}
}
analytics_1.analytics.capture('wizard interaction', {
action: 'completed file changes',
integration,
files: filesToChange,
});
return changes;
}
async function getRelevantFilesForIntegration({ installDir, integration, }) {
const filterPatterns = config_1.INTEGRATION_CONFIG[integration].filterPatterns;
const ignorePatterns = config_1.INTEGRATION_CONFIG[integration].ignorePatterns;
const filteredFiles = await (0, fast_glob_1.default)(filterPatterns, {
cwd: installDir,
ignore: ignorePatterns,
});
analytics_1.analytics.capture('wizard interaction', {
action: 'detected relevant files',
integration,
number_of_files: filteredFiles.length,
});
return filteredFiles;
}
//# sourceMappingURL=file-utils.js.map