@waron97/prbot 3.3.0 → 3.5.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.
@@ -2,6 +2,7 @@ import search from '@inquirer/search';
2
2
  import inquirer from 'inquirer';
3
3
  import { getToken } from '../../lib/auth.js';
4
4
  import { fuzzyMatch } from '../../lib/fuzzy.js';
5
+ import { log } from '../../lib/logger.js';
5
6
  import {
6
7
  createConfigurator,
7
8
  deleteConfigurator,
@@ -75,12 +76,12 @@ async function initPhase() {
75
76
  if (!ripUrl)
76
77
  throw new Error('RIP_URL is not configured. Run `prbot init` or set it in agrippa.yaml.');
77
78
 
78
- console.log('Fetching workflows...');
79
+ log('Fetching workflows...');
79
80
  const token = await getToken();
80
81
  const workflows = await listWorkflows(token, ripUrl);
81
82
 
82
83
  if (!workflows.length) {
83
- console.log('No workflows found.');
84
+ log('No workflows found.');
84
85
  return;
85
86
  }
86
87
 
@@ -92,11 +93,11 @@ async function initPhase() {
92
93
  },
93
94
  });
94
95
 
95
- console.log(`Fetching phases for "${workflow.name}"...`);
96
+ log(`Fetching phases for "${workflow.name}"...`);
96
97
  const phases = await getPhasesByWorkflow(token, ripUrl, workflow.id);
97
98
 
98
99
  if (!phases.length) {
99
- console.log('No phases found for this workflow.');
100
+ log('No phases found for this workflow.');
100
101
  return;
101
102
  }
102
103
 
@@ -111,7 +112,7 @@ async function initPhase() {
111
112
  ]);
112
113
 
113
114
  if (!selectedPhases.length) {
114
- console.log('No phases selected. Aborted.');
115
+ log('No phases selected. Aborted.');
115
116
  return;
116
117
  }
117
118
 
@@ -125,7 +126,7 @@ async function initPhase() {
125
126
  ]);
126
127
 
127
128
  if (!confirm) {
128
- console.log('Aborted.');
129
+ log('Aborted.');
129
130
  return;
130
131
  }
131
132
 
@@ -157,15 +158,13 @@ async function initPhase() {
157
158
  });
158
159
  }
159
160
 
160
- console.log(`Initialized phase "${phase.name}".`);
161
+ log(`Initialized phase "${phase.name}".`);
161
162
  if (results.length > 0) {
162
- console.log(` ${results.length} configurator(s) created: ${vars.join(', ')}`);
163
+ log(` ${results.length} configurator(s) created: ${vars.join(', ')}`);
163
164
  }
164
165
  }
165
166
 
166
- console.log(
167
- `Run 'agrippa pull' in workspaces that track this workflow to fetch the updated code.`
168
- );
167
+ log(`Run 'agrippa pull' in workspaces that track this workflow to fetch the updated code.`);
169
168
  }
170
169
 
171
170
  export { initPhase };
@@ -18,6 +18,7 @@ import { dirname, join } from 'path';
18
18
  import search from '@inquirer/search';
19
19
  import { parse as yamlParse } from 'yaml';
20
20
  import { fuzzyMatch } from '../../lib/fuzzy.js';
21
+ import { log, warn } from '../../lib/logger.js';
21
22
  import { readConfig } from '../lib/config.js';
22
23
  import {
23
24
  addNode,
@@ -120,7 +121,7 @@ function validate(dir) {
120
121
  try {
121
122
  recompose(projectReader(dir));
122
123
  } catch (e) {
123
- console.warn(`WARNING: project no longer recomposes cleanly: ${e.message}`);
124
+ warn(`WARNING: project no longer recomposes cleanly: ${e.message}`);
124
125
  }
125
126
  }
126
127
 
@@ -139,13 +140,13 @@ async function pbFormat(opts) {
139
140
  if (!n.layout) missing++;
140
141
  });
141
142
  validate(dir);
142
- console.log(
143
+ log(
143
144
  `Formatted ${dir} (${nodes} node(s) laid out${missing ? `, ${missing} without layout` : ''}).`
144
145
  );
145
146
  const issues = lintAll(structure);
146
147
  if (issues.length) {
147
- console.warn('Diagram issues:');
148
- for (const w of issues) console.warn(` ! ${w}`);
148
+ warn('Diagram issues:');
149
+ for (const w of issues) warn(` ! ${w}`);
149
150
  }
150
151
  }
151
152
 
@@ -180,13 +181,13 @@ async function pbAdd(opts) {
180
181
  saveStructure(dir, structure);
181
182
  saveManifest(dir, manifest);
182
183
  validate(dir);
183
- console.log(
184
+ log(
184
185
  `Added ${result.type} ${result.id}${result.file ? ` (${result.file})` : ''} between ${opts.from} → ${opts.to}.`
185
186
  );
186
- console.log(` ${opts.from} → ${result.id} (${result.edgeId}, retargeted)`);
187
- console.log(` ${result.id} → ${opts.to} (${result.newEdgeId})`);
188
- for (const w of result.warnings || []) console.warn(` ! ${w}`);
189
- console.log('Run `agrippa pb format` to lay it out.');
187
+ log(` ${opts.from} → ${result.id} (${result.edgeId}, retargeted)`);
188
+ log(` ${result.id} → ${opts.to} (${result.newEdgeId})`);
189
+ for (const w of result.warnings || []) warn(` ! ${w}`);
190
+ log('Run `agrippa pb format` to lay it out.');
190
191
  return;
191
192
  }
192
193
 
@@ -200,10 +201,8 @@ async function pbAdd(opts) {
200
201
  saveStructure(dir, structure);
201
202
  saveManifest(dir, manifest);
202
203
  validate(dir);
203
- console.log(`Added ${result.type} ${result.id}${result.file ? ` (${result.file})` : ''}.`);
204
- console.log(
205
- 'Connect it with `agrippa pb connect`, then run `agrippa pb format` to lay it out.'
206
- );
204
+ log(`Added ${result.type} ${result.id}${result.file ? ` (${result.file})` : ''}.`);
205
+ log('Connect it with `agrippa pb connect`, then run `agrippa pb format` to lay it out.');
207
206
  }
208
207
 
209
208
  async function pbRemove(opts) {
@@ -215,10 +214,12 @@ async function pbRemove(opts) {
215
214
  saveStructure(dir, structure);
216
215
  saveManifest(dir, manifest);
217
216
  validate(dir);
218
- console.log(
217
+ log(
219
218
  `Removed ${result.removed.length} node(s) [${result.removed.join(', ')}], ` +
220
219
  `${result.removedEdges} dangling edge(s), ${deletes.length} file(s).`
221
220
  );
221
+ for (const c of result.clearedDefaults || [])
222
+ log(` cleared dangling default ${c.edge} on ${c.node}.`);
222
223
  }
223
224
 
224
225
  async function pbConnect(opts) {
@@ -235,11 +236,11 @@ async function pbConnect(opts) {
235
236
  });
236
237
  saveStructure(dir, structure);
237
238
  validate(dir);
238
- console.log(
239
+ log(
239
240
  `Connected ${result.from} → ${result.to} (${result.id})${opts.default ? ' [default]' : ''}.`
240
241
  );
241
- for (const w of result.warnings || []) console.warn(` ! ${w}`);
242
- console.log('Run `agrippa pb format` to route it.');
242
+ for (const w of result.warnings || []) warn(` ! ${w}`);
243
+ log('Run `agrippa pb format` to route it.');
243
244
  }
244
245
 
245
246
  async function pbDisconnect(opts) {
@@ -250,7 +251,9 @@ async function pbDisconnect(opts) {
250
251
  const { result } = disconnect(structure, { id: opts.id, from: opts.from, to: opts.to });
251
252
  saveStructure(dir, structure);
252
253
  validate(dir);
253
- console.log(`Removed ${result.removed} edge(s)${result.id ? ` (${result.id})` : ''}.`);
254
+ log(`Removed ${result.removed} edge(s)${result.id ? ` (${result.id})` : ''}.`);
255
+ for (const c of result.clearedDefaults || [])
256
+ log(` cleared dangling default ${c.edge} on ${c.node}.`);
254
257
  }
255
258
 
256
259
  async function pbSetDefault(opts) {
@@ -261,11 +264,11 @@ async function pbSetDefault(opts) {
261
264
  const { result } = setDefault(structure, { id: opts.id, from: opts.from, to: opts.to });
262
265
  saveStructure(dir, structure);
263
266
  validate(dir);
264
- console.log(
267
+ log(
265
268
  `Default flow on ${result.from} is now ${result.id} (→ ${result.to})` +
266
269
  `${result.prev && result.prev !== result.id ? `, was ${result.prev}` : ''}.`
267
270
  );
268
- for (const w of result.warnings || []) console.warn(` ! ${w}`);
271
+ for (const w of result.warnings || []) warn(` ! ${w}`);
269
272
  }
270
273
 
271
274
  async function pbList(opts) {
@@ -275,7 +278,7 @@ async function pbList(opts) {
275
278
  for (const r of rows) {
276
279
  const where = r.parent ? ` [in ${r.parent}]` : '';
277
280
  const label = r.name ? ` "${r.name}"` : '';
278
- console.log(`${r.id} (${r.type})${label}${where}`);
281
+ log(`${r.id} (${r.type})${label}${where}`);
279
282
  for (const e of r.edges) {
280
283
  const tag = [
281
284
  e.isDefault && '[default]',
@@ -284,10 +287,10 @@ async function pbList(opts) {
284
287
  ]
285
288
  .filter(Boolean)
286
289
  .join(' ');
287
- console.log(` → ${e.target} (${e.id})${tag ? ` ${tag}` : ''}`);
290
+ log(` → ${e.target} (${e.id})${tag ? ` ${tag}` : ''}`);
288
291
  }
289
292
  }
290
- console.log(`\n${rows.length} node(s).`);
293
+ log(`\n${rows.length} node(s).`);
291
294
  }
292
295
 
293
296
  async function pbPreview(opts) {
@@ -296,7 +299,7 @@ async function pbPreview(opts) {
296
299
  const svg = toSvg(structure);
297
300
  const out = opts.out || join(dir, 'preview.svg');
298
301
  writeFileSync(out, svg, 'utf-8');
299
- console.log(`Wrote ${out} (${svg.length} bytes).`);
302
+ log(`Wrote ${out} (${svg.length} bytes).`);
300
303
  }
301
304
 
302
305
  async function pbLint(opts) {
@@ -304,9 +307,9 @@ async function pbLint(opts) {
304
307
  const { structure } = loadProject(dir);
305
308
  const issues = lintAll(structure);
306
309
  if (!issues.length) {
307
- console.log('No issues.');
310
+ log('No issues.');
308
311
  } else {
309
- for (const w of issues) console.warn(` ! ${w}`);
312
+ for (const w of issues) warn(` ! ${w}`);
310
313
  process.exitCode = 1;
311
314
  }
312
315
  }
@@ -1,6 +1,7 @@
1
1
  import { dirname } from 'path';
2
2
  import inquirer from 'inquirer';
3
3
  import { getToken } from '../../lib/auth.js';
4
+ import { log, warn } from '../../lib/logger.js';
4
5
  import { describeWorkflow, getPhasesByIds, getPhasesByWorkflow, listMfas } from '../lib/api.js';
5
6
  import { computeChecksum } from '../lib/checksum.js';
6
7
  import { loadEffectiveEnv, readConfig, writeConfig } from '../lib/config.js';
@@ -18,7 +19,7 @@ import {
18
19
  import { pullLrpEntry } from './pullLrp.js';
19
20
  import { pullPbEntry } from './pullPb.js';
20
21
 
21
- async function pull() {
22
+ async function pull(opts = {}) {
22
23
  const config = readConfig();
23
24
  loadEffectiveEnv(config);
24
25
 
@@ -29,19 +30,23 @@ async function pull() {
29
30
  // Stale-file check
30
31
  const stale = config.workspace.filter((e) => !fileExists(e.path));
31
32
  if (stale.length) {
32
- console.log('\nThe following tracked files no longer exist on disk:');
33
- stale.forEach((e) => console.log(` - ${e.path} (${e.name})`));
34
- const { cleanup } = await inquirer.prompt([
35
- {
36
- type: 'confirm',
37
- name: 'cleanup',
38
- message: 'Remove these entries from the workspace config?',
39
- default: true,
40
- },
41
- ]);
42
- if (cleanup) {
43
- config.workspace = config.workspace.filter((e) => fileExists(e.path));
44
- writeConfig(config);
33
+ log('\nThe following tracked files no longer exist on disk:');
34
+ stale.forEach((e) => log(` - ${e.path} (${e.name})`));
35
+ if (opts.nonInteractive) {
36
+ log(' (non-interactive: leaving them tracked; run interactively to clean up)');
37
+ } else {
38
+ const { cleanup } = await inquirer.prompt([
39
+ {
40
+ type: 'confirm',
41
+ name: 'cleanup',
42
+ message: 'Remove these entries from the workspace config?',
43
+ default: true,
44
+ },
45
+ ]);
46
+ if (cleanup) {
47
+ config.workspace = config.workspace.filter((e) => fileExists(e.path));
48
+ writeConfig(config);
49
+ }
45
50
  }
46
51
  }
47
52
 
@@ -58,7 +63,7 @@ async function pull() {
58
63
  (e) => e.object_type !== 'process_builder' && e.object_type !== 'long_running_process'
59
64
  );
60
65
  if (pullable.length) {
61
- console.log('Fetching remote code...');
66
+ log('Fetching remote code...');
62
67
  const remoteCodeMap = await fetchRemoteCode(token, ripUrl, pullable);
63
68
 
64
69
  const classified = pullable.map((entry) => {
@@ -85,12 +90,12 @@ async function pull() {
85
90
  const changed = classified.filter((e) => e.status !== 'unchanged');
86
91
 
87
92
  if (!changed.length) {
88
- console.log('Everything is up to date.');
93
+ log('Everything is up to date.');
89
94
  } else {
90
- const selected = await selectEntries(changed, 'pull (overwrites local files)');
95
+ const selected = await selectEntries(changed, 'pull (overwrites local files)', opts);
91
96
 
92
97
  if (!selected.length) {
93
- console.log('Nothing selected. No changes made.');
98
+ log('Nothing selected. No changes made.');
94
99
  } else {
95
100
  for (const entry of selected) {
96
101
  writeCodeFile(entry.path, entry.remoteCode);
@@ -105,18 +110,18 @@ async function pull() {
105
110
  }
106
111
  }
107
112
  writeConfig(config);
108
- console.log(`\nPulled ${selected.length} record(s).`);
113
+ log(`\nPulled ${selected.length} record(s).`);
109
114
  }
110
115
  }
111
116
  } else {
112
- console.log('No tracked resources. Run `agrippa clone` first.');
117
+ log('No tracked resources. Run `agrippa clone` first.');
113
118
  }
114
119
 
115
120
  // ── refresh tracked process-builder wizards ───────────────────────────────
116
- await pullPbEntries(token, config);
121
+ await pullPbEntries(token, config, opts);
117
122
 
118
123
  // ── refresh tracked long-running processes ────────────────────────────────
119
- await pullLrpEntries(token, config);
124
+ await pullLrpEntries(token, config, opts);
120
125
 
121
126
  // ── discover new phases on tracked workflows ──────────────────────────────
122
127
  await discoverNewPhases(token, ripUrl, config, changedWorkflowIds);
@@ -127,13 +132,13 @@ async function pull() {
127
132
  // unchanged local === remote semantically → nothing to do
128
133
  // fast-forward remote changed, local untouched since pull → safe overwrite
129
134
  // conflict local diverged from checksum_at_pull → overwrite loses local work
130
- async function pullPbEntries(token, config) {
135
+ async function pullPbEntries(token, config, opts = {}) {
131
136
  const entries = config.workspace.filter((e) => e.object_type === 'process_builder');
132
137
  if (!entries.length) return;
133
138
  if (!process.env.PB_URL)
134
139
  throw new Error('PB_URL is not configured. Run `prbot init` or set it in agrippa.yaml.');
135
140
 
136
- console.log('Checking process-builder wizards...');
141
+ log('Checking process-builder wizards...');
137
142
  const classified = [];
138
143
  for (const entry of entries) {
139
144
  let upstream = null;
@@ -143,7 +148,7 @@ async function pullPbEntries(token, config) {
143
148
  upstream = null;
144
149
  }
145
150
  if (!upstream) {
146
- console.warn(` ${entry.name}: could not fetch upstream, skipping`);
151
+ warn(` ${entry.name}: could not fetch upstream, skipping`);
147
152
  continue;
148
153
  }
149
154
  const localSemantic = localChecksum(projectReader(entry.path));
@@ -158,13 +163,13 @@ async function pullPbEntries(token, config) {
158
163
 
159
164
  const changed = classified.filter((e) => e.status !== 'unchanged');
160
165
  if (!changed.length) {
161
- console.log('Wizards are up to date.');
166
+ log('Wizards are up to date.');
162
167
  return;
163
168
  }
164
169
 
165
- const selected = await selectEntries(changed, 'pull (overwrites local wizard files)');
170
+ const selected = await selectEntries(changed, 'pull (overwrites local wizard files)', opts);
166
171
  if (!selected.length) {
167
- console.log('No wizards selected.');
172
+ log('No wizards selected.');
168
173
  return;
169
174
  }
170
175
 
@@ -180,16 +185,16 @@ async function pullPbEntries(token, config) {
180
185
  if (res.newStatus) config.workspace[idx].status = res.newStatus;
181
186
  }
182
187
  const note = res.diffs.length ? ` (WARNING: ${res.diffs.length} round-trip diff(s))` : '';
183
- console.log(` ${entry.name} → refreshed${note}`);
188
+ log(` ${entry.name} → refreshed${note}`);
184
189
  }
185
190
  writeConfig(config);
186
- console.log(`\nPulled ${selected.length} wizard(s). Local backups in .backup/${backupTs}/`);
191
+ log(`\nPulled ${selected.length} wizard(s). Local backups in .backup/${backupTs}/`);
187
192
  }
188
193
 
189
194
  // Refresh tracked long-running processes from upstream. Same classification
190
195
  // concern as pullPbEntries, but entries are located by NAME (the tabulator id
191
196
  // changes on every save/version — never a stable key).
192
- async function pullLrpEntries(token, config) {
197
+ async function pullLrpEntries(token, config, opts = {}) {
193
198
  const entries = config.workspace.filter((e) => e.object_type === 'long_running_process');
194
199
  if (!entries.length) return;
195
200
  if (!process.env.IMPORTEXPORT_URL)
@@ -197,7 +202,7 @@ async function pullLrpEntries(token, config) {
197
202
  'IMPORTEXPORT_URL is not configured. Run `prbot init` or set it in agrippa.yaml.'
198
203
  );
199
204
 
200
- console.log('Checking long-running processes...');
205
+ log('Checking long-running processes...');
201
206
  const classified = [];
202
207
  for (const entry of entries) {
203
208
  let upstream = null;
@@ -207,7 +212,7 @@ async function pullLrpEntries(token, config) {
207
212
  upstream = null;
208
213
  }
209
214
  if (!upstream) {
210
- console.warn(` ${entry.name}: could not fetch upstream, skipping`);
215
+ warn(` ${entry.name}: could not fetch upstream, skipping`);
211
216
  continue;
212
217
  }
213
218
  const localSemantic = localChecksum(projectReader(entry.path));
@@ -222,13 +227,13 @@ async function pullLrpEntries(token, config) {
222
227
 
223
228
  const changed = classified.filter((e) => e.status !== 'unchanged');
224
229
  if (!changed.length) {
225
- console.log('Long-running processes are up to date.');
230
+ log('Long-running processes are up to date.');
226
231
  return;
227
232
  }
228
233
 
229
- const selected = await selectEntries(changed, 'pull (overwrites local LRP files)');
234
+ const selected = await selectEntries(changed, 'pull (overwrites local LRP files)', opts);
230
235
  if (!selected.length) {
231
- console.log('No long-running processes selected.');
236
+ log('No long-running processes selected.');
232
237
  return;
233
238
  }
234
239
 
@@ -247,10 +252,10 @@ async function pullLrpEntries(token, config) {
247
252
  config.workspace[idx].status = res.newRow.status;
248
253
  }
249
254
  const note = res.diffs.length ? ` (WARNING: ${res.diffs.length} round-trip diff(s))` : '';
250
- console.log(` ${entry.name} → refreshed${note}`);
255
+ log(` ${entry.name} → refreshed${note}`);
251
256
  }
252
257
  writeConfig(config);
253
- console.log(
258
+ log(
254
259
  `\nPulled ${selected.length} long-running process(es). Local backups in .backup/${backupTs}/`
255
260
  );
256
261
  }
@@ -294,7 +299,7 @@ async function discoverNewPhases(token, ripUrl, config, changedWorkflowIds = new
294
299
  checksum_at_pull: computeChecksum(phase.code),
295
300
  name: `${wfName} / ${phase.name}`,
296
301
  });
297
- console.log(` new phase: ${filePath}`);
302
+ log(` new phase: ${filePath}`);
298
303
  newCount++;
299
304
  wfChanged = true;
300
305
  }
@@ -307,14 +312,14 @@ async function discoverNewPhases(token, ripUrl, config, changedWorkflowIds = new
307
312
  const structure = await describeWorkflow(token, ripUrl, wfId);
308
313
  writeWorkflowDoc(basePath, structure);
309
314
  } catch (err) {
310
- console.warn(` could not refresh workflow.yml for ${wfName}: ${err.message}`);
315
+ warn(` could not refresh workflow.yml for ${wfName}: ${err.message}`);
311
316
  }
312
317
  }
313
318
  }
314
319
 
315
320
  if (newCount) {
316
321
  writeConfig(config);
317
- console.log(`Added ${newCount} new phase(s) from tracked workflows.`);
322
+ log(`Added ${newCount} new phase(s) from tracked workflows.`);
318
323
  }
319
324
  }
320
325
 
@@ -343,18 +348,32 @@ async function fetchRemoteCode(token, ripUrl, workspace) {
343
348
  return map;
344
349
  }
345
350
 
346
- async function selectEntries(changed, verb, mode = 'pull') {
347
- const badgeFor = (status) => {
348
- if (mode === 'push') {
349
- return status === 'fast-forward' ? ' safe' : '⚠ conflict';
351
+ // `changed` only ever contains `fast-forward` and `conflict` entries (the
352
+ // caller already filtered out `unchanged`). `conflict` means local and remote
353
+ // have both diverged from the last-known-good baseline — applying it blindly
354
+ // can silently lose either side's work, so it is never preselected and is
355
+ // refused outright in `--non-interactive` mode instead of being silently
356
+ // skipped or applied.
357
+ async function selectEntries(changed, verb, opts = {}) {
358
+ const conflicts = changed.filter((e) => e.status === 'conflict');
359
+
360
+ if (opts.nonInteractive) {
361
+ if (conflicts.length) {
362
+ throw new Error(
363
+ `CONFLICT: refusing to ${verb} non-interactively — ${conflicts.length} resource(s) ` +
364
+ `in conflict: ${conflicts.map((e) => e.name).join(', ')}. Resolve interactively ` +
365
+ `or re-run once the conflicting side is reconciled.`
366
+ );
350
367
  }
351
- return status === 'fast-forward' ? '↑ safe' : '⚠ conflict';
352
- };
368
+ return changed;
369
+ }
370
+
371
+ const badgeFor = (status) => (status === 'fast-forward' ? '↑ safe' : '⚠ conflict');
353
372
 
354
373
  const choices = changed.map((e) => ({
355
374
  name: `${e.name} [${badgeFor(e.status)}]`,
356
375
  value: e,
357
- checked: true,
376
+ checked: e.status !== 'conflict',
358
377
  }));
359
378
 
360
379
  const { selected } = await inquirer.prompt([
@@ -1,8 +1,7 @@
1
1
  import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from 'fs';
2
2
  import { dirname, join } from 'path';
3
- import { computeChecksum } from '../lib/checksum.js';
4
3
  import { fetchUpstream } from '../lib/lrpApi.js';
5
- import { comparePayload, decompose, recompose, stableStringify } from '../lib/pbProject.js';
4
+ import { checksumOfPayload, comparePayload, decompose, recompose } from '../lib/pbProject.js';
6
5
  import { projectReader, writeProject } from '../lib/pbWorkspace.js';
7
6
 
8
7
  // Delete files under <baseDir>/scripts that are not in the fresh decompose
@@ -46,7 +45,7 @@ async function pullLrpEntry(token, entry, backupDir, backupTs) {
46
45
  const diffs = comparePayload(upstream.payload, rebuilt).filter((d) => !d.startsWith('pages:'));
47
46
 
48
47
  return {
49
- newChecksum: computeChecksum(stableStringify(rebuilt)),
48
+ newChecksum: checksumOfPayload(rebuilt),
50
49
  newRow: upstream.row,
51
50
  diffs,
52
51
  };
@@ -1,8 +1,7 @@
1
1
  import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from 'fs';
2
2
  import { dirname, join } from 'path';
3
- import { computeChecksum } from '../lib/checksum.js';
4
3
  import { getProcess } from '../lib/pbApi.js';
5
- import { comparePayload, decompose, recompose, stableStringify } from '../lib/pbProject.js';
4
+ import { checksumOfPayload, comparePayload, decompose, recompose } from '../lib/pbProject.js';
6
5
  import { projectReader, writeProject } from '../lib/pbWorkspace.js';
7
6
 
8
7
  // Delete files under <baseDir>/<sub> that are not in the fresh decompose map, so
@@ -44,7 +43,7 @@ async function pullPbEntry(token, entry, backupDir, backupTs) {
44
43
  const diffs = comparePayload(upstream, rebuilt);
45
44
 
46
45
  return {
47
- newChecksum: computeChecksum(stableStringify(rebuilt)),
46
+ newChecksum: checksumOfPayload(rebuilt),
48
47
  newUpdatedDate: upstream.updated_date,
49
48
  newStatus: upstream.status,
50
49
  diffs,