@waron97/prbot 3.0.4 → 3.1.0
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/package.json
CHANGED
|
@@ -114,7 +114,7 @@ async function initPhase() {
|
|
|
114
114
|
// Resolve result objects — API may return IDs or full objects
|
|
115
115
|
let results = phase.allowed_phase_result_ids || [];
|
|
116
116
|
if (results.length > 0 && typeof results[0] === 'number') {
|
|
117
|
-
results = await getPhaseResults(token, ripUrl,
|
|
117
|
+
results = await getPhaseResults(token, ripUrl, results);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
const code = generateCode(results);
|
package/src/agrippa/lib/api.js
CHANGED
|
@@ -48,11 +48,12 @@ function updateMfa(token, ripUrl, mfaId, code) {
|
|
|
48
48
|
return makeRequest('POST', '/symple.workflow/update_mfa', token, ripUrl, { id: mfaId, code });
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
async function getPhaseResults(token, ripUrl,
|
|
51
|
+
async function getPhaseResults(token, ripUrl, ids) {
|
|
52
|
+
if (!ids || ids.length === 0) return [];
|
|
52
53
|
try {
|
|
53
54
|
return await makeRequest(
|
|
54
55
|
'GET',
|
|
55
|
-
`/symple.triplet.phase.result/*?_filter_=[('
|
|
56
|
+
`/symple.triplet.phase.result/*?_filter_=[('id', 'in', [${ids.join(',')}])]`,
|
|
56
57
|
token,
|
|
57
58
|
ripUrl,
|
|
58
59
|
);
|
package/src/commands/export.js
CHANGED
|
@@ -2,9 +2,10 @@ import { exportPb } from './exportPb.js';
|
|
|
2
2
|
import { exportImperex } from './exportImperex.js';
|
|
3
3
|
import { exportEmailTemplates } from './exportEmailTemplates.js';
|
|
4
4
|
import { exportWorkflow } from './exportWorkflow.js';
|
|
5
|
+
import { exportLrp } from './exportLrp.js';
|
|
5
6
|
|
|
6
7
|
function exportRip() {
|
|
7
8
|
console.log('Not implemented yet.');
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export { exportPb, exportRip, exportImperex, exportEmailTemplates, exportWorkflow };
|
|
11
|
+
export { exportPb, exportRip, exportImperex, exportEmailTemplates, exportWorkflow, exportLrp };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fetch from 'node-fetch';
|
|
4
|
+
import search from '@inquirer/search';
|
|
5
|
+
import { getToken } from '../lib/auth.js';
|
|
6
|
+
import { execGit } from '../lib/git.js';
|
|
7
|
+
import { resolveAddonsPath } from '../lib/addons.js';
|
|
8
|
+
import { fuzzyMatch } from '../lib/fuzzy.js';
|
|
9
|
+
import { CONFIG_DIR } from '../config.js';
|
|
10
|
+
|
|
11
|
+
const CACHE_FILE = path.join(CONFIG_DIR, 'lrp_processes_cache.json');
|
|
12
|
+
|
|
13
|
+
function getSymphonyBase() {
|
|
14
|
+
const url = process.env.IMPORTEXPORT_URL;
|
|
15
|
+
if (!url) throw new Error('IMPORTEXPORT_URL not configured');
|
|
16
|
+
const parsed = new URL(url);
|
|
17
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function fetchProcessList(token, signal) {
|
|
21
|
+
const base = getSymphonyBase();
|
|
22
|
+
const params = encodeURIComponent(JSON.stringify({ page: 1, size: 1000, sorters: [], filters: [] }));
|
|
23
|
+
const otherfilters = encodeURIComponent(
|
|
24
|
+
JSON.stringify([
|
|
25
|
+
{ field: 'id', type: '=', value: null },
|
|
26
|
+
{ field: 'name', type: 'like', value: null },
|
|
27
|
+
{ field: 'tenantId', type: '=', value: null },
|
|
28
|
+
{ field: 'latestVersion', type: '=', value: true },
|
|
29
|
+
])
|
|
30
|
+
);
|
|
31
|
+
const othersort = encodeURIComponent(JSON.stringify({ field: 'lastModifiedDate', dir: 'desc' }));
|
|
32
|
+
const url = `${base}/symphony/restInfo/ajax/tabulator?params=${params}&connector=SymphBpmnFileTabCon&otherfilters=${otherfilters}&card=true&othersort=${othersort}`;
|
|
33
|
+
|
|
34
|
+
const response = await fetch(url, {
|
|
35
|
+
headers: {
|
|
36
|
+
accept: 'application/json',
|
|
37
|
+
Authorization: `Bearer ${token}`,
|
|
38
|
+
},
|
|
39
|
+
signal,
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) throw new Error(await response.text());
|
|
42
|
+
const json = await response.json();
|
|
43
|
+
|
|
44
|
+
const items = [];
|
|
45
|
+
for (const row of json.data || []) {
|
|
46
|
+
for (let i = 1; i <= 4; i++) {
|
|
47
|
+
const cell = row[`cellContent${i}`];
|
|
48
|
+
if (cell && cell.id && cell.name) {
|
|
49
|
+
items.push({ id: String(cell.id), name: cell.name });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return items;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function loadCache() {
|
|
57
|
+
try {
|
|
58
|
+
const data = await fs.readFile(CACHE_FILE, 'utf-8');
|
|
59
|
+
return JSON.parse(data);
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function saveCache(items) {
|
|
66
|
+
try {
|
|
67
|
+
await fs.mkdir(path.dirname(CACHE_FILE), { recursive: true });
|
|
68
|
+
await fs.writeFile(CACHE_FILE, JSON.stringify(items));
|
|
69
|
+
} catch {
|
|
70
|
+
// non-fatal
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function fetchProcessDetail(id, token) {
|
|
75
|
+
const base = getSymphonyBase();
|
|
76
|
+
const url = `${base}/symphony/restInfo/ajax/tabulator/id/${id}?connector=SymphBpmnFileTabCon&modelroot=/management/development/edit`;
|
|
77
|
+
const response = await fetch(url, {
|
|
78
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) throw new Error(await response.text());
|
|
81
|
+
return response.text();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function extractBpmnData(jsText) {
|
|
85
|
+
const valueMatch = jsText.match(/doc\.value\s*=\s*'([^']+)'/);
|
|
86
|
+
if (!valueMatch) throw new Error('Could not find doc.value in response');
|
|
87
|
+
|
|
88
|
+
const filenameMatch = jsText.match(/filename\.value\s*=\s*'([^']+)'/);
|
|
89
|
+
if (!filenameMatch) throw new Error('Could not find filename.value in response');
|
|
90
|
+
|
|
91
|
+
const xml = Buffer.from(valueMatch[1], 'base64').toString('utf-8');
|
|
92
|
+
const filename = filenameMatch[1];
|
|
93
|
+
return { xml, filename };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function findExistingFile(baseDir, filename) {
|
|
97
|
+
async function walk(dir) {
|
|
98
|
+
let entries;
|
|
99
|
+
try {
|
|
100
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
const full = path.join(dir, entry.name);
|
|
106
|
+
if (entry.isDirectory()) {
|
|
107
|
+
const found = await walk(full);
|
|
108
|
+
if (found) return found;
|
|
109
|
+
} else if (entry.name === filename) {
|
|
110
|
+
return full;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
return walk(baseDir);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function exportLrp(opts) {
|
|
119
|
+
const token = await getToken();
|
|
120
|
+
|
|
121
|
+
// choices is a mutable ref so source() sees background updates live
|
|
122
|
+
let choices = [];
|
|
123
|
+
|
|
124
|
+
const cached = await loadCache();
|
|
125
|
+
|
|
126
|
+
const bgController = new AbortController();
|
|
127
|
+
|
|
128
|
+
if (cached) {
|
|
129
|
+
choices = cached.map((p) => ({ name: p.name, value: p.id }));
|
|
130
|
+
console.log(`Loaded ${choices.length} processes from cache. Fetching fresh list in background (~1 min) — results update as you type.`);
|
|
131
|
+
fetchProcessList(token, bgController.signal)
|
|
132
|
+
.then(async (fresh) => {
|
|
133
|
+
await saveCache(fresh);
|
|
134
|
+
const updated = fresh.map((p) => ({ name: p.name, value: p.id }));
|
|
135
|
+
choices.length = 0;
|
|
136
|
+
choices.push(...updated);
|
|
137
|
+
})
|
|
138
|
+
.catch(() => {});
|
|
139
|
+
} else {
|
|
140
|
+
console.log('No cache found. Fetching process list (~1 min)...');
|
|
141
|
+
const items = await fetchProcessList(token);
|
|
142
|
+
await saveCache(items);
|
|
143
|
+
choices = items.map((p) => ({ name: p.name, value: p.id }));
|
|
144
|
+
console.log(`Loaded ${choices.length} processes.`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const selectedId = await search({
|
|
148
|
+
message: 'Select LRP process to export:',
|
|
149
|
+
source: async (input) => {
|
|
150
|
+
if (!input) return choices;
|
|
151
|
+
return choices.filter((c) => fuzzyMatch(c.name, input));
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
console.log('Fetching process detail...');
|
|
156
|
+
const jsText = await fetchProcessDetail(selectedId, token);
|
|
157
|
+
const { xml, filename } = extractBpmnData(jsText);
|
|
158
|
+
const bpmnFilename = `${filename.replace(/^B2WA_/, '')}.bpmn20.xml`;
|
|
159
|
+
|
|
160
|
+
const ADDONS_PATH = resolveAddonsPath(process.env.ADDONS_PATH);
|
|
161
|
+
const processesDir = path.join(ADDONS_PATH, '.cloudbuild', 'symphony', 'B2WA', 'processes');
|
|
162
|
+
|
|
163
|
+
const existing = await findExistingFile(processesDir, bpmnFilename);
|
|
164
|
+
let savePath;
|
|
165
|
+
if (existing) {
|
|
166
|
+
savePath = existing;
|
|
167
|
+
await fs.writeFile(savePath, xml, 'utf-8');
|
|
168
|
+
console.log(`Updated: ${savePath}`);
|
|
169
|
+
} else {
|
|
170
|
+
savePath = path.join(processesDir, 'all', bpmnFilename);
|
|
171
|
+
await fs.mkdir(path.dirname(savePath), { recursive: true });
|
|
172
|
+
await fs.writeFile(savePath, xml, 'utf-8');
|
|
173
|
+
console.log(`Created: ${savePath}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (opts.commit !== false) {
|
|
177
|
+
await execGit(['add', savePath], ADDONS_PATH);
|
|
178
|
+
await execGit(['commit', '-m', '[IMP][.cloudbuild] Update long running process'], ADDONS_PATH);
|
|
179
|
+
console.log('Committed.');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
bgController.abort();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { exportLrp };
|
package/src/commands/ver.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { resolveAddonsPath } from '../lib/addons.js';
|
|
5
5
|
|
|
6
|
-
async function verbot(module_name, level) {
|
|
6
|
+
async function verbot(module_name, level, opts = {}) {
|
|
7
7
|
if (!['major', 'minor', 'patch'].includes(level)) {
|
|
8
8
|
throw new Error('Level must be one of major, minor, patch');
|
|
9
9
|
}
|
|
@@ -52,6 +52,8 @@ async function verbot(module_name, level) {
|
|
|
52
52
|
await fs.writeFile(manifestPath, newContent);
|
|
53
53
|
console.log(`Updated version: ${currentVersion} -> ${newVersion}`);
|
|
54
54
|
|
|
55
|
+
if (opts.commit === false) return;
|
|
56
|
+
|
|
55
57
|
await new Promise((resolve, reject) => {
|
|
56
58
|
execFile('git', ['add', manifestPath], { cwd: ADDONS_PATH }, (error) => {
|
|
57
59
|
if (error) reject(error);
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { configDotenv } from 'dotenv';
|
|
|
5
5
|
import { autopr } from './commands/autopr.js';
|
|
6
6
|
import { changelog } from './commands/changelog.js';
|
|
7
7
|
import { commit } from './commands/commit.js';
|
|
8
|
-
import { exportPb, exportRip, exportImperex, exportEmailTemplates, exportWorkflow } from './commands/export.js';
|
|
8
|
+
import { exportPb, exportRip, exportImperex, exportEmailTemplates, exportWorkflow, exportLrp } from './commands/export.js';
|
|
9
9
|
import { init } from './commands/init.js';
|
|
10
10
|
import { main as prMain } from './commands/pr.js';
|
|
11
11
|
import { verbot } from './commands/ver.js';
|
|
@@ -119,6 +119,15 @@ exportCmd
|
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
exportCmd
|
|
123
|
+
.command('lrp')
|
|
124
|
+
.option('--no-commit')
|
|
125
|
+
.action((opts) => {
|
|
126
|
+
exportLrp(opts).catch((err) => {
|
|
127
|
+
throw err;
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
122
131
|
exportCmd
|
|
123
132
|
.command('email-templates')
|
|
124
133
|
.option('--no-commit')
|