From 205cdb118dd64c2eaf23ffdcf5e5ba01fd0dd5d7 Mon Sep 17 00:00:00 2001 From: PrashamTrivedi Date: Mon, 12 Aug 2024 13:31:08 +0000 Subject: [PATCH] Setting up expertise and questionnaire --- commands/analyse.mts | 22 +- commands/getDirStructure.mts | 40 +++- commands/prepareReport.mts | 12 +- commands/setExpertise.mts | 90 ++++++++ index.mts | 3 + package-lock.json | 398 ++++++++++++++++++++++++++++++++++- package.json | 15 +- utils.mts | 10 + 8 files changed, 563 insertions(+), 27 deletions(-) create mode 100644 commands/setExpertise.mts diff --git a/commands/analyse.mts b/commands/analyse.mts index f6dcfc2..2054080 100644 --- a/commands/analyse.mts +++ b/commands/analyse.mts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import {FileNode, getDirStructure} from "../directoryProcessor.mjs" import OpenAIInferrence, {LlmInterface} from "../openai.mjs" import fs from 'fs' @@ -6,8 +7,11 @@ import ora from 'ora' import {Arguments} from 'yargs' import {ChatCompletionChunk} from "openai/resources/index.mjs" import {Stream} from "openai/streaming.mjs" - import chalk from "chalk" +import {confirm} from '@inquirer/prompts' +import {handler as setExpertiseHandler} from './setExpertise.mjs' + + // Export these functions for testing export { @@ -73,7 +77,6 @@ export async function handler(argv: Arguments) { console.log(`Analyse the given directory structure to understand the project structure and dependencies: ${argv.path}`) } const config = readConfig() - const rootDir = config.ANALYSIS_DIR const projectName = argv.path as string @@ -96,6 +99,7 @@ export async function handler(argv: Arguments) { const sourceCodePath = argv.path as string const dirToWriteAnalysis = isProjectRoot ? `${sourceCodePath}/.SourceSailor` : `${rootDir}/.SourceSailor/${projectName}` + const {directoryInferrence, directoryStructureWithContent} = await analyseDirectoryStructure(path, isVerbose, isRoot, dirToWriteAnalysis, useOpenAi, isProjectRoot, ignore, llmInterface) @@ -146,13 +150,19 @@ export async function handler(argv: Arguments) { } } - + } + if (!config.userExpertise) { + console.log(chalk.yellow("User expertise is not set. Setting your expertise level will help us provide more tailored analysis.")) + const setExpertise = await confirm({message: "Would you like to set your expertise now?", default: true}) + if (setExpertise) { + await setExpertiseHandler() + } } } async function analyseDirectoryStructure(path: string, isVerbose: boolean | undefined, - isRoot: boolean, projectName: string, useOpenAi: any, isProjectRoot: boolean | undefined, + isRoot: boolean, projectName: string, useOpenAi: boolean, isProjectRoot: boolean | undefined, ignore: string[], llm: LlmInterface) { const spinner = ora('Analyzing the directory structure...').start() const directoryStructureWithContent = await getDirStructure(path, ignore, isVerbose) @@ -314,7 +324,9 @@ async function getDirectoryWithoutLockfile(directoryInferrence: any, directorySt const lockfile = directoryInferrence.lockFile const directoryStructureWithoutLockFile = JSON.parse(JSON.stringify(directoryStructureWithContent)) removeLockFile(directoryStructureWithoutLockFile, lockfile) - + if (isVerbose) { + console.log({directoryStructureWithoutLockFile}) + } return directoryStructureWithoutLockFile } diff --git a/commands/getDirStructure.mts b/commands/getDirStructure.mts index d92bebb..59e4e6d 100644 --- a/commands/getDirStructure.mts +++ b/commands/getDirStructure.mts @@ -1,13 +1,16 @@ import chalk from "chalk" -import {readConfig} from "../utils.mjs" import {getDirStructure, FileNode} from "../directoryProcessor.mjs" - +import {Argv} from 'yargs' +import {Arguments} from 'yargs' +import {readConfig} from "../utils.mjs" +import {confirm} from '@inquirer/prompts' +import {handler as setExpertiseHandler} from './setExpertise.mjs' export const command = 'dirStructure [verbose|v] [withContent|c] [ignore|i]' export const describe = 'Get Directory Structure' -import {Argv} from 'yargs' + export function builder(yargs: Argv) { yargs.positional('path', { @@ -41,7 +44,6 @@ export function builder(yargs: Argv) { return yargs } -import {Arguments} from 'yargs' export async function handler(argv: Arguments) { const isVerbose = argv.verbose as boolean || argv.v as boolean || false @@ -52,6 +54,8 @@ export async function handler(argv: Arguments) { } const projectName = argv.path as string + const config = readConfig() + if (isVerbose) { console.log(`Project Name: ${projectName}`) } @@ -73,15 +77,12 @@ export async function handler(argv: Arguments) { } else { const directoryStructure = JSON.parse(JSON.stringify(directoryStructureWithContent)) - function deleteContent(file: FileNode) { - delete file.content - if (file.children) { - for (const child of file.children) { - deleteContent(child) - } - } + for (const file of directoryStructure.children) { + deleteContent(file) } + + for (const file of directoryStructure.children) { deleteContent(file) } @@ -90,6 +91,23 @@ export async function handler(argv: Arguments) { } catch (error) { console.error('Error analyzing directory structure:', error) } + + if (!config.userExpertise) { + console.log(chalk.yellow("User expertise is not set. Setting your expertise level will help us provide more tailored analysis.")) + const setExpertise = await confirm({message: "Would you like to set your expertise now?", default: true}) + if (setExpertise) { + await setExpertiseHandler() + } + } +} + +function deleteContent(file: FileNode) { + delete file.content + if (file.children) { + for (const child of file.children) { + deleteContent(child) + } + } } export const usage = '$0 [args]' diff --git a/commands/prepareReport.mts b/commands/prepareReport.mts index 4ef56af..2249b50 100644 --- a/commands/prepareReport.mts +++ b/commands/prepareReport.mts @@ -5,6 +5,9 @@ import OpenAIInferrence, {LlmInterface} from "../openai.mjs" import ora from "ora" import {ChatCompletionChunk} from "openai/resources/index.mjs" import {Stream} from "openai/streaming.mjs" +import chalk from "chalk" +import {confirm} from '@inquirer/prompts' +import {handler as setExpertiseHandler} from './setExpertise.mjs' export const command = 'prepareReport [verbose|v] [streaming|s]' @@ -41,7 +44,6 @@ export async function handler(argv: Arguments) { const allowStreaming = argv.streaming as boolean || argv.s as boolean || false const projectDir = argv.path as string || argv.p as string const config = readConfig() - const openai = new OpenAIInferrence() const llmInterface: LlmInterface = openai const rootDir = config.ANALYSIS_DIR @@ -90,6 +92,14 @@ export async function handler(argv: Arguments) { readmeResponse = reportAsText } } + + if (!config.userExpertise) { + console.log(chalk.yellow("User expertise is not set. Setting your expertise level will help us provide more tailored reports.")) + const setExpertise = await confirm({message: "Would you like to set your expertise now?", default: true}) + if (setExpertise) { + await setExpertiseHandler() + } + } } export const usage = '$0 [args]' diff --git a/commands/setExpertise.mts b/commands/setExpertise.mts new file mode 100644 index 0000000..6a9fcb4 --- /dev/null +++ b/commands/setExpertise.mts @@ -0,0 +1,90 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import {readConfig, writeConfig} from '../utils.mjs' +import chalk from 'chalk' +import {confirm, select} from '@inquirer/prompts' +export const command = 'set-expertise' + +export const describe = 'Set the user expertise level for various programming languages and frameworks' + +export function builder(yargs: any) { + return yargs +} +interface Language { + name: string, frameworks: string[] +} + +interface Choice { + name: string, value: string, description: string +} + +const languages: Language[] = [ + {name: 'JavaScript', frameworks: ['React', 'Angular', 'Vue.js', 'Express', 'Node.js']}, + {name: 'Python', frameworks: ['Django', 'Flask', 'FastAPI', 'Pyramid']}, + {name: 'Java', frameworks: ['Spring', 'Hibernate', 'Struts', 'JavaServer Faces']}, + {name: 'C#', frameworks: ['.NET Core', 'ASP.NET', 'Entity Framework', 'Xamarin']}, + {name: 'Ruby', frameworks: ['Ruby on Rails', 'Sinatra', 'Hanami']}, + {name: 'PHP', frameworks: ['Laravel', 'Symfony', 'CodeIgniter', 'Yii']}, + {name: 'Go', frameworks: ['Gin', 'Echo', 'Beego', 'Revel']}, + {name: 'Rust', frameworks: ['Rocket', 'Actix', 'Warp', 'Tide']}, + {name: 'TypeScript', frameworks: ['NestJS', 'Deno', 'Angular', 'Next.js']}, + {name: 'Swift', frameworks: ['SwiftUI', 'Vapor', 'Perfect', 'Kitura']} +] + +const expertiseLevels: Choice[] = [ + {name: 'Beginner', value: 'beginner', description: 'Beginner'}, + {name: 'Intermediate', value: 'intermediate', description: 'Intermediate'}, + {name: 'Expert', value: 'expert', description: 'Expert'} +] + +export async function handler() { + try { + const config = await readConfig() + config.userExpertise = {} + + console.log(chalk.blue('Welcome to the expertise assessment questionnaire!')) + console.log(chalk.yellow('Please answer the following questions about your programming expertise.')) + + for (const lang of languages) { + const knowsLanguage = await confirm({ + message: `Do you have experience with ${lang.name}?`, + default: false + }) + + if (knowsLanguage) { + const languageLevel = await select({ + message: `What is your expertise level in ${lang.name}?`, + choices: expertiseLevels, + default: 'beginner' + }) + + config.userExpertise[lang.name] = languageLevel + + for (const framework of lang.frameworks) { + const knowsFramework = await confirm({ + message: `Do you have experience with ${framework}?`, + default: false + }) + + if (knowsFramework) { + const frameworkLevel = await select({ + message: `What is your expertise level in ${framework}?`, + choices: expertiseLevels, + default: 'beginner' + }) + + config.userExpertise[framework] = frameworkLevel + } + } + } + } + + await writeConfig(config) + console.log(chalk.green('Expertise levels have been successfully set and saved!')) + } catch (error) { + console.error(chalk.red('Error setting user expertise levels:'), error) + } +} + +export const usage = '$0 ' + +export const aliases = ['expertise', 'skill-level', 'h', 'help'] diff --git a/index.mts b/index.mts index a7341da..3999939 100755 --- a/index.mts +++ b/index.mts @@ -9,6 +9,7 @@ import * as ListConfigProcessor from "./commands/listConfig.mjs" import * as UpdateConfigProcessor from "./commands/updateConfig.mjs" import * as PrepareReportProcessor from "./commands/prepareReport.mjs" import * as GetDirStructure from "./commands/getDirStructure.mjs" +import * as SetExpertiseCommand from "./commands/setExpertise.mjs" const yargsSetup = yargs(hideBin(process.argv)) // console.log("Hello there") @@ -27,6 +28,8 @@ yargsSetup. .command(UpdateConfigProcessor) .command(PrepareReportProcessor) .command(GetDirStructure) + .command(SetExpertiseCommand) + .help() .alias('h', 'help') .demandCommand(1) diff --git a/package-lock.json b/package-lock.json index 59e07f5..e908ddb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "1.4.4", "license": "ISC", "dependencies": { + "@inquirer/prompts": "^5.3.8", "boxen": "^7.1.1", "chalk": "^5.3.0", "ignore": "^5.3.1", + "inquirer": "^10.1.8", "openai": "^4.33.1", "ora": "^8.0.1", "tiktoken": "^1.0.13", @@ -21,6 +23,7 @@ "SourceSailor": "dist/index.mjs" }, "devDependencies": { + "@types/inquirer": "^9.0.7", "@types/node": "^20.12.13", "@types/yargs": "^17.0.32", "@typescript-eslint/eslint-plugin": "^7.3.1", @@ -909,6 +912,226 @@ "deprecated": "Use @eslint/object-schema instead", "dev": true }, + "node_modules/@inquirer/checkbox": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.4.7.tgz", + "integrity": "sha512-5YwCySyV1UEgqzz34gNsC38eKxRBtlRDpJLlKcRtTjlYA/yDKuc1rfw+hjw+2WJxbAZtaDPsRl5Zk7J14SBoBw==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "dependencies": { + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/@types/node": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", + "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@inquirer/core/node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.22.tgz", + "integrity": "sha512-K1QwTu7GCK+nKOVRBp5HY9jt3DXOfPGPr6WRDrPImkcJRelG9UTx2cAtK1liXmibRrzJlTWOwqgWT3k2XnS62w==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.22.tgz", + "integrity": "sha512-wTZOBkzH+ItPuZ3ZPa9lynBsdMp6kQ9zbjVPYEtSBG7UulGjg2kQiAnUjgyG4SlntpTce5bOmXAPvE4sguXjpA==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.9.tgz", + "integrity": "sha512-7Z6N+uzkWM7+xsE+3rJdhdG/+mQgejOVqspoW+w0AbSZnL6nq5tGMEVASaYVWbkoSzecABWwmludO2evU3d31g==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/number": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.0.10.tgz", + "integrity": "sha512-kWTxRF8zHjQOn2TJs+XttLioBih6bdc5CcosXIzZsrTY383PXI35DuhIllZKu7CdXFi2rz2BWPN9l0dPsvrQOA==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.22.tgz", + "integrity": "sha512-5Fxt1L9vh3rAKqjYwqsjU4DZsEvY/2Gll+QkqR4yEpy6wvzLxdSgFhUcxfDAOtO4BEoTreWoznC0phagwLU5Kw==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.3.8.tgz", + "integrity": "sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==", + "dependencies": { + "@inquirer/checkbox": "^2.4.7", + "@inquirer/confirm": "^3.1.22", + "@inquirer/editor": "^2.1.22", + "@inquirer/expand": "^2.1.22", + "@inquirer/input": "^2.2.9", + "@inquirer/number": "^1.0.10", + "@inquirer/password": "^2.1.22", + "@inquirer/rawlist": "^2.2.4", + "@inquirer/search": "^1.0.7", + "@inquirer/select": "^2.4.7" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.2.4.tgz", + "integrity": "sha512-pb6w9pWrm7EfnYDgQObOurh2d2YH07+eDo3xQBsNAM2GRhliz6wFXGi1thKQ4bN6B0xDd6C3tBsjdr3obsCl3Q==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/search": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.0.7.tgz", + "integrity": "sha512-p1wpV+3gd1eST/o5N3yQpYEdFNCzSP0Klrl+5bfD3cTTz8BGG6nf4Z07aBW0xjlKIj1Rp0y3x/X4cZYi6TfcLw==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.4.7.tgz", + "integrity": "sha512-JH7XqPEkBpNWp3gPCqWqY8ECbyMoFcCZANlL6pV9hf59qK6dGmkOlx1ydyhY+KZ0c5X74+W6Mtp+nm2QX0/MAQ==", + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1337,6 +1560,24 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/inquirer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", + "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", + "dev": true, + "dependencies": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.14.15", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz", @@ -1355,6 +1596,20 @@ "form-data": "^4.0.0" } }, + "node_modules/@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -1789,6 +2044,31 @@ "string-width": "^4.1.0" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2072,6 +2352,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -2118,6 +2403,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2612,6 +2905,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3011,6 +3328,23 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/inquirer": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-10.1.8.tgz", + "integrity": "sha512-syxGpOzLyqVeZi1KDBjRTnCn5PiGWySGHP0BbqXbqsEK0ckkZk3egAepEWslUjZXj0rhkUapVXM/IpADWe4D6w==", + "dependencies": { + "@inquirer/prompts": "^5.3.8", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "ansi-escapes": "^4.3.2", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3450,6 +3784,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -3680,6 +4022,14 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -3999,6 +4349,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4022,12 +4380,18 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "optional": true, - "peer": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { "version": "7.6.2", @@ -4072,7 +4436,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -4337,6 +4700,17 @@ "node": ">=14.0.0" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4386,6 +4760,11 @@ "typescript": ">=4.2.0" } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4812,6 +5191,17 @@ "engines": { "node": ">=12" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index f9d14f3..1cc5491 100644 --- a/package.json +++ b/package.json @@ -31,22 +31,25 @@ "author": "Prasham H Trivedi", "license": "ISC", "dependencies": { + "@inquirer/prompts": "^5.3.8", + "boxen": "^7.1.1", "chalk": "^5.3.0", "ignore": "^5.3.1", + "inquirer": "^10.1.8", "openai": "^4.33.1", "ora": "^8.0.1", "tiktoken": "^1.0.13", - "yargs": "^17.7.2", - "boxen": "^7.1.1" + "yargs": "^17.7.2" }, "devDependencies": { + "@types/inquirer": "^9.0.7", "@types/node": "^20.12.13", "@types/yargs": "^17.0.32", - "@vitest/coverage-istanbul": "^2.0.0", - "typescript": "^5.4.5", - "vitest": "^2.0.0", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", - "eslint": "^8.57.0" + "@vitest/coverage-istanbul": "^2.0.0", + "eslint": "^8.57.0", + "typescript": "^5.4.5", + "vitest": "^2.0.0" } } diff --git a/utils.mts b/utils.mts index 94d80d1..9a5ad95 100644 --- a/utils.mts +++ b/utils.mts @@ -17,6 +17,16 @@ export function readConfig() { return {} } +export function writeConfig(config: any) { + const homeDir = os.homedir() + const configDir = path.join(homeDir, '.SourceSailor') + const configFile = path.join(configDir, 'config.json') + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }) + } + fs.writeFileSync(configFile, JSON.stringify(config, null, 2)) +} + export function addAnalysisInGitIgnore(projectRoot: string) { // First check if the project root has gitignore file, if the file is not found don't create one. // If the file is found, append .SourceSailor/analysis to the file.