From 3c1cd5e8367fa462c642a9a4e467bc3f1f0ac6b6 Mon Sep 17 00:00:00 2001 From: Timur Moziev Date: Wed, 25 Sep 2024 17:28:20 +0000 Subject: [PATCH] add bulk action support from cli refactor actions to separate file --- anca.json | 4 +- src/action.ts | 243 +++++++++++++++++++++++++++++++++++++++ src/cinnabar.ts | 4 +- src/developments.ts | 41 ++++++- src/index.ts | 23 +++- src/schema.ts | 29 +++++ src/tui.ts | 273 ++------------------------------------------ 7 files changed, 342 insertions(+), 275 deletions(-) create mode 100644 src/action.ts diff --git a/anca.json b/anca.json index 86bdcaf..5b1d97c 100644 --- a/anca.json +++ b/anca.json @@ -13,8 +13,8 @@ "dataVersion": 0, "version": { "latest": "0.1.0-dev.3", - "latestNext": "0.1.0-dev.3+next.20240925_144217", - "timestamp": 1727275337 + "latestNext": "0.1.0-dev.3+next.20240925_172241", + "timestamp": 1727284961 }, "files": [ { diff --git a/src/action.ts b/src/action.ts new file mode 100644 index 0000000..9eee244 --- /dev/null +++ b/src/action.ts @@ -0,0 +1,243 @@ +import { fixAncaConfig } from "./actions/anca.js"; +import { fixContributingMd } from "./actions/contributing.js"; +import { + fixDevcontainerDockerfile, + fixDevcontainerJson, +} from "./actions/devcontainers.js"; +import { fixGitIgnore } from "./actions/git.js"; +import { + fixGithubActionsOtherFiles, + fixGithubActionsRelease, + fixGithubActionsTest, +} from "./actions/github-actions.js"; +import { fixLicenseMd } from "./actions/license.js"; +import { + fixNodejsPackageJson, + getUpdatedPackagesCommitMessage, + installNodejsDependencies, + NodejsPackageJson, + NpmUpdate, + updateNodejsPackageJsonDependencies, + updateNodejsPackageJsonDevDependencies, + writeNodejsPackageJson, +} from "./actions/nodejs.js"; +import { fixNodejsEsbuildJs } from "./actions/nodejs-esbuild.js"; +import { fixNodejsEslintConfigJs } from "./actions/nodejs-eslint.js"; +import { generateNodejsOpenapiFiles } from "./actions/nodejs-openapi.js"; +import { + fixNodejsPrettierIgnore, + fixNodejsPrettierRc, +} from "./actions/nodejs-prettier.js"; +import { + fixNodejsSeaBuildJs, + fixNodejsSeaConfigJson, +} from "./actions/nodejs-sea.js"; +import { fixNodejsSrc, fixNodejsTest } from "./actions/nodejs-src.js"; +import { fixNodejsTsconfigJson } from "./actions/nodejs-tsconfig.js"; +import { fixNodejsTsupConfigJs } from "./actions/nodejs-tsup.js"; +import { fixOpenapiJson } from "./actions/openapi.js"; +import { fixReadmeMd } from "./actions/readme.js"; +import { syncDevelopment } from "./developments.js"; +import { AncaAction, AncaDevelopment } from "./schema.js"; + +const actionMappings: Record< + AncaAction, + { action: (development: AncaDevelopment) => Promise; label: string } +> = { + ancaJsonFix: { + action: async (development: AncaDevelopment) => { + await fixAncaConfig(development); + }, + label: "[anca.json] Fix", + }, + contributingSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixContributingMd(development); + }, + label: "[CONTRIBUTING.md] Set to default", + }, + devcontainerDockerfileSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixDevcontainerDockerfile(development); + }, + label: "[.devcontainer/Dockerfile] Set to default", + }, + devcontainerJsonSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixDevcontainerJson(development); + }, + label: "[.devcontainer/devcontainer.json] Set to default", + }, + gitClone: { + action: async (development: AncaDevelopment) => { + await syncDevelopment(development); + }, + label: "[git] Clone", + }, + githubActionsOtherFilesRemove: { + action: async (development: AncaDevelopment) => { + await fixGithubActionsOtherFiles(development); + }, + label: "[.github/workflows] Remove other files", + }, + githubActionsReleaseSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixGithubActionsRelease(development); + }, + label: "[.github/workflows/release.yml] Set to default", + }, + githubActionsTestSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixGithubActionsTest(development); + }, + label: "[.github/workflows/test.yml] Set to default", + }, + gitIgnoreSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixGitIgnore(development); + }, + label: "[.gitignore] Set to default", + }, + licenseSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixLicenseMd(development); + }, + label: "[LICENSE] Set to default", + }, + nodejsEsbuildSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsEsbuildJs(development); + }, + label: "[esbuild.js] Set to default", + }, + nodejsEslintSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsEslintConfigJs(development); + }, + label: "[eslint.config.js] Set to default", + }, + nodejsOpenapiSetToDefault: { + action: async (development: AncaDevelopment) => { + await generateNodejsOpenapiFiles(development); + }, + label: "[openapi] Set to default", + }, + nodejsPackageJsonCheckUpdates: { + action: async (development: AncaDevelopment) => { + const fileContents = development.state?.jsonFiles[ + "package.json" + ] as NodejsPackageJson; + if (fileContents != null) { + const rebuildFile: NodejsPackageJson = {}; + const npmUpdate: NpmUpdate = await updateNodejsPackageJsonDependencies( + rebuildFile, + development, + false, + true, + ); + npmUpdate.push( + ...(await updateNodejsPackageJsonDevDependencies( + rebuildFile, + development, + false, + true, + )), + ); + if (npmUpdate.length > 0) { + console.log("\nAdd to commit message: \n"); + console.log(getUpdatedPackagesCommitMessage(npmUpdate)); + console.log(); + } + fileContents.dependencies = rebuildFile.dependencies; + fileContents.devDependencies = rebuildFile.devDependencies; + await writeNodejsPackageJson(development); + await installNodejsDependencies(development); + } + }, + label: "[package.json] Check dependencies updates", + }, + nodejsPackageJsonFix: { + action: async (development: AncaDevelopment) => { + await fixNodejsPackageJson(development, false); + await writeNodejsPackageJson(development); + await installNodejsDependencies(development); + }, + label: "[package.json] Fix", + }, + nodejsPackageJsonFixFull: { + action: async (development: AncaDevelopment) => { + await fixNodejsPackageJson(development, true); + await writeNodejsPackageJson(development); + await installNodejsDependencies(development); + }, + label: "[package.json] Fix & add optional fields", + }, + nodejsPrettierIgnoreSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsPrettierIgnore(development); + }, + label: "[.prettierignore] Set to default", + }, + nodejsPrettierRcSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsPrettierRc(development); + }, + label: "[.prettierrc] Set to default", + }, + nodejsSeaBuildJsSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsSeaBuildJs(development); + }, + label: "[sea.build.js] Set to default", + }, + nodejsSeaConfigJsonSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsSeaConfigJson(development); + }, + label: "[sea.config.json] Set to default", + }, + nodejsSrcSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsSrc(development); + }, + label: "[src/index.ts] Set to default", + }, + nodejsTestSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsTest(development); + }, + label: "[test/index.test.ts] Set to default", + }, + nodejsTsconfigSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsTsconfigJson(development); + }, + label: "[tsconfig.json] Set to default", + }, + nodejsTsupConfigJsSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixNodejsTsupConfigJs(development); + }, + label: "[tsup.config.js] Set to default", + }, + openapiJsonSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixOpenapiJson(development); + }, + label: "[openapi.json] Set to default", + }, + readmeSetToDefault: { + action: async (development: AncaDevelopment) => { + await fixReadmeMd(development); + }, + label: "[README.md] Set to default", + }, +}; + +/** + * + * @param action + */ +export function getAction(action: AncaAction) { + return actionMappings[action]; +} diff --git a/src/cinnabar.ts b/src/cinnabar.ts index 9e09829..b1ca9b3 100644 --- a/src/cinnabar.ts +++ b/src/cinnabar.ts @@ -1,4 +1,4 @@ // This file was generated by Cinnabar Meta. Do not edit. -export const CINNABAR_PROJECT_TIMESTAMP = 1727275337; -export const CINNABAR_PROJECT_VERSION = "0.1.0-dev.3+next.20240925_144217"; +export const CINNABAR_PROJECT_TIMESTAMP = 1727284961; +export const CINNABAR_PROJECT_VERSION = "0.1.0-dev.3+next.20240925_172241"; diff --git a/src/developments.ts b/src/developments.ts index f7a3a9e..f837a30 100644 --- a/src/developments.ts +++ b/src/developments.ts @@ -2,6 +2,7 @@ import { mergician } from "mergician"; import path from "path"; import pc from "picocolors"; +import { getAction } from "./action.js"; import { checkAnca } from "./actions/anca.js"; import { checkContributingMd } from "./actions/contributing.js"; import { @@ -33,7 +34,13 @@ import { checkOpenapiJson } from "./actions/openapi.js"; import { checkReadmeMd } from "./actions/readme.js"; import { checkForGit, getGit } from "./git.js"; import { getDevelopmentMeta } from "./meta.js"; -import { AncaConfig, AncaDevelopment, AncaDevelopmentState } from "./schema.js"; +import { + ANCA_ACTIONS, + AncaAction, + AncaConfig, + AncaDevelopment, + AncaDevelopmentState, +} from "./schema.js"; import { checkExistence, readFolderFile, readFolderJsonFile } from "./utils.js"; /** @@ -557,3 +564,35 @@ async function checkNodeJsToDevelopmentPack(development: AncaDevelopment) { development.state.issues.push("nodejsTsupConfigJsSetToDefault"); } } + +/** + * + * @param actions + * @param developments + */ +export async function doActionsOnDevelopments( + actions: AncaAction[], + developments: AncaDevelopment[], +) { + console.log( + `\nPerforming ${actions.length} action(s) on ${developments.length} development(s)...\n`, + ); + for (const actionName of actions) { + const action = getAction(actionName); + + if (action != null) { + console.log(`Performing action '${actionName}'...`); + for (const development of developments) { + await getDevelopmentStatus(development); + if (development.state == null) { + continue; + } + console.log(`...on ${getDevelopmentDisplayName(development)}...`); + action.action(development); + } + } else { + console.log(`Action '${actionName}' doesn't exist.`); + console.log(`Try: ${ANCA_ACTIONS.join(", ")}`); + } + } +} diff --git a/src/index.ts b/src/index.ts index 0fdb552..b5dc8e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,8 @@ import { loadProjects, readConfigFile, } from "./config.js"; -import { Anca } from "./schema.js"; +import { doActionsOnDevelopments } from "./developments.js"; +import { Anca, AncaAction } from "./schema.js"; import { showDevelopmentActions, showMainMenu } from "./tui.js"; /** @@ -34,10 +35,24 @@ async function main() { } if (projects) { - if (projects.deployments?.length || projects.developments?.length !== 1) { - showMainMenu(); + if (options.action) { + if (projects.developments?.length) { + await doActionsOnDevelopments( + options.action as AncaAction[], + projects.developments, + ); + } else { + console.error("No developments available"); + } } else { - showDevelopmentActions(projects.developments[0]); + if ( + projects.deployments?.length || + projects.developments?.length !== 1 + ) { + await showMainMenu(); + } else { + await showDevelopmentActions(projects.developments[0]); + } } } else { console.error("No config file provided"); diff --git a/src/schema.ts b/src/schema.ts index 9215b85..1f22ba4 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -44,6 +44,35 @@ export type AncaAction = | "openapiJsonSetToDefault" | "readmeSetToDefault"; +export const ANCA_ACTIONS: AncaAction[] = [ + "ancaJsonFix", + "contributingSetToDefault", + "devcontainerDockerfileSetToDefault", + "devcontainerJsonSetToDefault", + "gitClone", + "githubActionsOtherFilesRemove", + "githubActionsReleaseSetToDefault", + "githubActionsTestSetToDefault", + "gitIgnoreSetToDefault", + "licenseSetToDefault", + "nodejsEsbuildSetToDefault", + "nodejsEslintSetToDefault", + "nodejsOpenapiSetToDefault", + "nodejsPackageJsonCheckUpdates", + "nodejsPackageJsonFix", + "nodejsPackageJsonFixFull", + "nodejsPrettierIgnoreSetToDefault", + "nodejsPrettierRcSetToDefault", + "nodejsSeaBuildJsSetToDefault", + "nodejsSeaConfigJsonSetToDefault", + "nodejsSrcSetToDefault", + "nodejsTestSetToDefault", + "nodejsTsconfigSetToDefault", + "nodejsTsupConfigJsSetToDefault", + "openapiJsonSetToDefault", + "readmeSetToDefault", +]; + export interface AncaMeta { description?: string; name?: string; diff --git a/src/tui.ts b/src/tui.ts index 7093afb..6fce320 100644 --- a/src/tui.ts +++ b/src/tui.ts @@ -1,61 +1,17 @@ import { promptMenu } from "clivo"; import pc from "picocolors"; -import { fixAncaConfig } from "./actions/anca.js"; -import { fixContributingMd } from "./actions/contributing.js"; -import { - fixDevcontainerDockerfile, - fixDevcontainerJson, -} from "./actions/devcontainers.js"; -import { fixGitIgnore } from "./actions/git.js"; -import { - fixGithubActionsOtherFiles, - fixGithubActionsRelease, - fixGithubActionsTest, -} from "./actions/github-actions.js"; -import { fixLicenseMd } from "./actions/license.js"; -import { - fixNodejsPackageJson, - getUpdatedPackagesCommitMessage, - installNodejsDependencies, - NodejsPackageJson, - NpmUpdate, - updateNodejsPackageJsonDependencies, - updateNodejsPackageJsonDevDependencies, - writeNodejsPackageJson, -} from "./actions/nodejs.js"; -import { fixNodejsEsbuildJs } from "./actions/nodejs-esbuild.js"; -import { fixNodejsEslintConfigJs } from "./actions/nodejs-eslint.js"; -import { generateNodejsOpenapiFiles } from "./actions/nodejs-openapi.js"; -import { - fixNodejsPrettierIgnore, - fixNodejsPrettierRc, -} from "./actions/nodejs-prettier.js"; -import { - fixNodejsSeaBuildJs, - fixNodejsSeaConfigJson, -} from "./actions/nodejs-sea.js"; -import { fixNodejsSrc, fixNodejsTest } from "./actions/nodejs-src.js"; -import { fixNodejsTsconfigJson } from "./actions/nodejs-tsconfig.js"; -import { fixNodejsTsupConfigJs } from "./actions/nodejs-tsup.js"; -import { fixOpenapiJson } from "./actions/openapi.js"; -import { fixReadmeMd } from "./actions/readme.js"; +import { getAction } from "./action.js"; import { CINNABAR_PROJECT_VERSION } from "./cinnabar.js"; import { getInstance } from "./config.js"; import { getDevelopmentDisplayName, getDevelopmentStatus, refreshDevelopmentState, - syncDevelopment, } from "./developments.js"; import { AncaAction, AncaDevelopment } from "./schema.js"; import { checkExistence } from "./utils.js"; -interface ClivoAction { - action: () => Promise; - label: string; -} - const APP_NAME_AND_VERSION = `ANCA v${CINNABAR_PROJECT_VERSION}`; /** @@ -83,234 +39,19 @@ export async function showDevelopmentActions( const state = development.state; - const mappings: Record = { - ancaJsonFix: { - action: async () => { - await fixAncaConfig(development); - await backHere(); - }, - label: "[anca.json] Fix", - }, - contributingSetToDefault: { - action: async () => { - await fixContributingMd(development); - await backHere(); - }, - label: "[CONTRIBUTING.md] Set to default", - }, - devcontainerDockerfileSetToDefault: { - action: async () => { - await fixDevcontainerDockerfile(development); - await backHere(); - }, - label: "[.devcontainer/Dockerfile] Set to default", - }, - devcontainerJsonSetToDefault: { - action: async () => { - await fixDevcontainerJson(development); - await backHere(); - }, - label: "[.devcontainer/devcontainer.json] Set to default", - }, - gitClone: { - action: async () => { - await syncDevelopment(development); - await backHere(); - }, - label: "[git] Clone", - }, - githubActionsOtherFilesRemove: { - action: async () => { - await fixGithubActionsOtherFiles(development); - await backHere(); - }, - label: "[.github/workflows] Remove other files", - }, - githubActionsReleaseSetToDefault: { - action: async () => { - await fixGithubActionsRelease(development); - await backHere(); - }, - label: "[.github/workflows/release.yml] Set to default", - }, - githubActionsTestSetToDefault: { - action: async () => { - await fixGithubActionsTest(development); - await backHere(); - }, - label: "[.github/workflows/test.yml] Set to default", - }, - gitIgnoreSetToDefault: { - action: async () => { - await fixGitIgnore(development); - await backHere(); - }, - label: "[.gitignore] Set to default", - }, - licenseSetToDefault: { - action: async () => { - await fixLicenseMd(development); - await backHere(); - }, - label: "[LICENSE] Set to default", - }, - nodejsEsbuildSetToDefault: { - action: async () => { - await fixNodejsEsbuildJs(development); - await backHere(); - }, - label: "[esbuild.js] Set to default", - }, - nodejsEslintSetToDefault: { - action: async () => { - await fixNodejsEslintConfigJs(development); - await backHere(); - }, - label: "[eslint.config.js] Set to default", - }, - nodejsOpenapiSetToDefault: { - action: async () => { - await generateNodejsOpenapiFiles(development); - await backHere(); - }, - label: "[openapi] Set to default", - }, - nodejsPackageJsonCheckUpdates: { - action: async () => { - const fileContents = development.state?.jsonFiles[ - "package.json" - ] as NodejsPackageJson; - if (fileContents != null) { - const rebuildFile: NodejsPackageJson = {}; - const npmUpdate: NpmUpdate = - await updateNodejsPackageJsonDependencies( - rebuildFile, - development, - false, - true, - ); - npmUpdate.push( - ...(await updateNodejsPackageJsonDevDependencies( - rebuildFile, - development, - false, - true, - )), - ); - console.log("\nAdd to commit message: \n"); - console.log(getUpdatedPackagesCommitMessage(npmUpdate)); - console.log(); - fileContents.dependencies = rebuildFile.dependencies; - fileContents.devDependencies = rebuildFile.devDependencies; - await writeNodejsPackageJson(development); - await installNodejsDependencies(development); - } - await backHere(); - }, - label: "[package.json] Check dependencies updates", - }, - nodejsPackageJsonFix: { - action: async () => { - await fixNodejsPackageJson(development, false); - await writeNodejsPackageJson(development); - await installNodejsDependencies(development); - await backHere(); - }, - label: "[package.json] Fix", - }, - nodejsPackageJsonFixFull: { - action: async () => { - await fixNodejsPackageJson(development, true); - await writeNodejsPackageJson(development); - await installNodejsDependencies(development); - await backHere(); - }, - label: "[package.json] Fix & add optional fields", - }, - nodejsPrettierIgnoreSetToDefault: { - action: async () => { - await fixNodejsPrettierIgnore(development); - await backHere(); - }, - label: "[.prettierignore] Set to default", - }, - nodejsPrettierRcSetToDefault: { - action: async () => { - await fixNodejsPrettierRc(development); - await backHere(); - }, - label: "[.prettierrc] Set to default", - }, - nodejsSeaBuildJsSetToDefault: { - action: async () => { - await fixNodejsSeaBuildJs(development); - await backHere(); - }, - label: "[sea.build.js] Set to default", - }, - nodejsSeaConfigJsonSetToDefault: { - action: async () => { - await fixNodejsSeaConfigJson(development); - await backHere(); - }, - label: "[sea.config.json] Set to default", - }, - nodejsSrcSetToDefault: { - action: async () => { - await fixNodejsSrc(development); - await backHere(); - }, - label: "[src/index.ts] Set to default", - }, - nodejsTestSetToDefault: { - action: async () => { - await fixNodejsTest(development); - await backHere(); - }, - label: "[test/index.test.ts] Set to default", - }, - nodejsTsconfigSetToDefault: { - action: async () => { - await fixNodejsTsconfigJson(development); - await backHere(); - }, - label: "[tsconfig.json] Set to default", - }, - nodejsTsupConfigJsSetToDefault: { - action: async () => { - await fixNodejsTsupConfigJs(development); - await backHere(); - }, - label: "[tsup.config.js] Set to default", - }, - openapiJsonSetToDefault: { - action: async () => { - await fixOpenapiJson(development); - await backHere(); - }, - label: "[openapi.json] Set to default", - }, - readmeSetToDefault: { - action: async () => { - await fixReadmeMd(development); - await backHere(); - }, - label: "[README.md] Set to default", - }, - }; - const map = (code: AncaAction, isIssue: boolean) => { - const mapping = mappings[code]; + const mapping = getAction(code); if (mapping) { menu.push({ - action: mapping.action, + action: async () => { + await mapping.action(development); + await backHere(); + }, label: isIssue ? pc.bgRed("[!]") + " " + mapping.label : mapping.label, }); } else { menu.push({ - action: async () => { - await backHere(); - }, + action: backHere, label: "THE ACTION IS NOT IMPLEMENTED: " + code, }); }