@waron97/prbot 3.2.1 → 3.4.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/README.md +26 -18
- package/agrippa-pb.md +141 -68
- package/package.json +5 -1
- package/src/agrippa/commands/clone.js +17 -10
- package/src/agrippa/commands/cloneLrp.js +114 -0
- package/src/agrippa/commands/clonePb.js +10 -10
- package/src/agrippa/commands/diff.js +9 -8
- package/src/agrippa/commands/init.js +14 -13
- package/src/agrippa/commands/initPhase.js +51 -42
- package/src/agrippa/commands/pb.js +71 -39
- package/src/agrippa/commands/pull.js +137 -42
- package/src/agrippa/commands/pullLrp.js +54 -0
- package/src/agrippa/commands/pullPb.js +2 -3
- package/src/agrippa/commands/push.js +112 -33
- package/src/agrippa/commands/pushLrp.js +56 -0
- package/src/agrippa/commands/repair.js +4 -3
- package/src/agrippa/index.js +48 -30
- package/src/agrippa/lib/lrpApi.js +153 -0
- package/src/agrippa/lib/pbEdit.js +31 -10
- package/src/agrippa/lib/pbLayout.js +8 -1
- package/src/agrippa/lib/pbModel.js +318 -86
- package/src/agrippa/lib/pbPreview.js +6 -2
- package/src/agrippa/lib/pbProject.js +93 -7
- package/src/agrippa/lib/pbScriptTemplate.js +29 -0
- package/src/commands/autopr.js +21 -22
- package/src/commands/changelog.js +4 -3
- package/src/commands/commit.js +11 -10
- package/src/commands/export.js +2 -1
- package/src/commands/exportPb.js +19 -2
- package/src/commands/init.js +2 -1
- package/src/commands/routine.js +19 -8
- package/src/index.js +137 -112
- package/src/lib/auth.js +19 -1
- package/src/lib/logger.js +12 -1
|
@@ -2,14 +2,17 @@ import { mkdirSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { dirname, join } from 'path';
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
4
|
import { getToken } from '../../lib/auth.js';
|
|
5
|
+
import { log } from '../../lib/logger.js';
|
|
5
6
|
import { updateMfa, updatePhase } from '../lib/api.js';
|
|
6
7
|
import { computeChecksum } from '../lib/checksum.js';
|
|
7
8
|
import { loadEffectiveEnv, readConfig, writeConfig } from '../lib/config.js';
|
|
9
|
+
import { fetchUpstream } from '../lib/lrpApi.js';
|
|
8
10
|
import { getProcess } from '../lib/pbApi.js';
|
|
9
11
|
import { localChecksum, remoteChecksumPb } from '../lib/pbProject.js';
|
|
10
12
|
import { projectReader } from '../lib/pbWorkspace.js';
|
|
11
13
|
import { fileExists, readCodeFile } from '../lib/workspace.js';
|
|
12
14
|
import { fetchRemoteCode, selectEntries } from './pull.js';
|
|
15
|
+
import { deploy, pushLrpEntry } from './pushLrp.js';
|
|
13
16
|
import { publish, pushPbEntry } from './pushPb.js';
|
|
14
17
|
|
|
15
18
|
const BACKUP_DIR = '.backup';
|
|
@@ -21,24 +24,28 @@ async function push(opts = {}) {
|
|
|
21
24
|
// Stale-entry check (a path may be a file for phase/mfa or a dir for pb).
|
|
22
25
|
const stale = config.workspace.filter((e) => !fileExists(e.path));
|
|
23
26
|
if (stale.length) {
|
|
24
|
-
|
|
25
|
-
stale.forEach((e) =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
log('\nThe following tracked resources no longer exist on disk:');
|
|
28
|
+
stale.forEach((e) => log(` - ${e.path} (${e.name})`));
|
|
29
|
+
if (opts.nonInteractive) {
|
|
30
|
+
log(' (non-interactive: leaving them tracked; run interactively to clean up)');
|
|
31
|
+
} else {
|
|
32
|
+
const { cleanup } = await inquirer.prompt([
|
|
33
|
+
{
|
|
34
|
+
type: 'confirm',
|
|
35
|
+
name: 'cleanup',
|
|
36
|
+
message: 'Remove these entries from the workspace config?',
|
|
37
|
+
default: true,
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
if (cleanup) {
|
|
41
|
+
config.workspace = config.workspace.filter((e) => fileExists(e.path));
|
|
42
|
+
writeConfig(config);
|
|
43
|
+
}
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
if (!config.workspace.length) {
|
|
41
|
-
|
|
48
|
+
log('No tracked resources. Run `agrippa clone` first.');
|
|
42
49
|
return;
|
|
43
50
|
}
|
|
44
51
|
|
|
@@ -46,13 +53,18 @@ async function push(opts = {}) {
|
|
|
46
53
|
(e) => e.object_type === 'phase' || e.object_type === 'mfa'
|
|
47
54
|
);
|
|
48
55
|
const hasPb = config.workspace.some((e) => e.object_type === 'process_builder');
|
|
56
|
+
const hasLrp = config.workspace.some((e) => e.object_type === 'long_running_process');
|
|
49
57
|
const ripUrl = process.env.RIP_URL;
|
|
50
58
|
if (hasCode && !ripUrl)
|
|
51
59
|
throw new Error('RIP_URL is not configured. Run `prbot init` or set it in agrippa.yaml.');
|
|
52
60
|
if (hasPb && !process.env.PB_URL)
|
|
53
61
|
throw new Error('PB_URL is not configured. Run `prbot init` or set it in agrippa.yaml.');
|
|
62
|
+
if (hasLrp && !process.env.IMPORTEXPORT_URL)
|
|
63
|
+
throw new Error(
|
|
64
|
+
'IMPORTEXPORT_URL is not configured. Run `prbot init` or set it in agrippa.yaml.'
|
|
65
|
+
);
|
|
54
66
|
|
|
55
|
-
|
|
67
|
+
log('Fetching remote state...');
|
|
56
68
|
const token = await getToken();
|
|
57
69
|
|
|
58
70
|
const remoteCodeMap = hasCode
|
|
@@ -66,6 +78,14 @@ async function push(opts = {}) {
|
|
|
66
78
|
upstreamMap.set(e.guid, null);
|
|
67
79
|
}
|
|
68
80
|
}
|
|
81
|
+
const lrpUpstreamMap = new Map();
|
|
82
|
+
for (const e of config.workspace.filter((x) => x.object_type === 'long_running_process')) {
|
|
83
|
+
try {
|
|
84
|
+
lrpUpstreamMap.set(e.name, await fetchUpstream(token, e.name));
|
|
85
|
+
} catch {
|
|
86
|
+
lrpUpstreamMap.set(e.name, null);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
69
89
|
|
|
70
90
|
// Classify every entry to a status badge — concern: overwriting remote work.
|
|
71
91
|
const classified = config.workspace.map((entry) => {
|
|
@@ -81,6 +101,18 @@ async function push(opts = {}) {
|
|
|
81
101
|
return { ...entry, upstream, status };
|
|
82
102
|
}
|
|
83
103
|
|
|
104
|
+
if (entry.object_type === 'long_running_process') {
|
|
105
|
+
const upstream = lrpUpstreamMap.get(entry.name) ?? null;
|
|
106
|
+
const localSemantic = localChecksum(projectReader(entry.path));
|
|
107
|
+
const remoteSemantic = upstream ? remoteChecksumPb(upstream.payload) : null;
|
|
108
|
+
const pullChecksum = entry.checksum_at_pull;
|
|
109
|
+
let status;
|
|
110
|
+
if (localSemantic === remoteSemantic) status = 'unchanged';
|
|
111
|
+
else if (pullChecksum === remoteSemantic) status = 'fast-forward';
|
|
112
|
+
else status = 'conflict';
|
|
113
|
+
return { ...entry, upstream, status };
|
|
114
|
+
}
|
|
115
|
+
|
|
84
116
|
const key = `${entry.object_type}:${entry.id}`;
|
|
85
117
|
const remoteCode = remoteCodeMap.get(key) ?? null;
|
|
86
118
|
const localCode = readCodeFile(entry.path);
|
|
@@ -96,22 +128,26 @@ async function push(opts = {}) {
|
|
|
96
128
|
|
|
97
129
|
const changed = classified.filter((e) => e.status !== 'unchanged');
|
|
98
130
|
if (!changed.length) {
|
|
99
|
-
|
|
131
|
+
log('Nothing to push — everything matches the last-pulled state.');
|
|
100
132
|
return;
|
|
101
133
|
}
|
|
102
134
|
|
|
103
|
-
const selected = await selectEntries(changed, 'push (overwrites remote)',
|
|
135
|
+
const selected = await selectEntries(changed, 'push (overwrites remote)', opts);
|
|
104
136
|
if (!selected.length) {
|
|
105
|
-
|
|
137
|
+
log('Nothing selected. No changes made.');
|
|
106
138
|
return;
|
|
107
139
|
}
|
|
108
140
|
|
|
109
141
|
const backupTs = new Date().toISOString().replace(/:/g, '-').replace('T', '_').slice(0, 19);
|
|
110
142
|
|
|
111
|
-
// Back up remote code for phase/mfa before overwriting (pb
|
|
112
|
-
// full upstream payload inside pushPbEntry).
|
|
143
|
+
// Back up remote code for phase/mfa before overwriting (pb/lrp back up
|
|
144
|
+
// their own full upstream payload inside pushPbEntry/pushLrpEntry).
|
|
113
145
|
for (const entry of selected) {
|
|
114
|
-
if (
|
|
146
|
+
if (
|
|
147
|
+
entry.object_type !== 'process_builder' &&
|
|
148
|
+
entry.object_type !== 'long_running_process' &&
|
|
149
|
+
entry.remoteCode != null
|
|
150
|
+
) {
|
|
115
151
|
const backupPath = join(BACKUP_DIR, backupTs, entry.path);
|
|
116
152
|
mkdirSync(dirname(backupPath), { recursive: true });
|
|
117
153
|
writeFileSync(backupPath, (entry.remoteCode ?? '').trim() + '\n', 'utf-8');
|
|
@@ -119,15 +155,15 @@ async function push(opts = {}) {
|
|
|
119
155
|
}
|
|
120
156
|
|
|
121
157
|
const pushedPb = [];
|
|
158
|
+
const pushedLrp = [];
|
|
122
159
|
let pushed = 0;
|
|
123
160
|
for (const entry of selected) {
|
|
124
|
-
const idx = config.workspace.findIndex(
|
|
125
|
-
(e)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
);
|
|
161
|
+
const idx = config.workspace.findIndex((e) => {
|
|
162
|
+
if (e.object_type !== entry.object_type) return false;
|
|
163
|
+
if (entry.object_type === 'process_builder') return e.guid === entry.guid;
|
|
164
|
+
if (entry.object_type === 'long_running_process') return e.name === entry.name;
|
|
165
|
+
return e.id === entry.id;
|
|
166
|
+
});
|
|
131
167
|
|
|
132
168
|
if (entry.object_type === 'process_builder') {
|
|
133
169
|
const res = await pushPbEntry(token, entry, BACKUP_DIR, backupTs);
|
|
@@ -137,13 +173,26 @@ async function push(opts = {}) {
|
|
|
137
173
|
]
|
|
138
174
|
.filter(Boolean)
|
|
139
175
|
.join(', ');
|
|
140
|
-
|
|
176
|
+
log(` ${entry.name} → saved (draft)${note ? ` [${note}]` : ''}`);
|
|
141
177
|
if (idx !== -1) {
|
|
142
178
|
config.workspace[idx].checksum_at_pull = res.newChecksum;
|
|
143
179
|
if (res.newUpdatedDate) config.workspace[idx].updated_date = res.newUpdatedDate;
|
|
144
180
|
config.workspace[idx].status = res.newStatus || 'draft';
|
|
145
181
|
}
|
|
146
182
|
pushedPb.push({ entry, idx });
|
|
183
|
+
} else if (entry.object_type === 'long_running_process') {
|
|
184
|
+
const res = await pushLrpEntry(token, entry, BACKUP_DIR, backupTs);
|
|
185
|
+
log(` ${entry.name} → saved`);
|
|
186
|
+
if (idx !== -1) {
|
|
187
|
+
config.workspace[idx].checksum_at_pull = res.newChecksum;
|
|
188
|
+
config.workspace[idx].tenant_id = res.newRow.tenantId;
|
|
189
|
+
config.workspace[idx].description = res.newRow.description;
|
|
190
|
+
config.workspace[idx].version = res.newRow.version;
|
|
191
|
+
config.workspace[idx].status = res.newRow.status;
|
|
192
|
+
}
|
|
193
|
+
// deployId is the fresh post-save id (re-resolved by name in
|
|
194
|
+
// pushLrpEntry); the pre-save id is dead once the save returns.
|
|
195
|
+
pushedLrp.push({ entry, idx, deployId: res.deployId });
|
|
147
196
|
} else {
|
|
148
197
|
const code = entry.localCode ?? '';
|
|
149
198
|
if (entry.object_type === 'phase') await updatePhase(token, ripUrl, entry.id, code);
|
|
@@ -153,15 +202,18 @@ async function push(opts = {}) {
|
|
|
153
202
|
pushed++;
|
|
154
203
|
}
|
|
155
204
|
|
|
156
|
-
|
|
205
|
+
log(`\nRemote backups written to ${BACKUP_DIR}/${backupTs}/`);
|
|
157
206
|
|
|
158
|
-
// Publish step for pushed wizards
|
|
207
|
+
// Publish/deploy step for pushed wizards and LRPs.
|
|
159
208
|
if (pushedPb.length) {
|
|
160
209
|
await handlePublish(token, pushedPb, config, opts);
|
|
161
210
|
}
|
|
211
|
+
if (pushedLrp.length) {
|
|
212
|
+
await handleDeploy(token, pushedLrp, config, opts);
|
|
213
|
+
}
|
|
162
214
|
|
|
163
215
|
writeConfig(config);
|
|
164
|
-
|
|
216
|
+
log(`\nPushed ${pushed} record(s).`);
|
|
165
217
|
}
|
|
166
218
|
|
|
167
219
|
async function handlePublish(token, pushedPb, config, opts) {
|
|
@@ -169,6 +221,8 @@ async function handlePublish(token, pushedPb, config, opts) {
|
|
|
169
221
|
let doPublish;
|
|
170
222
|
if (opts.skipPublish) doPublish = false;
|
|
171
223
|
else if (opts.publish) doPublish = true;
|
|
224
|
+
else if (opts.nonInteractive)
|
|
225
|
+
doPublish = false; // no stdin to prompt on; default to safe
|
|
172
226
|
else {
|
|
173
227
|
({ doPublish } = await inquirer.prompt([
|
|
174
228
|
{
|
|
@@ -182,7 +236,32 @@ async function handlePublish(token, pushedPb, config, opts) {
|
|
|
182
236
|
if (doPublish) {
|
|
183
237
|
await publish(token, entry.guid);
|
|
184
238
|
if (idx !== -1) config.workspace[idx].status = 'published';
|
|
185
|
-
|
|
239
|
+
log(` published ${entry.name}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function handleDeploy(token, pushedLrp, config, opts) {
|
|
245
|
+
for (const { entry, idx, deployId } of pushedLrp) {
|
|
246
|
+
let doDeploy;
|
|
247
|
+
if (opts.skipPublish) doDeploy = false;
|
|
248
|
+
else if (opts.publish) doDeploy = true;
|
|
249
|
+
else if (opts.nonInteractive)
|
|
250
|
+
doDeploy = false; // no stdin to prompt on; default to safe
|
|
251
|
+
else {
|
|
252
|
+
({ doDeploy } = await inquirer.prompt([
|
|
253
|
+
{
|
|
254
|
+
type: 'confirm',
|
|
255
|
+
name: 'doDeploy',
|
|
256
|
+
message: `Deploy "${entry.name}" now?`,
|
|
257
|
+
default: false,
|
|
258
|
+
},
|
|
259
|
+
]));
|
|
260
|
+
}
|
|
261
|
+
if (doDeploy) {
|
|
262
|
+
await deploy(token, deployId);
|
|
263
|
+
if (idx !== -1) config.workspace[idx].status = 'deployed';
|
|
264
|
+
log(` deployed ${entry.name}`);
|
|
186
265
|
}
|
|
187
266
|
}
|
|
188
267
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { deployLrp, resolveLrpByName, saveLrp } from '../lib/lrpApi.js';
|
|
4
|
+
import { localChecksum, recompose } from '../lib/pbProject.js';
|
|
5
|
+
import { projectReader } from '../lib/pbWorkspace.js';
|
|
6
|
+
|
|
7
|
+
// Push one LRP entry: back up upstream, re-resolve the CURRENT id/tenantId by
|
|
8
|
+
// name (never trust a stored/stale id — it changes on every save/version),
|
|
9
|
+
// and PATCH the recomposed XML back. Returns a summary; deploy is a separate
|
|
10
|
+
// step (see deploy()), mirroring PB's push-then-publish split.
|
|
11
|
+
//
|
|
12
|
+
// The save bumps the version and mints a NEW id, so the pre-save id is stale
|
|
13
|
+
// the moment saveLrp returns. Both the deploy target and the post-save
|
|
14
|
+
// version/status must come from a fresh resolve-by-name AFTER the save — never
|
|
15
|
+
// from the pre-save row or the PATCH response (which does not echo the new id).
|
|
16
|
+
async function pushLrpEntry(token, entry, backupDir, backupTs) {
|
|
17
|
+
const read = projectReader(entry.path);
|
|
18
|
+
const localPayload = recompose(read);
|
|
19
|
+
const upstream = entry.upstream; // { row, payload } from push.js's classification
|
|
20
|
+
|
|
21
|
+
if (upstream) {
|
|
22
|
+
const backupPath = join(backupDir, backupTs, entry.path, 'upstream.xml');
|
|
23
|
+
mkdirSync(dirname(backupPath), { recursive: true });
|
|
24
|
+
writeFileSync(backupPath, upstream.payload.built_page, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Re-resolve immediately before saving — the row captured during
|
|
28
|
+
// classification may be stale if something else saved in between.
|
|
29
|
+
const row = await resolveLrpByName(token, entry.name);
|
|
30
|
+
const description = upstream?.row?.description ?? entry.description ?? '';
|
|
31
|
+
const saved = await saveLrp(
|
|
32
|
+
token,
|
|
33
|
+
{ ...row, bpmnFileSvg: entry.svg ?? row.bpmnFileSvg },
|
|
34
|
+
localPayload.built_page,
|
|
35
|
+
description
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// The save minted a new id and bumped the version — re-resolve by name to
|
|
39
|
+
// get the fresh row. deployBpmn must target this new id (the pre-save id is
|
|
40
|
+
// now dead: deploying it 200s but activates nothing), and the workspace
|
|
41
|
+
// entry's version/status must come from here, not the stale pre-save row.
|
|
42
|
+
const deployRow = await resolveLrpByName(token, entry.name);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
newChecksum: localChecksum(read),
|
|
46
|
+
newRow: { ...deployRow, description },
|
|
47
|
+
saved,
|
|
48
|
+
deployId: deployRow.id,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function deploy(token, id) {
|
|
53
|
+
return deployLrp(token, id);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { pushLrpEntry, deploy };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { log } from '../../lib/logger.js';
|
|
1
2
|
import { readConfig, writeConfig } from '../lib/config.js';
|
|
2
3
|
import { fileExists } from '../lib/workspace.js';
|
|
3
4
|
|
|
@@ -9,16 +10,16 @@ async function repair() {
|
|
|
9
10
|
config.workspace = config.workspace.filter((entry) => fileExists(entry.path));
|
|
10
11
|
|
|
11
12
|
if (!stale.length) {
|
|
12
|
-
|
|
13
|
+
log('No stale entries found.');
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
for (const entry of stale) {
|
|
17
|
-
|
|
18
|
+
log(` removed: ${entry.path} (${entry.name})`);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
writeConfig(config);
|
|
21
|
-
|
|
22
|
+
log(
|
|
22
23
|
`Removed ${stale.length} stale entr${stale.length === 1 ? 'y' : 'ies'} (${before} → ${config.workspace.length}).`
|
|
23
24
|
);
|
|
24
25
|
}
|
package/src/agrippa/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import { program } from 'commander';
|
|
4
|
+
import { error } from '../lib/logger.js';
|
|
4
5
|
import { clone } from './commands/clone.js';
|
|
5
6
|
import { diff } from './commands/diff.js';
|
|
6
7
|
import { init } from './commands/init.js';
|
|
@@ -24,7 +25,7 @@ const require = createRequire(import.meta.url);
|
|
|
24
25
|
const { version } = require('../../package.json');
|
|
25
26
|
|
|
26
27
|
process.on('unhandledRejection', (err) => {
|
|
27
|
-
|
|
28
|
+
error(`Error: ${err.message}`);
|
|
28
29
|
process.exit(1);
|
|
29
30
|
});
|
|
30
31
|
|
|
@@ -35,23 +36,26 @@ program
|
|
|
35
36
|
.description('Create agrippa.yaml workspace config in the current directory')
|
|
36
37
|
.action(() =>
|
|
37
38
|
init().catch((err) => {
|
|
38
|
-
|
|
39
|
+
error(`Error: ${err.message}`);
|
|
39
40
|
process.exit(1);
|
|
40
41
|
})
|
|
41
42
|
);
|
|
42
43
|
|
|
43
44
|
program
|
|
44
45
|
.command('clone')
|
|
45
|
-
.description(
|
|
46
|
+
.description(
|
|
47
|
+
'Clone a phase, MFA, process-builder wizard, or long-running process into this workspace'
|
|
48
|
+
)
|
|
46
49
|
.option('--phase', 'Clone a phase (select a workflow)')
|
|
47
50
|
.option('--mfa', 'Clone a Model Function Access record')
|
|
48
51
|
.option('--pb', 'Clone a process-builder wizard')
|
|
52
|
+
.option('--lrp', 'Clone a long-running process')
|
|
49
53
|
.option('--id <id>', 'Record ID to clone (phase/mfa)')
|
|
50
|
-
.option('--name <
|
|
51
|
-
.option('--path <path>', 'Destination path (file for MFA, base dir for workflow/pb)')
|
|
54
|
+
.option('--name <name>', 'document_id (--pb) or process name (--lrp) to clone')
|
|
55
|
+
.option('--path <path>', 'Destination path (file for MFA, base dir for workflow/pb/lrp)')
|
|
52
56
|
.action((opts) =>
|
|
53
57
|
clone(opts).catch((err) => {
|
|
54
|
-
|
|
58
|
+
error(`Error: ${err.message}`);
|
|
55
59
|
process.exit(1);
|
|
56
60
|
})
|
|
57
61
|
);
|
|
@@ -59,21 +63,29 @@ program
|
|
|
59
63
|
program
|
|
60
64
|
.command('pull')
|
|
61
65
|
.description('Pull remote changes into local files')
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
.option(
|
|
67
|
+
'--non-interactive',
|
|
68
|
+
'No prompts; auto-select safe (fast-forward) entries and fail if any is in conflict'
|
|
69
|
+
)
|
|
70
|
+
.action((opts) =>
|
|
71
|
+
pull(opts).catch((err) => {
|
|
72
|
+
error(`Error: ${err.message}`);
|
|
65
73
|
process.exit(1);
|
|
66
74
|
})
|
|
67
75
|
);
|
|
68
76
|
|
|
69
77
|
program
|
|
70
78
|
.command('push')
|
|
71
|
-
.description('Push local changes to RIP / Process Builder (backs up remote first)')
|
|
72
|
-
.option('--publish', 'Auto-publish pushed
|
|
73
|
-
.option('--skip-publish', 'Skip publishing pushed wizards (no prompt)')
|
|
79
|
+
.description('Push local changes to RIP / Process Builder / LRP (backs up remote first)')
|
|
80
|
+
.option('--publish', 'Auto-publish pushed wizards and auto-deploy pushed LRPs')
|
|
81
|
+
.option('--skip-publish', 'Skip publishing/deploying pushed wizards and LRPs (no prompt)')
|
|
82
|
+
.option(
|
|
83
|
+
'--non-interactive',
|
|
84
|
+
'No prompts; auto-select safe (fast-forward) entries and fail if any is in conflict'
|
|
85
|
+
)
|
|
74
86
|
.action((opts) =>
|
|
75
87
|
push(opts).catch((err) => {
|
|
76
|
-
|
|
88
|
+
error(`Error: ${err.message}`);
|
|
77
89
|
process.exit(1);
|
|
78
90
|
})
|
|
79
91
|
);
|
|
@@ -83,7 +95,7 @@ program
|
|
|
83
95
|
.description('Show differences between local files and remote code')
|
|
84
96
|
.action((path) =>
|
|
85
97
|
diff(path).catch((err) => {
|
|
86
|
-
|
|
98
|
+
error(`Error: ${err.message}`);
|
|
87
99
|
process.exit(1);
|
|
88
100
|
})
|
|
89
101
|
);
|
|
@@ -93,7 +105,7 @@ program
|
|
|
93
105
|
.description('Initialize a phase with default code template and result vars')
|
|
94
106
|
.action(() =>
|
|
95
107
|
initPhase().catch((err) => {
|
|
96
|
-
|
|
108
|
+
error(`Error: ${err.message}`);
|
|
97
109
|
process.exit(1);
|
|
98
110
|
})
|
|
99
111
|
);
|
|
@@ -103,30 +115,34 @@ program
|
|
|
103
115
|
.description('Remove stale workspace entries where local file no longer exists')
|
|
104
116
|
.action(() =>
|
|
105
117
|
repair().catch((err) => {
|
|
106
|
-
|
|
118
|
+
error(`Error: ${err.message}`);
|
|
107
119
|
process.exit(1);
|
|
108
120
|
})
|
|
109
121
|
);
|
|
110
122
|
|
|
111
|
-
// ---- pb: local editing helpers for a cloned process-builder wizard ----
|
|
123
|
+
// ---- pb: local editing helpers for a cloned process-builder wizard or LRP ----
|
|
112
124
|
const die = (err) => {
|
|
113
|
-
|
|
125
|
+
error(`Error: ${err.message}`);
|
|
114
126
|
process.exit(1);
|
|
115
127
|
};
|
|
116
128
|
const pb = program
|
|
117
129
|
.command('pb')
|
|
118
|
-
.description(
|
|
130
|
+
.description(
|
|
131
|
+
'Edit a cloned process-builder wizard or long-running process (local; run `pb format` after edits)'
|
|
132
|
+
);
|
|
119
133
|
|
|
120
134
|
pb.command('format')
|
|
121
135
|
.description('Auto-lay-out the diagram (left→right) and rewrite geometry')
|
|
122
|
-
.option('--pb <
|
|
136
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP (else single-entry / fuzzy prompt)')
|
|
123
137
|
.action((opts) => pbFormat(opts).catch(die));
|
|
124
138
|
|
|
125
139
|
pb.command('add')
|
|
126
140
|
.description('Add a node (scaffolds script/page); stub geometry, run format after')
|
|
127
141
|
.requiredOption(
|
|
128
142
|
'--type <type>',
|
|
129
|
-
'Node type: scriptTask|serviceTask|userTask|exclusiveGateway|subProcess|transaction|
|
|
143
|
+
'Node type: scriptTask|serviceTask|userTask|exclusiveGateway|subProcess|transaction|' +
|
|
144
|
+
'startEvent|endEvent|boundaryEvent|intermediateCatchEvent|intermediateThrowEvent|' +
|
|
145
|
+
'callActivity|parallelGateway|eventBasedGateway (userTask is process-builder only)'
|
|
130
146
|
)
|
|
131
147
|
.option('--name <name>', 'Node name')
|
|
132
148
|
.option('--parent <id>', 'Place inside this subProcess/transaction')
|
|
@@ -136,13 +152,13 @@ pb.command('add')
|
|
|
136
152
|
'exactly one edge must already run --from → --to)'
|
|
137
153
|
)
|
|
138
154
|
.option('--to <id>', 'Insert between two already-connected nodes: target id (requires --from)')
|
|
139
|
-
.option('--pb <
|
|
155
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
140
156
|
.action((opts) => pbAdd(opts).catch(die));
|
|
141
157
|
|
|
142
158
|
pb.command('rm')
|
|
143
159
|
.description('Remove a node, its edges, and its script/page files')
|
|
144
160
|
.requiredOption('--id <id>', 'Node id to remove')
|
|
145
|
-
.option('--pb <
|
|
161
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
146
162
|
.action((opts) => pbRemove(opts).catch(die));
|
|
147
163
|
|
|
148
164
|
pb.command('connect')
|
|
@@ -153,7 +169,7 @@ pb.command('connect')
|
|
|
153
169
|
.option('--condition <expr>', 'Condition expression, e.g. ${isAlive}')
|
|
154
170
|
.option('--condition-type <type>', 'xsi:type for the condition (default tFormalExpression)')
|
|
155
171
|
.option('--default', 'Mark this as the source gateway default flow')
|
|
156
|
-
.option('--pb <
|
|
172
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
157
173
|
.action((opts) => pbConnect(opts).catch(die));
|
|
158
174
|
|
|
159
175
|
pb.command('disconnect')
|
|
@@ -161,7 +177,7 @@ pb.command('disconnect')
|
|
|
161
177
|
.option('--id <id>', 'Edge id to remove')
|
|
162
178
|
.option('--from <id>', 'Source node id')
|
|
163
179
|
.option('--to <id>', 'Target node id')
|
|
164
|
-
.option('--pb <
|
|
180
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
165
181
|
.action((opts) => pbDisconnect(opts).catch(die));
|
|
166
182
|
|
|
167
183
|
pb.command('set-default')
|
|
@@ -169,23 +185,25 @@ pb.command('set-default')
|
|
|
169
185
|
.option('--id <id>', 'Edge id to mark default')
|
|
170
186
|
.option('--from <id>', 'Source gateway id')
|
|
171
187
|
.option('--to <id>', 'Target node id')
|
|
172
|
-
.option('--pb <
|
|
188
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
173
189
|
.action((opts) => pbSetDefault(opts).catch(die));
|
|
174
190
|
|
|
175
191
|
pb.command('lint')
|
|
176
|
-
.description(
|
|
177
|
-
|
|
192
|
+
.description(
|
|
193
|
+
'Check diagram for structural issues (edge names, incoming-edge rules, gateway rules)'
|
|
194
|
+
)
|
|
195
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
178
196
|
.action((opts) => pbLint(opts).catch(die));
|
|
179
197
|
|
|
180
198
|
pb.command('ls')
|
|
181
199
|
.description('List nodes and edges (discover ids without reading the YAML)')
|
|
182
|
-
.option('--pb <
|
|
200
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
183
201
|
.action((opts) => pbList(opts).catch(die));
|
|
184
202
|
|
|
185
203
|
pb.command('preview')
|
|
186
204
|
.description('Render the diagram to an SVG (dev check of format output)')
|
|
187
205
|
.option('--out <file>', 'Output path (default <project>/preview.svg)')
|
|
188
|
-
.option('--pb <
|
|
206
|
+
.option('--pb <document_id_or_name>', 'Target wizard/LRP')
|
|
189
207
|
.action((opts) => pbPreview(opts).catch(die));
|
|
190
208
|
|
|
191
209
|
program.parse();
|