wiki-interface/lib/api/v1.js (427 lines of code) (raw):
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const crypto = require("crypto");
const configFile = require('../../lib/config/file');
const configEnv = require('../../lib/config/env');
const gitlabOperator = require('../../lib/gitlab/wiki');
const fileUtils = require('../../lib/file/file');
const gitOperator = require('../../lib/git/utils');
const aiOperator = require('../../lib/rest-ai/client');
const mdOperator = require('../../lib/markdown/mdhelper');
const imgOperator = require('../../lib/markdown/imghelper');
const vertexUtils = require('../../lib/vertex/vertex');
const gcsUtils = require('../../lib/gcs/gcs');
const gitUtils = require('../../lib/git/utils');
/* build a list for User Stories */
async function getUsOptions(projectId) {
/* Loading Wiki data */
let wikiList = await gitlabOperator.listWiki(projectId);
let options = [];
/* Sorting Data */
wikiList = wikiList.sort(function (a, b) {
let x = a.title.toLowerCase();
let y = b.title.toLowerCase();
if (x > y) { return 1; }
if (x < y) { return -1; }
return 0;
});
for (let thisWiki of wikiList) {
if (!thisWiki.title.includes(configFile.getGeneratorsufix()) && !thisWiki.title.includes(configFile.getCypresssufix()) &&
!thisWiki.title.includes(configFile.getPlaywrightsufix()) && !thisWiki.title.includes(configFile.getEvaluatorsufix())) {
let thisOption = {
value: thisWiki.slug,
label: thisWiki.title
}
options.push(thisOption);
}
}
return options;
}
/* build an HTML list for User Stories */
async function getTcOptions(projectId) {
/* Loading Wiki data */
let wikiList = await gitlabOperator.listWiki(projectId);
let options = [];
/* Sorting Data */
wikiList = wikiList.sort(function (a, b) {
let x = a.title.toLowerCase();
let y = b.title.toLowerCase();
if (x > y) { return 1; }
if (x < y) { return -1; }
return 0;
});
for (let thisWiki of wikiList) {
if (!thisWiki.title.includes(configFile.getGeneratorsufix()) && !thisWiki.title.includes(configFile.getCypresssufix()) &&
!thisWiki.title.includes(configFile.getPlaywrightsufix()) && !thisWiki.title.includes(configFile.getEvaluatorsufix())) {
let thisOption = {
value: thisWiki.slug,
label: thisWiki.title
}
options.push(thisOption);
}
}
return options;
}
/* build an HTML list for Test Cases */
async function getTsOptions(projectId) {
/* Loading Wiki data */
let wikiList = await gitlabOperator.listWiki(projectId);
let options = [];
/* Sorting Data */
wikiList = wikiList.sort(function (a, b) {
let x = a.title.toLowerCase();
let y = b.title.toLowerCase();
if (x > y) { return 1; }
if (x < y) { return -1; }
return 0;
});
for (let thisWiki of wikiList) {
if (thisWiki.title.includes(configFile.getGeneratorsufix())) {
let thisOption = {
value: thisWiki.slug,
label: thisWiki.title
}
options.push(thisOption);
}
}
return options;
}
async function processUserStory(projectId, documentId) {
let transactionId = crypto.randomUUID();
let pageObject = await gitlabOperator.getWiki(projectId, documentId);
let pageContent = pageObject.content;
let newPagePath = documentId + "_" + configFile.getEvaluatorsufix();
let newPageContent = await aiOperator.generateEvaluation(pageContent);
let thisResponse = {
projectId: projectId,
documentId: documentId,
transactionId: transactionId,
pagePath: newPagePath,
pageContent: newPageContent
}
return thisResponse;
}
async function processTestCase(projectId, documentId) {
let transactionId = crypto.randomUUID();
let pageObject = await gitlabOperator.getWiki(projectId, documentId);
let pageContent = pageObject.content;
/* Checking if markdown has images */
let imgCheck = await mdOperator.checkImagesOnMarkdown(pageContent);
if (imgCheck) {
/* Get project URL */
let baseUrl = await gitlabOperator.getProjectUrl(projectId);
/* Clone wiki git repo */
if (await gitOperator.cloneWiki(baseUrl, projectId)) {
let allImages = await mdOperator.extractImagesFromMarkdown(pageContent);
/* Process each image */
for (let i = 0; i < allImages.length; i++) {
let imgName = allImages[i].altText;
let imgUrl = allImages[i].url;
let imgMime = await imgOperator.getMimeType(imgUrl);
let imgContent = await gitOperator.getFileFromRepo(projectId, imgUrl);
let imgHash = await imgOperator.getBase64(imgContent);
let imageDesc = await aiOperator.describeImage(imgMime, imgHash);
pageContent = await mdOperator.replaceImagesInMarkdown(pageContent, imgName, imageDesc);
}
await gitOperator.deleteClone(projectId);
}
}
let newPagePath = documentId + "_" + configFile.getGeneratorsufix();
let newPageContent = await aiOperator.generateDoc(pageContent);
let thisResponse = {
projectId: projectId,
documentId: documentId,
transactionId: transactionId,
pagePath: newPagePath,
pageContent: newPageContent
}
return thisResponse;
}
async function processCypress(projectId, documentId) {
let transactionId = crypto.randomUUID();
let pageObject = await gitlabOperator.getWiki(projectId, documentId);
let pageContent = pageObject.content;
let newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getCypresssufix());
let newPageContent = await aiOperator.generateCypress(pageContent);
let thisResponse = {
projectId: projectId,
documentId: documentId,
transactionId: transactionId,
pagePath: newPagePath,
pageContent: newPageContent
}
return thisResponse;
}
async function processPlaywright(projectId, documentId) {
let transactionId = crypto.randomUUID();
let pageObject = await gitlabOperator.getWiki(projectId, documentId);
let pageContent = pageObject.content;
let newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getPlaywrightsufix());
let newPageContent = await aiOperator.generatePlaywright(pageContent);
let thisResponse = {
projectId: projectId,
documentId: documentId,
transactionId: transactionId,
pagePath: newPagePath,
pageContent: newPageContent
}
return thisResponse;
}
async function processSelenium(projectId, documentId) {
let transactionId = crypto.randomUUID();
let pageObject = await gitlabOperator.getWiki(projectId, documentId);
let pageContent = pageObject.content;
let newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getSeleniumsufix());
let newPageContent = await aiOperator.generateSelenium(pageContent);
let thisResponse = {
projectId: projectId,
documentId: documentId,
transactionId: transactionId,
pagePath: newPagePath,
pageContent: newPageContent
}
return thisResponse;
}
async function processCodeSearch(projectId, repoId, userQuery) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let searchResults = await aiOperator.generateCodeSearch(codeBase, userQuery);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "code-search",
pageContent: searchResults
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionOverview(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionOverview(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-overview",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionDatabase(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionDatabase(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-database",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionAPI(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionAPI(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-api",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionDep(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionDep(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-dependency",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionIntegration(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionIntegration(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-dependency",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function processSolutionSecurity(projectId, repoId) {
let transactionId = crypto.randomUUID();
let codeBase = "";
if (repoId != "") {
/* Clone Repo */
await gitUtils.cloneGitRepo(repoId, configEnv.getGitToken(), transactionId);
/* Preparing context for AI */
let dirPath = configFile.getWorkDir() + "/" + transactionId;
codeBase = await fileUtils.getAllFilesContentsForService(dirPath, transactionId);
gitUtils.removeLocalSource(transactionId);
let codeReport = await aiOperator.generateSolutionSecurity(codeBase);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "solution-security",
pageContent: codeReport
}
return thisResponse;
} else {
return null;
}
}
async function checkDocumentExists(projectId, documentId, modelId) {
let newPagePath = documentId;
switch (modelId) {
case "evaluator":
newPagePath = documentId + "_" + configFile.getEvaluatorsufix();
break;
case "testcase":
newPagePath = documentId + "_" + configFile.getGeneratorsufix();
break;
case "script-cypress":
newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getCypresssufix());
break;
case "script-playwright":
newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getPlaywrightsufix());
break;
case "script-selenium":
newPagePath = documentId.replace(configFile.getGeneratorsufix(), configFile.getSeleniumsufix());
break;
default:
newPagePath = documentId;
break;
}
let pageObject = await gitlabOperator.getWiki(projectId, newPagePath);
if (pageObject != null) {
return true;
} else {
return false;
}
}
async function processTestData(projectId, modelId, documentId, sampleQty) {
let transactionId = crypto.randomUUID();
let newContent = await aiOperator.generateTestData(modelId, documentId, sampleQty);
let thisResponse = {
projectId: projectId,
documentId: "do-not-save",
transactionId: transactionId,
pagePath: "test-data",
pageContent: newContent
}
return thisResponse;
}
async function checkChatSession(chatSession) {
let response = {
"status": ""
}
if (await gcsUtils.sysinfoExistsSync(chatSession) && await gcsUtils.historyExistsSync(chatSession)) {
response.status = "OK";
} else {
response.status = "NOT_FOUND";
}
return response;
}
async function sendCodeChatMessage(chatSession, inputMessage) {
let responseText = await vertexUtils.sendCodeMessage(chatSession, inputMessage)
let response = {
"chatSession": chatSession,
"message": responseText
}
return response;
}
async function sendDocChatMessage(chatSession, inputMessage) {
let responseText = await vertexUtils.sendDocMessage(chatSession, inputMessage)
let response = {
"chatSession": chatSession,
"message": responseText
}
return response;
}
async function getProjects() {
let response = [];
let allProjects = await gitlabOperator.getProjectList()
for (let thisProject of allProjects) {
let thisEntry = {
projectId: thisProject.id,
projectName: thisProject.name
};
response.push(thisEntry)
}
return response;
}
async function getProjectName(projectId) {
let thisProject = await gitlabOperator.getProjectName(projectId);
return thisProject;
}
async function createDocument(projectId, newPagePath, documentContent) {
let response = await gitlabOperator.createWikiPage(projectId, newPagePath, documentContent);
return response;
}
module.exports.getUsOptions = getUsOptions;
module.exports.getTcOptions = getTcOptions;
module.exports.getTsOptions = getTsOptions;
module.exports.processUserStory = processUserStory;
module.exports.processTestCase = processTestCase;
module.exports.processCypress = processCypress;
module.exports.processPlaywright = processPlaywright;
module.exports.processSelenium = processSelenium;
module.exports.processCodeSearch = processCodeSearch;
module.exports.processSolutionOverview = processSolutionOverview;
module.exports.processSolutionDatabase = processSolutionDatabase;
module.exports.processSolutionAPI = processSolutionAPI;
module.exports.processSolutionDep = processSolutionDep;
module.exports.processSolutionIntegration = processSolutionIntegration;
module.exports.processSolutionSecurity = processSolutionSecurity;
module.exports.checkDocumentExists = checkDocumentExists;
module.exports.processTestData = processTestData;
module.exports.checkChatSession = checkChatSession;
module.exports.sendCodeChatMessage = sendCodeChatMessage;
module.exports.sendDocChatMessage = sendDocChatMessage;
module.exports.getProjects = getProjects;
module.exports.getProjectName = getProjectName;
module.exports.createDocument = createDocument;