autoforce 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -3
- package/lib/helpers/context.d.ts +2 -1
- package/lib/helpers/context.js +33 -22
- package/lib/helpers/github-graphql.d.ts +1 -1
- package/lib/helpers/github-graphql.js +1 -1
- package/lib/helpers/github-project-graphql.js +2 -2
- package/lib/helpers/openai.js +1 -1
- package/lib/helpers/taskFunctions.js +18 -6
- package/lib/helpers/tasks.js +6 -6
- package/lib/helpers/template.d.ts +1 -1
- package/lib/helpers/template.js +3 -0
- package/lib/helpers/util.d.ts +2 -1
- package/lib/helpers/util.js +40 -17
- package/package.json +1 -1
- package/templates/models.json +2 -3
package/CHANGELOG.md
CHANGED
@@ -1,4 +1,21 @@
|
|
1
|
+
# Versiones
|
1
2
|
|
2
|
-
Version 0.1.
|
3
|
-
|
4
|
-
|
3
|
+
## Version 0.1.10
|
4
|
+
- Fecha: 28/11/2024
|
5
|
+
- Cambios:
|
6
|
+
* [publish deberia pedir la version, y asignarla en el autoforce version](https://github.com/sebastianclaros/autoforce/issues/12)
|
7
|
+
* [Models en config que lea un json descriptivo](https://github.com/sebastianclaros/autoforce/issues/9)
|
8
|
+
* [comando list](https://github.com/sebastianclaros/autoforce/issues/1)
|
9
|
+
* [Guard para verificar existencia de Variables de Entorno por ejemplo NPM_TOKEN con un $NPM_TOKEN ?
|
10
|
+
(https://github.com/sebastianclaros/autoforce/issues/10)
|
11
|
+
]
|
12
|
+
* [New issue con Body optativo](https://github.com/sebastianclaros/autoforce/issues/3)
|
13
|
+
* [Parametros adicionales tipo npx autoforce start XXX](https://github.com/sebastianclaros/autoforce/issues/5)
|
14
|
+
* [Modelos en los Templates](https://github.com/sebastianclaros/autoforce/issues/8)
|
15
|
+
|
16
|
+
|
17
|
+
## Version 0.1.9
|
18
|
+
|
19
|
+
- Cambios:
|
20
|
+
* Comando de new issue para crear un issue nuevo en el backlog
|
21
|
+
* Comando de list para ver issues en backlog o ver los detalles de uno
|
package/lib/helpers/context.d.ts
CHANGED
@@ -49,10 +49,11 @@ declare class Context implements IObjectRecord {
|
|
49
49
|
repositoryRepo: string | undefined;
|
50
50
|
projectId: string | undefined;
|
51
51
|
backlogColumn: string;
|
52
|
+
constructor();
|
52
53
|
loadProjectApi(): void;
|
53
54
|
loadGitApi(): void;
|
54
55
|
loadPackage(): void;
|
55
|
-
loadConfig():
|
56
|
+
loadConfig(): Promise<boolean>;
|
56
57
|
init(): void;
|
57
58
|
get targetOrg(): string;
|
58
59
|
get existBranchScratch(): boolean;
|
package/lib/helpers/context.js
CHANGED
@@ -21,14 +21,14 @@ export var GitServices;
|
|
21
21
|
GitServices["GitHub"] = "github";
|
22
22
|
GitServices["GitLab"] = "gitlab";
|
23
23
|
GitServices["None"] = "none";
|
24
|
-
})(GitServices
|
24
|
+
})(GitServices || (GitServices = {}));
|
25
25
|
export var ProjectServices;
|
26
26
|
(function (ProjectServices) {
|
27
27
|
ProjectServices["GitHub"] = "github";
|
28
28
|
ProjectServices["GitLab"] = "gitlab";
|
29
29
|
ProjectServices["Jira"] = "Jira";
|
30
30
|
ProjectServices["None"] = "none";
|
31
|
-
})(ProjectServices
|
31
|
+
})(ProjectServices || (ProjectServices = {}));
|
32
32
|
const filterProcesses = (fullPath) => fullPath.endsWith(".md"); // && !fullPath.endsWith("intro.md")
|
33
33
|
const ISSUES_TYPES = [{ value: 'feature', title: 'feature' }, { value: 'bug', title: 'bug' }, { value: 'documentation', title: 'documentation' }, { value: 'automation', title: 'automation' }];
|
34
34
|
class Context {
|
@@ -47,6 +47,8 @@ class Context {
|
|
47
47
|
// Ultima salida del shell
|
48
48
|
this.salida = '';
|
49
49
|
this.backlogColumn = 'Todo';
|
50
|
+
this.loadConfig();
|
51
|
+
this.loadPackage();
|
50
52
|
}
|
51
53
|
loadProjectApi() {
|
52
54
|
if (!this.isProjectApi) {
|
@@ -119,28 +121,38 @@ class Context {
|
|
119
121
|
this.repositoryRepo = data.repositoryRepo;
|
120
122
|
}
|
121
123
|
loadConfig() {
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
124
|
+
return __awaiter(this, void 0, void 0, function* () {
|
125
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
126
|
+
logWarning('Bienvenido! La herramienta Autoforce necesita un primer paso de configuracion antes de usarla.');
|
127
|
+
logWarning('- Podes usar el asistente ejecutando npx autoforce config');
|
128
|
+
logWarning('- Podes hacerlo manualmente leyendo la documentacion y creando .autoforce.json manualmente en el root del proyecto (https://sebastianclaros.github.io/autoforce/docs/configuracion)');
|
129
|
+
const answer = yield prompts([
|
130
|
+
{
|
131
|
+
type: "confirm",
|
132
|
+
name: "asistente",
|
133
|
+
message: "Queres ejecutar el asistente ahora?"
|
134
|
+
}
|
135
|
+
]);
|
136
|
+
if (answer.asistente) {
|
137
|
+
yield createConfigurationFile();
|
138
|
+
return true;
|
139
|
+
}
|
140
|
+
return false;
|
134
141
|
}
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
142
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf8");
|
143
|
+
try {
|
144
|
+
const config = JSON.parse(content);
|
145
|
+
for (const key in config) {
|
146
|
+
this.set(key, config[key]);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
catch (_a) {
|
150
|
+
throw new Error(`Verifique que el ${CONFIG_FILE} sea json valido`);
|
151
|
+
}
|
152
|
+
return true;
|
153
|
+
});
|
139
154
|
}
|
140
155
|
init() {
|
141
|
-
// Busca variables de entorno
|
142
|
-
this.loadConfig();
|
143
|
-
this.loadPackage();
|
144
156
|
this.loadProjectApi();
|
145
157
|
this.loadGitApi();
|
146
158
|
//
|
@@ -518,7 +530,6 @@ class Context {
|
|
518
530
|
}
|
519
531
|
}
|
520
532
|
const context = new Context();
|
521
|
-
context.loadConfig();
|
522
533
|
let initialized = false;
|
523
534
|
export function initializeContext() {
|
524
535
|
try {
|
@@ -95,8 +95,8 @@ export class GitHubApi {
|
|
95
95
|
});
|
96
96
|
}
|
97
97
|
assignBranchToIssue(issueNumber, branchName, commitSha) {
|
98
|
-
var _a;
|
99
98
|
return __awaiter(this, void 0, void 0, function* () {
|
99
|
+
var _a;
|
100
100
|
const issue = yield this.getIssue(issueNumber);
|
101
101
|
const commit = yield this.getCommit(commitSha);
|
102
102
|
const mutation = `
|
@@ -43,8 +43,8 @@ export class GitHubProjectApi extends GitHubApi {
|
|
43
43
|
});
|
44
44
|
}
|
45
45
|
createIssue(title, state, label, body, milestone) {
|
46
|
-
var _a;
|
47
46
|
return __awaiter(this, void 0, void 0, function* () {
|
47
|
+
var _a;
|
48
48
|
const user = yield this.getUser();
|
49
49
|
const repository = yield this.getRepository(label);
|
50
50
|
const repositoryId = repository.id;
|
@@ -115,8 +115,8 @@ export class GitHubProjectApi extends GitHubApi {
|
|
115
115
|
});
|
116
116
|
}
|
117
117
|
getIssueState(issueNumber) {
|
118
|
-
var _a, _b, _c;
|
119
118
|
return __awaiter(this, void 0, void 0, function* () {
|
119
|
+
var _a, _b, _c;
|
120
120
|
const issue = yield this.getIssue(issueNumber);
|
121
121
|
return (_c = (_b = (_a = issue.projectItems) === null || _a === void 0 ? void 0 : _a.nodes[0]) === null || _b === void 0 ? void 0 : _b.fieldValueByName) === null || _c === void 0 ? void 0 : _c.name;
|
122
122
|
});
|
package/lib/helpers/openai.js
CHANGED
@@ -12,8 +12,8 @@ const client = new OpenAI({
|
|
12
12
|
apiKey: process.env['OPENAI_API_KEY'], // This is the default and can be omitted
|
13
13
|
});
|
14
14
|
export function getCommitMessage() {
|
15
|
-
var _a;
|
16
15
|
return __awaiter(this, void 0, void 0, function* () {
|
16
|
+
var _a;
|
17
17
|
if (process.env['OPENAI_API_KEY']) {
|
18
18
|
const params = {
|
19
19
|
messages: [{ role: 'user', content: 'Say this is a test' }],
|
@@ -14,7 +14,20 @@ import metadata from './metadata.js';
|
|
14
14
|
import prompts from "prompts";
|
15
15
|
import templateGenerator from "./template.js";
|
16
16
|
import { getColored } from "./color.js";
|
17
|
-
import { storeConfig } from "./util.js";
|
17
|
+
import { storeConfig, TEMPLATE_MODEL_FOLDER } from "./util.js";
|
18
|
+
function generateTemplate(templateFolder, templateExtension, template, context) {
|
19
|
+
if (!template || !templateFolder || !templateExtension) {
|
20
|
+
return;
|
21
|
+
}
|
22
|
+
const templateEngine = templateGenerator(templateFolder, templateExtension);
|
23
|
+
const formulas = {
|
24
|
+
today: Date.now(),
|
25
|
+
};
|
26
|
+
const view = Object.assign(Object.assign({}, formulas), context);
|
27
|
+
templateEngine.read(template);
|
28
|
+
templateEngine.render(view);
|
29
|
+
return templateEngine.rendered;
|
30
|
+
}
|
18
31
|
function createTemplate(templateFolder, templateExtension, template, filename, folder, context) {
|
19
32
|
if (!template || !filename || !templateFolder || !templateExtension) {
|
20
33
|
return;
|
@@ -457,20 +470,19 @@ export const taskFunctions = {
|
|
457
470
|
});
|
458
471
|
},
|
459
472
|
listIssues() {
|
460
|
-
return __awaiter(this,
|
473
|
+
return __awaiter(this, arguments, void 0, function* (filter = '{state: OPEN}', template = 'openIssues') {
|
461
474
|
if (!context.projectApi) {
|
462
475
|
return false;
|
463
476
|
}
|
464
477
|
const result = yield context.projectApi.getIssues();
|
465
|
-
|
466
|
-
|
467
|
-
}
|
478
|
+
const rendered = generateTemplate(TEMPLATE_MODEL_FOLDER, 'md', template, Object.assign({ issues: result }, context));
|
479
|
+
console.log(rendered);
|
468
480
|
return true;
|
469
481
|
});
|
470
482
|
},
|
471
483
|
checkIssueType(issueNumber) {
|
472
|
-
var _a;
|
473
484
|
return __awaiter(this, void 0, void 0, function* () {
|
485
|
+
var _a;
|
474
486
|
if (!context.projectApi) {
|
475
487
|
return false;
|
476
488
|
}
|
package/lib/helpers/tasks.js
CHANGED
@@ -104,8 +104,8 @@ export function validateTask(task) {
|
|
104
104
|
}
|
105
105
|
return true;
|
106
106
|
}
|
107
|
-
export function runTask(
|
108
|
-
return __awaiter(this,
|
107
|
+
export function runTask(task_1, taskContext_1) {
|
108
|
+
return __awaiter(this, arguments, void 0, function* (task, taskContext, tabs = '') {
|
109
109
|
initializeContext();
|
110
110
|
// Valida que este ya esten las variables de enotorno y configuracion
|
111
111
|
if (task.guards) {
|
@@ -134,8 +134,8 @@ export function runTask(task, taskContext, tabs = '') {
|
|
134
134
|
return true;
|
135
135
|
});
|
136
136
|
}
|
137
|
-
export function previewTask(
|
138
|
-
return __awaiter(this,
|
137
|
+
export function previewTask(task_1) {
|
138
|
+
return __awaiter(this, arguments, void 0, function* (task, tabs = '') {
|
139
139
|
initializeContext();
|
140
140
|
logStep(`${task.name}: ${task.description}`, tabs);
|
141
141
|
for (const step of task.steps) {
|
@@ -206,8 +206,8 @@ function askForContinueOrRetry() {
|
|
206
206
|
function getStepError(step, stepName) {
|
207
207
|
return step.errorMessage ? context.merge(step.errorMessage) : stepName ? `Fallo el step ${stepName}` : '';
|
208
208
|
}
|
209
|
-
function executeStep(
|
210
|
-
return __awaiter(this,
|
209
|
+
function executeStep(step_1, tabs_1) {
|
210
|
+
return __awaiter(this, arguments, void 0, function* (step, tabs, verbose = false) {
|
211
211
|
const stepName = step.name ? context.merge(step.name) : undefined;
|
212
212
|
if (verbose && stepName) {
|
213
213
|
logStep(`[INICIO] ${stepName}`, tabs);
|
@@ -1,4 +1,3 @@
|
|
1
|
-
/// <reference types="handlebars" />
|
2
1
|
declare class TemplateEngine {
|
3
2
|
_template: HandlebarsTemplateDelegate | undefined;
|
4
3
|
_rendered: string | undefined;
|
@@ -8,6 +7,7 @@ declare class TemplateEngine {
|
|
8
7
|
getTemplates(): string[];
|
9
8
|
read(templateName: string): void;
|
10
9
|
render(context: object, options?: RuntimeOptions): void;
|
10
|
+
get rendered(): string | undefined;
|
11
11
|
save(filename: string, folder: string, options?: SaveTemplateOptions): void;
|
12
12
|
}
|
13
13
|
declare const _default: (source: string, extension: string) => TemplateEngine;
|
package/lib/helpers/template.js
CHANGED
@@ -51,6 +51,9 @@ class TemplateEngine {
|
|
51
51
|
}
|
52
52
|
this._rendered = this._template(context, options);
|
53
53
|
}
|
54
|
+
get rendered() {
|
55
|
+
return this._rendered;
|
56
|
+
}
|
54
57
|
save(filename, folder, options = { create: true, overwrite: true }) {
|
55
58
|
let accion = "creo";
|
56
59
|
if (folder && !fs.existsSync(folder)) {
|
package/lib/helpers/util.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import prompts from "prompts";
|
1
|
+
import prompts, { Choice } from "prompts";
|
2
2
|
import { AnyValue } from "../types/auto.js";
|
3
3
|
export declare const CONFIG_FILE: string;
|
4
4
|
export declare const TEMPLATES_FOLDER: string;
|
@@ -20,6 +20,7 @@ export declare function titlesToChoices(list: string[], titleToValue?: (title: s
|
|
20
20
|
value: string;
|
21
21
|
}[];
|
22
22
|
export declare function getDataFromPackage(): Record<string, string>;
|
23
|
+
export declare function findChoicesPosition(choices: Choice[], value: string): number;
|
23
24
|
export declare function createConfigurationFile(): Promise<boolean>;
|
24
25
|
export declare function getConfig(variable: string, defaultValue: AnyValue): any;
|
25
26
|
export declare function storeConfig(variable: string, value: AnyValue): void;
|
package/lib/helpers/util.js
CHANGED
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
10
10
|
import fs from "fs";
|
11
11
|
import { fileURLToPath } from 'url';
|
12
12
|
import prompts from "prompts";
|
13
|
-
import { ProjectServices, GitServices } from "./context.js";
|
13
|
+
import context, { ProjectServices, GitServices } from "./context.js";
|
14
14
|
import { logInfo, logWarning } from "./color.js";
|
15
15
|
const COMMAND_FOLDER = searchInFolderHierarchy('commands', fileURLToPath(import.meta.url));
|
16
16
|
export const CONFIG_FILE = process.cwd() + '/.autoforce.json';
|
@@ -69,23 +69,26 @@ export function getDataFromPackage() {
|
|
69
69
|
}
|
70
70
|
return data;
|
71
71
|
}
|
72
|
+
export function findChoicesPosition(choices, value) {
|
73
|
+
const index = choices.findIndex(choice => choice.value === value);
|
74
|
+
return index === -1 ? 0 : index;
|
75
|
+
}
|
72
76
|
export function createConfigurationFile() {
|
73
77
|
return __awaiter(this, void 0, void 0, function* () {
|
74
78
|
// Todo: Chequear el repoOwner y repo
|
75
|
-
const
|
76
|
-
const
|
77
|
-
if (!data.repositoryOwner || !data.repositoryRepo) {
|
78
|
-
throw new Error('No se encontro repository en el package.json ! Por favor agreguelo y vuelva a intentar');
|
79
|
-
}
|
80
|
-
const initialServices = data.repositoryUrl.includes("github.com") ? 0 : 1;
|
79
|
+
const config = { backlogColumn: context.backlogColumn, model: context.model, modelTemplates: context.modelTemplates, gitServices: context.gitServices, projectServices: context.projectServices, projectId: context.projectId };
|
80
|
+
const gitChoices = [{ title: 'Github', value: GitServices.GitHub }, { title: 'Gitlab', value: GitServices.GitLab }];
|
81
81
|
// Preguntar por GitHub o GitLab
|
82
82
|
const gitServices = yield prompts([{
|
83
83
|
type: "select",
|
84
84
|
name: "git",
|
85
|
-
initial: initialServices,
|
86
85
|
message: "Elija un servicio de Git",
|
87
|
-
|
86
|
+
initial: findChoicesPosition(gitChoices, config.gitServices),
|
87
|
+
choices: gitChoices
|
88
88
|
}]);
|
89
|
+
if (gitServices.git === undefined)
|
90
|
+
return false;
|
91
|
+
config.gitServices = gitServices.git;
|
89
92
|
// Chequear las variables de entorno
|
90
93
|
if (gitServices.git === GitServices.GitHub && !process.env.GITHUB_TOKEN) {
|
91
94
|
logWarning('A fin de que la herramienta funcione debe configurar una variable de entorno GITHUB_TOKEN');
|
@@ -93,13 +96,19 @@ export function createConfigurationFile() {
|
|
93
96
|
if (gitServices.git === GitServices.GitLab && !process.env.GITLAB_TOKEN) {
|
94
97
|
logWarning('A fin de que la herramienta funcione debe configurar una variable de entorno GITLAB_TOKEN');
|
95
98
|
}
|
99
|
+
// Selecciona el modelo de automatizacion
|
96
100
|
const models = readJsonSync(`${COMMAND_FOLDER}/models.json`);
|
101
|
+
models.push({ title: 'Personalizado', value: 'custom', description: 'En este caso los comandos son configurados fuera de la herramienta y los lee de la carpeta commands en el root del repo' });
|
97
102
|
const automationModel = yield prompts([{
|
98
103
|
type: "select",
|
99
104
|
name: "model",
|
100
105
|
message: "Elija un modelo de automatizacion",
|
101
|
-
|
106
|
+
initial: findChoicesPosition(models, config.model),
|
107
|
+
choices: models
|
102
108
|
}]);
|
109
|
+
if (automationModel.model === undefined)
|
110
|
+
return false;
|
111
|
+
config.model = automationModel.model;
|
103
112
|
// Si es custom pregunta si quiere tomar de base alguno existente
|
104
113
|
if (automationModel.model === 'custom') {
|
105
114
|
const baseModel = yield prompts([{
|
@@ -113,39 +122,53 @@ export function createConfigurationFile() {
|
|
113
122
|
}
|
114
123
|
}
|
115
124
|
// Gestion del Proyecto
|
125
|
+
const projectChoices = [{ title: 'Github Projects', value: ProjectServices.GitHub }, { title: 'GitLab Projects', value: ProjectServices.GitLab }, { title: 'Jira', value: ProjectServices.Jira }, { title: 'None', value: ProjectServices.None }];
|
116
126
|
const projectServices = yield prompts([{
|
117
127
|
type: "select",
|
118
128
|
name: "project",
|
119
|
-
initial: initialServices,
|
120
129
|
message: "Gestion de proyecto",
|
121
|
-
|
130
|
+
initial: findChoicesPosition(projectChoices, config.projectServices),
|
131
|
+
choices: projectChoices
|
122
132
|
}]);
|
133
|
+
if (projectServices.project === undefined)
|
134
|
+
return false;
|
135
|
+
config.projectServices = projectServices.project;
|
136
|
+
;
|
123
137
|
if (projectServices.project === ProjectServices.GitHub || projectServices.project === ProjectServices.GitLab) {
|
124
138
|
// Gestion del Proyecto
|
125
139
|
const backlogColumn = yield prompts([{
|
126
140
|
type: "text",
|
127
141
|
name: "backlogColumn",
|
128
|
-
initial:
|
142
|
+
initial: config.backlogColumn,
|
129
143
|
message: "Nombre de la columna donde se crean nuevos issues"
|
130
144
|
}]);
|
131
|
-
|
132
|
-
|
145
|
+
if (backlogColumn.backlogColumn === undefined)
|
146
|
+
return false;
|
147
|
+
config.backlogColumn = backlogColumn.backlogColumn;
|
148
|
+
logInfo(`Por omision ser utilizan proyectos dentro de ${context.repositoryOwner} y ${context.repositoryRepo} `);
|
133
149
|
}
|
150
|
+
// Id de Projecto
|
134
151
|
const projectId = yield prompts([{
|
135
152
|
type: "text",
|
136
153
|
name: "projectId",
|
154
|
+
initial: config.projectId,
|
137
155
|
message: "Id del proyecto"
|
138
156
|
}]);
|
157
|
+
if (projectId.projectId === undefined)
|
158
|
+
return false;
|
159
|
+
config.projectId = projectId.projectId;
|
139
160
|
// Modelo de Dcumentacion
|
140
161
|
const modelsTemplates = readJsonSync(`${TEMPLATES_FOLDER}/models.json`);
|
141
162
|
const modelTemplates = yield prompts([{
|
142
163
|
type: "select",
|
143
164
|
name: "model",
|
144
165
|
message: "Elija un modelo de documentacion",
|
166
|
+
initial: findChoicesPosition(modelsTemplates, config.modelTemplates),
|
145
167
|
choices: modelsTemplates
|
146
168
|
}]);
|
147
|
-
|
148
|
-
|
169
|
+
if (modelTemplates.model === undefined)
|
170
|
+
return false;
|
171
|
+
config.modelTemplates = modelTemplates.model;
|
149
172
|
try {
|
150
173
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
151
174
|
}
|
package/package.json
CHANGED
package/templates/models.json
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
{
|
3
3
|
"title": "Procesos de Negocio en Salesforce",
|
4
4
|
"value": "modelA",
|
5
|
-
"description": "Documenta Clases, Objetos y LWC a traves de procesos de negocios. Se basa en docusaurus"
|
5
|
+
"description": "Documenta Clases, Objetos y LWC a traves de procesos de negocios. Se basa en docusaurus"
|
6
6
|
},
|
7
7
|
{
|
8
8
|
"title": "Proyecto simple en Github Docs",
|
9
9
|
"value": "modelB",
|
10
10
|
"description": "Github pages con changelog, readme y carpeta docs de Markdowns"
|
11
11
|
}
|
12
|
-
]
|
13
|
-
|
12
|
+
]
|