@go-labs-sg/bb 2.47.0 → 3.0.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 +116 -19
- package/command-manifest.json +2309 -233
- package/command-reference.md +283 -27
- package/dist/index.js +2397 -764
- package/package.json +2 -2
- package/role-aware-agent-guide.md +7 -0
package/dist/index.js
CHANGED
|
@@ -35,31 +35,31 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
35
35
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
36
36
|
var __require = import.meta.require;
|
|
37
37
|
|
|
38
|
-
// ../../../node_modules/.bun/dotenv@18.0.
|
|
38
|
+
// ../../../node_modules/.bun/dotenv@18.0.7/node_modules/dotenv/dist/index.cjs
|
|
39
39
|
var require_dist = __commonJS(function(exports, module) {
|
|
40
|
-
var
|
|
40
|
+
var k = (e, n) => () => {
|
|
41
41
|
try {
|
|
42
|
-
return
|
|
42
|
+
return n || e((n = { exports: {} }).exports, n), n.exports;
|
|
43
43
|
} catch (t) {
|
|
44
|
-
throw
|
|
44
|
+
throw n = 0, t;
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
|
-
var
|
|
47
|
+
var I = k((xe, U) => {
|
|
48
48
|
function G(e) {
|
|
49
49
|
return typeof e == "string" ? !["false", "0", "no", "off", ""].includes(e.toLowerCase()) : !!e;
|
|
50
50
|
}
|
|
51
|
-
function
|
|
52
|
-
let
|
|
51
|
+
function Y(e = process.env) {
|
|
52
|
+
let n = {};
|
|
53
53
|
for (let t of ["ENCODING", "PATH", "QUIET", "DEBUG", "OVERRIDE", "FAST"]) {
|
|
54
|
-
let
|
|
55
|
-
|
|
54
|
+
let o = e[`DOTENV_${t}`] != null ? e[`DOTENV_${t}`] : e[`DOTENV_CONFIG_${t}`];
|
|
55
|
+
o != null && (n[t.toLowerCase()] = t === "ENCODING" || t === "PATH" ? o : G(o));
|
|
56
56
|
}
|
|
57
|
-
return
|
|
57
|
+
return n;
|
|
58
58
|
}
|
|
59
|
-
U.exports = { parseBoolean: G, optionsFromEnv:
|
|
59
|
+
U.exports = { parseBoolean: G, optionsFromEnv: Y };
|
|
60
60
|
});
|
|
61
|
-
var N =
|
|
62
|
-
var
|
|
61
|
+
var N = k((ye, x) => {
|
|
62
|
+
var z = __require("fs"), S = __require("path"), Z = __require("os"), { URL: ee, fileURLToPath: te } = __require("url"), { parseBoolean: $, optionsFromEnv: B } = I(), re = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg, b = new Uint8Array(256);
|
|
63
63
|
for (let e = 48;e <= 57; e++)
|
|
64
64
|
b[e] = 1;
|
|
65
65
|
for (let e = 65;e <= 90; e++)
|
|
@@ -69,92 +69,92 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
69
69
|
b[45] = 1;
|
|
70
70
|
b[46] = 1;
|
|
71
71
|
b[95] = 1;
|
|
72
|
-
function
|
|
73
|
-
let
|
|
72
|
+
function ne(e) {
|
|
73
|
+
let n = {}, t = e.toString();
|
|
74
74
|
t = t.replace(/\r\n?/mg, `
|
|
75
75
|
`);
|
|
76
|
-
let
|
|
77
|
-
for (;(
|
|
78
|
-
let r =
|
|
76
|
+
let o;
|
|
77
|
+
for (;(o = re.exec(t)) != null; ) {
|
|
78
|
+
let r = o[1], s = o[2] || "";
|
|
79
79
|
s = s.trim();
|
|
80
80
|
let i = s[0];
|
|
81
81
|
s = s.replace(/^(['"`])([\s\S]*)\1$/mg, "$2"), i === '"' && (s = s.replace(/\\n/g, `
|
|
82
|
-
`), s = s.replace(/\\r/g, "\r")),
|
|
82
|
+
`), s = s.replace(/\\r/g, "\r")), n[r] = s;
|
|
83
83
|
}
|
|
84
|
-
return
|
|
84
|
+
return n;
|
|
85
85
|
}
|
|
86
86
|
function w(e) {
|
|
87
87
|
return e <= 32 ? e === 32 || e >= 9 && e <= 13 : e >= 160 && (e === 160 || e === 5760 || e >= 8192 && e <= 8202 || e === 8232 || e === 8233 || e === 8239 || e === 8287 || e === 12288 || e === 65279);
|
|
88
88
|
}
|
|
89
|
-
function
|
|
89
|
+
function q(e) {
|
|
90
90
|
return e === 10 || e === 8232 || e === 8233;
|
|
91
91
|
}
|
|
92
92
|
function oe(e) {
|
|
93
|
-
let
|
|
93
|
+
let n = {}, t = typeof e == "string" ? e : e.toString();
|
|
94
94
|
t.indexOf("\r") !== -1 && (t = t.replace(/\r\n?/g, `
|
|
95
95
|
`));
|
|
96
|
-
let
|
|
97
|
-
for (;r <
|
|
96
|
+
let o = t.length, r = 0;
|
|
97
|
+
for (;r < o; ) {
|
|
98
98
|
let s = t.charCodeAt(r);
|
|
99
|
-
for (;r <
|
|
99
|
+
for (;r < o && w(s); )
|
|
100
100
|
r++, s = t.charCodeAt(r);
|
|
101
|
-
if (r >=
|
|
101
|
+
if (r >= o)
|
|
102
102
|
break;
|
|
103
103
|
if (s === 35) {
|
|
104
|
-
for (;r <
|
|
104
|
+
for (;r < o && !q(t.charCodeAt(r)); )
|
|
105
105
|
r++;
|
|
106
106
|
continue;
|
|
107
107
|
}
|
|
108
108
|
let i = -1;
|
|
109
|
-
if (s === 101 && r + 6 <
|
|
109
|
+
if (s === 101 && r + 6 < o && t.charCodeAt(r + 1) === 120 && t.charCodeAt(r + 2) === 112 && t.charCodeAt(r + 3) === 111 && t.charCodeAt(r + 4) === 114 && t.charCodeAt(r + 5) === 116) {
|
|
110
110
|
let v = t.charCodeAt(r + 6);
|
|
111
111
|
if (w(v)) {
|
|
112
112
|
let u = r + 7;
|
|
113
|
-
for (;u <
|
|
113
|
+
for (;u < o && w(t.charCodeAt(u)); )
|
|
114
114
|
u++;
|
|
115
115
|
b[t.charCodeAt(u)] && (i = r + 6, r = u);
|
|
116
116
|
} else
|
|
117
117
|
s = t.charCodeAt(r);
|
|
118
118
|
}
|
|
119
119
|
let l = r, d = 0;
|
|
120
|
-
for (;r <
|
|
120
|
+
for (;r < o && (d = t.charCodeAt(r), b[d]); )
|
|
121
121
|
r++;
|
|
122
122
|
if (r === l) {
|
|
123
|
-
for (;r <
|
|
123
|
+
for (;r < o && !q(t.charCodeAt(r)); )
|
|
124
124
|
r++;
|
|
125
125
|
continue;
|
|
126
126
|
}
|
|
127
127
|
let p = t.slice(l, r), f = r;
|
|
128
|
-
if (r >=
|
|
128
|
+
if (r >= o && (d = 0), w(d))
|
|
129
129
|
do
|
|
130
|
-
r++, d = r <
|
|
130
|
+
r++, d = r < o ? t.charCodeAt(r) : 0;
|
|
131
131
|
while (w(d));
|
|
132
132
|
if (d === 61)
|
|
133
133
|
r++;
|
|
134
|
-
else if (d === 58 && r === f && r + 1 <
|
|
134
|
+
else if (d === 58 && r === f && r + 1 < o && w(t.charCodeAt(r + 1)))
|
|
135
135
|
r += 2;
|
|
136
136
|
else {
|
|
137
|
-
for (r = i === -1 ? f : i;r <
|
|
137
|
+
for (r = i === -1 ? f : i;r < o && !q(t.charCodeAt(r)); )
|
|
138
138
|
r++;
|
|
139
139
|
continue;
|
|
140
140
|
}
|
|
141
141
|
let c = r, a = r;
|
|
142
|
-
for (;a <
|
|
142
|
+
for (;a < o && w(t.charCodeAt(a)); )
|
|
143
143
|
a++;
|
|
144
|
-
let
|
|
145
|
-
if (
|
|
144
|
+
let h = t.charCodeAt(a), g, y = false;
|
|
145
|
+
if (h === 39 || h === 34 || h === 96) {
|
|
146
146
|
let v = t[a], u = t.indexOf(v, a + 1), m = -1, C = -1;
|
|
147
147
|
for (;u !== -1; ) {
|
|
148
|
-
let
|
|
149
|
-
for (;E <
|
|
148
|
+
let O = t.charCodeAt(u - 1) === 92, E = u + 1;
|
|
149
|
+
for (;E < o && !q(t.charCodeAt(E)) && w(t.charCodeAt(E)); )
|
|
150
150
|
E++;
|
|
151
|
-
if ((E ===
|
|
151
|
+
if ((E === o || q(t.charCodeAt(E)) || t.charCodeAt(E) === 35) && (m = u, C = E), !O)
|
|
152
152
|
break;
|
|
153
153
|
u = t.indexOf(v, u + 1);
|
|
154
154
|
}
|
|
155
155
|
if (m !== -1) {
|
|
156
|
-
if (
|
|
157
|
-
for (;r <
|
|
156
|
+
if (g = t.slice(a + 1, m), r = C, t.charCodeAt(r) === 35)
|
|
157
|
+
for (;r < o && !q(t.charCodeAt(r)); )
|
|
158
158
|
r++;
|
|
159
159
|
y = true;
|
|
160
160
|
}
|
|
@@ -162,9 +162,9 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
162
162
|
if (!y) {
|
|
163
163
|
let v = t.indexOf(`
|
|
164
164
|
`, c);
|
|
165
|
-
v === -1 && (v =
|
|
165
|
+
v === -1 && (v = o);
|
|
166
166
|
let u;
|
|
167
|
-
if (
|
|
167
|
+
if (o < 4096)
|
|
168
168
|
u = t.indexOf("#", c), (u === -1 || u > v) && (u = v);
|
|
169
169
|
else
|
|
170
170
|
for (u = c;u < v && t.charCodeAt(u) !== 35; )
|
|
@@ -174,38 +174,41 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
174
174
|
m++;
|
|
175
175
|
for (;C > m && w(t.charCodeAt(C - 1)); )
|
|
176
176
|
C--;
|
|
177
|
-
let
|
|
178
|
-
if (C - m >= 2 && (
|
|
179
|
-
for (;r <
|
|
177
|
+
let O = t.charCodeAt(m);
|
|
178
|
+
if (C - m >= 2 && (O === 39 || O === 34 || O === 96) && t.charCodeAt(C - 1) === O ? g = t.slice(m + 1, C - 1) : g = t.slice(m, C), r = u, u < v)
|
|
179
|
+
for (;r < o && !q(t.charCodeAt(r)); )
|
|
180
180
|
r++;
|
|
181
181
|
}
|
|
182
|
-
|
|
183
|
-
`).replace(/\\r/g, "\r")),
|
|
182
|
+
h === 34 && (y || a < r) && g.indexOf("\\") !== -1 && (g = g.replace(/\\n/g, `
|
|
183
|
+
`).replace(/\\r/g, "\r")), n[p] = g;
|
|
184
184
|
}
|
|
185
|
-
return
|
|
185
|
+
return n;
|
|
186
186
|
}
|
|
187
|
-
function
|
|
188
|
-
return
|
|
187
|
+
function se(e, n) {
|
|
188
|
+
return n && $(n.fast) ? oe(e) : ne(e);
|
|
189
189
|
}
|
|
190
190
|
function T(e) {
|
|
191
191
|
console.log(`\u2506 ${e}`);
|
|
192
192
|
}
|
|
193
|
-
function
|
|
193
|
+
function ie(e) {
|
|
194
194
|
console.error(`\u25C7 ${e}`);
|
|
195
195
|
}
|
|
196
196
|
function V(e) {
|
|
197
|
-
return e[0] === "~" ?
|
|
197
|
+
return e[0] === "~" ? S.join(Z.homedir(), e.slice(1)) : e;
|
|
198
198
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
199
|
+
function ce(e = {}) {
|
|
200
|
+
let n = { ...e };
|
|
201
|
+
for (let t of Object.keys(n))
|
|
202
|
+
n[t] === undefined && delete n[t];
|
|
203
|
+
return { ...B(), ...n };
|
|
201
204
|
}
|
|
202
|
-
function
|
|
203
|
-
e =
|
|
204
|
-
let
|
|
205
|
-
e && e.processEnv != null && (
|
|
206
|
-
let r =
|
|
205
|
+
function ae(e) {
|
|
206
|
+
e = ce(e);
|
|
207
|
+
let n = S.resolve(process.cwd(), ".env"), t = "utf8", o = process.env;
|
|
208
|
+
e && e.processEnv != null && (o = e.processEnv);
|
|
209
|
+
let r = $(e && e.debug);
|
|
207
210
|
e && e.encoding ? t = e.encoding : r && T("no encoding is specified (UTF-8 is used by default)");
|
|
208
|
-
let s = [
|
|
211
|
+
let s = [n];
|
|
209
212
|
if (e && e.path)
|
|
210
213
|
if (!Array.isArray(e.path))
|
|
211
214
|
s = [V(e.path)];
|
|
@@ -217,106 +220,106 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
217
220
|
let i, l = {}, d = { fast: e.fast };
|
|
218
221
|
for (let c of s)
|
|
219
222
|
try {
|
|
220
|
-
let a = A.parse(
|
|
223
|
+
let a = A.parse(z.readFileSync(c, { encoding: t }), d);
|
|
221
224
|
A.populate(l, a, e);
|
|
222
225
|
} catch (a) {
|
|
223
226
|
r && T(`failed to load ${c} ${a.message}`), i = a;
|
|
224
227
|
}
|
|
225
|
-
let p = A.populate(
|
|
228
|
+
let p = A.populate(o, l, e), f = $(Object.prototype.hasOwnProperty.call(e, "quiet") ? e.quiet : B(o).quiet);
|
|
226
229
|
if (r || !f) {
|
|
227
230
|
let c = Object.keys(p).length, a = [];
|
|
228
|
-
for (let
|
|
231
|
+
for (let h of s)
|
|
229
232
|
try {
|
|
230
|
-
let
|
|
231
|
-
a.push(
|
|
232
|
-
} catch (
|
|
233
|
-
r && T(`failed to load ${
|
|
233
|
+
let g = S.relative(process.cwd(), h instanceof ee ? te(h) : h);
|
|
234
|
+
a.push(g);
|
|
235
|
+
} catch (g) {
|
|
236
|
+
r && T(`failed to load ${h} ${g.message}`), i = g;
|
|
234
237
|
}
|
|
235
|
-
|
|
238
|
+
ie(`injected env (${c}) from ${a.join(",")}`);
|
|
236
239
|
}
|
|
237
240
|
return i ? { parsed: l, error: i } : { parsed: l };
|
|
238
241
|
}
|
|
239
|
-
function
|
|
242
|
+
function le(e) {
|
|
240
243
|
return A.configDotenv(e);
|
|
241
244
|
}
|
|
242
|
-
function
|
|
243
|
-
let
|
|
244
|
-
if (e === null || typeof e != "object" ||
|
|
245
|
+
function fe(e, n, t = {}) {
|
|
246
|
+
let o = $(t && t.debug), r = $(t && t.override), s = {};
|
|
247
|
+
if (e === null || typeof e != "object" || n === null || typeof n != "object") {
|
|
245
248
|
let i = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
246
249
|
throw i.code = "OBJECT_REQUIRED", i;
|
|
247
250
|
}
|
|
248
|
-
for (let i of Object.keys(
|
|
249
|
-
Object.prototype.hasOwnProperty.call(e, i) ? (r === true && (e[i] =
|
|
251
|
+
for (let i of Object.keys(n))
|
|
252
|
+
Object.prototype.hasOwnProperty.call(e, i) ? (r === true && (e[i] = n[i], s[i] = n[i]), o && T(r === true ? `"${i}" is already defined and WAS overwritten` : `"${i}" is already defined and was NOT overwritten`)) : (e[i] = n[i], s[i] = n[i]);
|
|
250
253
|
return s;
|
|
251
254
|
}
|
|
252
|
-
var A = { configDotenv:
|
|
255
|
+
var A = { configDotenv: ae, config: le, parse: se, populate: fe };
|
|
253
256
|
x.exports.configDotenv = A.configDotenv;
|
|
254
257
|
x.exports.config = A.config;
|
|
255
258
|
x.exports.parse = A.parse;
|
|
256
259
|
x.exports.populate = A.populate;
|
|
257
260
|
x.exports = A;
|
|
258
261
|
});
|
|
259
|
-
var M =
|
|
260
|
-
var _ = __require("child_process"),
|
|
261
|
-
function
|
|
262
|
-
let
|
|
263
|
-
for (let
|
|
264
|
-
if (
|
|
262
|
+
var M = k((Te, W) => {
|
|
263
|
+
var _ = __require("child_process"), ue = __require("fs"), L = __require("path");
|
|
264
|
+
function de(e) {
|
|
265
|
+
let n = ['"'], t = 0;
|
|
266
|
+
for (let o of e) {
|
|
267
|
+
if (o === "\\") {
|
|
265
268
|
t++;
|
|
266
269
|
continue;
|
|
267
270
|
}
|
|
268
|
-
|
|
271
|
+
o === '"' ? n.push("\\".repeat(t * 2 + 1), '"') : n.push("\\".repeat(t), o), t = 0;
|
|
269
272
|
}
|
|
270
|
-
return
|
|
273
|
+
return n.push("\\".repeat(t * 2), '"'), n.join("");
|
|
271
274
|
}
|
|
272
|
-
function H(e,
|
|
273
|
-
for (let t = 0;t <
|
|
274
|
-
let
|
|
275
|
+
function H(e, n = 1) {
|
|
276
|
+
for (let t = 0;t < n; t++) {
|
|
277
|
+
let o = [];
|
|
275
278
|
for (let r of e) {
|
|
276
279
|
let s = r.charCodeAt(0), i = s >= 48 && s <= 57 || s >= 65 && s <= 90 || s >= 97 && s <= 122, l = "\\/:._-".includes(r);
|
|
277
|
-
!i && !l && s < 128 &&
|
|
280
|
+
!i && !l && s < 128 && o.push("^"), o.push(r);
|
|
278
281
|
}
|
|
279
|
-
e =
|
|
282
|
+
e = o.join("");
|
|
280
283
|
}
|
|
281
284
|
return e;
|
|
282
285
|
}
|
|
283
|
-
function P(e,
|
|
284
|
-
let t = Object.keys(e).reverse().find((
|
|
286
|
+
function P(e, n) {
|
|
287
|
+
let t = Object.keys(e).reverse().find((o) => o.toUpperCase() === n);
|
|
285
288
|
return t === undefined ? undefined : e[t];
|
|
286
289
|
}
|
|
287
|
-
function
|
|
288
|
-
let
|
|
290
|
+
function pe(e, n, t) {
|
|
291
|
+
let o = (P(n, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean), s = o.some((l) => e.toLowerCase().endsWith(l.toLowerCase())) ? ["", ...o] : [...o, ""], i = /[\\/]/.test(e) ? [t] : [t, ...(P(n, "PATH") || "").split(";")];
|
|
289
292
|
for (let l of i)
|
|
290
293
|
for (let d of s) {
|
|
291
294
|
let p = L.resolve(t, l.replace(/^"|"$/g, ""), e + d);
|
|
292
295
|
try {
|
|
293
|
-
if (
|
|
296
|
+
if (ue.statSync(p).isFile())
|
|
294
297
|
return p;
|
|
295
298
|
} catch {}
|
|
296
299
|
}
|
|
297
300
|
}
|
|
298
|
-
function
|
|
301
|
+
function he(e, n, t) {
|
|
299
302
|
if (process.platform !== "win32")
|
|
300
|
-
return _.spawn(e,
|
|
301
|
-
let
|
|
303
|
+
return _.spawn(e, n, t);
|
|
304
|
+
let o = t.env || process.env, r = pe(e, o, t.cwd || process.cwd());
|
|
302
305
|
if (r && /\.(?:exe|com)$/i.test(r))
|
|
303
|
-
return _.spawn(r,
|
|
306
|
+
return _.spawn(r, n, t);
|
|
304
307
|
let s = /\.(?:bat|cmd)$/i.test(r || e), i = [H(L.normalize(r || e))];
|
|
305
|
-
for (let d of
|
|
306
|
-
i.push(H(
|
|
308
|
+
for (let d of n)
|
|
309
|
+
i.push(H(de(d), s ? 2 : 1));
|
|
307
310
|
let l = i.join(" ");
|
|
308
|
-
return _.spawn(P(
|
|
311
|
+
return _.spawn(P(o, "COMSPEC") || "cmd.exe", ["/d", "/v:off", "/s", "/c", `"${l}"`], { ...t, windowsVerbatimArguments: true });
|
|
309
312
|
}
|
|
310
|
-
W.exports =
|
|
313
|
+
W.exports = he;
|
|
311
314
|
});
|
|
312
|
-
var
|
|
313
|
-
var
|
|
314
|
-
function
|
|
315
|
+
var X = k(($e, F) => {
|
|
316
|
+
var ge = __require("fs"), me = __require("os"), Q = __require("path"), ve = __require("child_process"), Ce = M(), R = N(), { optionsFromEnv: J } = I();
|
|
317
|
+
function D() {
|
|
315
318
|
console.log(["Usage: dotenv run [--help] [-q|--quiet] [--debug] [--override] [--fast] [-f|--file <paths>] [--] <command> [args...]", "", "Run a command with environment variables from a .env file.", "Place dotenv options before the command; all following arguments go to the command.", "", "Options:", " -f, --file <paths> .env paths, comma-separated or repeated (default: .env)", " -q, --quiet suppress the injected env message", " --debug enable debug logging", " --override override existing environment variables", " --fast use the faster character-scanner parser", "", "Environment variables (DOTENV_CONFIG_* names remain as fallbacks):", " DOTENV_PATH, DOTENV_ENCODING, DOTENV_QUIET,", " DOTENV_DEBUG, DOTENV_OVERRIDE,", " DOTENV_FAST"].join(`
|
|
316
319
|
`));
|
|
317
320
|
}
|
|
318
321
|
function we(e) {
|
|
319
|
-
let
|
|
322
|
+
let n = [], t = false, o, r, s, i, l = -1;
|
|
320
323
|
for (let p = 0;p < e.length; p++) {
|
|
321
324
|
let f = e[p];
|
|
322
325
|
if (f === "--") {
|
|
@@ -326,7 +329,7 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
326
329
|
if (f === "--help" || f === "-h")
|
|
327
330
|
return { help: true };
|
|
328
331
|
if (f === "--quiet" || f === "-q") {
|
|
329
|
-
|
|
332
|
+
o = true;
|
|
330
333
|
continue;
|
|
331
334
|
}
|
|
332
335
|
if (f === "--debug") {
|
|
@@ -342,13 +345,13 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
342
345
|
continue;
|
|
343
346
|
}
|
|
344
347
|
if (f === "-f" || f === "--file" || f.startsWith("-f=") || f.startsWith("--file=")) {
|
|
345
|
-
let c = f.indexOf("="), a = c === -1 ? f : f.slice(0, c),
|
|
346
|
-
if (!
|
|
348
|
+
let c = f.indexOf("="), a = c === -1 ? f : f.slice(0, c), h = c === -1 ? e[++p] : f.slice(c + 1);
|
|
349
|
+
if (!h || h === "--")
|
|
347
350
|
return { error: `${a} requires a path` };
|
|
348
|
-
let
|
|
349
|
-
if (
|
|
351
|
+
let g = h.split(",").map((y) => y.trim()).filter(Boolean);
|
|
352
|
+
if (g.length === 0)
|
|
350
353
|
return { error: `${a} requires a path` };
|
|
351
|
-
|
|
354
|
+
n.push(...g), t = true;
|
|
352
355
|
continue;
|
|
353
356
|
}
|
|
354
357
|
if (f.startsWith("-"))
|
|
@@ -357,68 +360,68 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
357
360
|
break;
|
|
358
361
|
}
|
|
359
362
|
let d = l === -1 ? [] : e.slice(l);
|
|
360
|
-
return { paths:
|
|
363
|
+
return { paths: n, pathSet: t, quiet: o, debug: r, override: s, fast: i, command: d };
|
|
361
364
|
}
|
|
362
365
|
function Ae(e) {
|
|
363
|
-
return e[0] === "~" ? Q.join(
|
|
366
|
+
return e[0] === "~" ? Q.join(me.homedir(), e.slice(1)) : e;
|
|
364
367
|
}
|
|
365
368
|
function Ee(e) {
|
|
366
|
-
let
|
|
367
|
-
return
|
|
369
|
+
let n = J(), t = { encoding: n.encoding || "utf8", quiet: n.quiet, debug: n.debug === true, override: n.override === true, fast: n.fast === true, paths: [".env"], defaultPath: true };
|
|
370
|
+
return n.path != null && (t.paths = [n.path], t.defaultPath = false), e.pathSet && (t.paths = e.paths, t.defaultPath = false), e.quiet != null && (t.quiet = e.quiet), e.debug != null && (t.debug = e.debug), e.override != null && (t.override = e.override), e.fast != null && (t.fast = e.fast), t;
|
|
368
371
|
}
|
|
369
372
|
function be(e) {
|
|
370
|
-
let
|
|
373
|
+
let n = {}, t = [], o = { override: e.override, debug: e.debug };
|
|
371
374
|
for (let s of e.paths) {
|
|
372
375
|
let i = Q.resolve(process.cwd(), Ae(s));
|
|
373
376
|
try {
|
|
374
|
-
let l = R.parse(
|
|
375
|
-
R.populate(
|
|
377
|
+
let l = R.parse(ge.readFileSync(i, { encoding: e.encoding }), { fast: e.fast });
|
|
378
|
+
R.populate(n, l, o), t.push(s);
|
|
376
379
|
} catch (l) {
|
|
377
380
|
if (e.debug && console.log(`\u2506 failed to load ${s} ${l.message}`), !(e.defaultPath && l.code === "ENOENT"))
|
|
378
381
|
throw l;
|
|
379
382
|
}
|
|
380
383
|
}
|
|
381
|
-
return { injected: R.populate(process.env,
|
|
384
|
+
return { injected: R.populate(process.env, n, o), loadedPaths: t };
|
|
382
385
|
}
|
|
383
|
-
function
|
|
384
|
-
let
|
|
385
|
-
if (
|
|
386
|
-
|
|
386
|
+
function K(e) {
|
|
387
|
+
let n = e[0];
|
|
388
|
+
if (n === "--help" || n === "-h") {
|
|
389
|
+
D();
|
|
387
390
|
return;
|
|
388
391
|
}
|
|
389
|
-
if (
|
|
390
|
-
|
|
392
|
+
if (n !== "run") {
|
|
393
|
+
D(), process.exitCode = 1;
|
|
391
394
|
return;
|
|
392
395
|
}
|
|
393
396
|
let t = we(e.slice(1));
|
|
394
397
|
if (t.help) {
|
|
395
|
-
|
|
398
|
+
D();
|
|
396
399
|
return;
|
|
397
400
|
}
|
|
398
401
|
if (t.error) {
|
|
399
|
-
console.error(`dotenv: ${t.error}`),
|
|
402
|
+
console.error(`dotenv: ${t.error}`), D(), process.exitCode = 1;
|
|
400
403
|
return;
|
|
401
404
|
}
|
|
402
405
|
if (t.command.length === 0) {
|
|
403
|
-
|
|
406
|
+
D(), process.exitCode = 1;
|
|
404
407
|
return;
|
|
405
408
|
}
|
|
406
|
-
let
|
|
409
|
+
let o = Ee(t);
|
|
407
410
|
try {
|
|
408
|
-
let c = be(
|
|
409
|
-
if (!
|
|
410
|
-
let
|
|
411
|
-
c.loadedPaths.length > 0 && (
|
|
411
|
+
let c = be(o);
|
|
412
|
+
if (!(o.quiet == null ? J().quiet : o.quiet)) {
|
|
413
|
+
let h = `\u25C7 injected env (${Object.keys(c.injected).length})`;
|
|
414
|
+
c.loadedPaths.length > 0 && (h += ` from ${c.loadedPaths.join(", ")}`), console.error(h);
|
|
412
415
|
}
|
|
413
416
|
} catch (c) {
|
|
414
417
|
console.error(`dotenv: ${c.message}`), process.exitCode = 1;
|
|
415
418
|
return;
|
|
416
419
|
}
|
|
417
|
-
let r = !!process.stdin.isTTY, s = process.platform !== "win32" && !r, i =
|
|
420
|
+
let r = !!process.stdin.isTTY, s = process.platform !== "win32" && !r, i = Ce(t.command[0], t.command.slice(1), { stdio: "inherit", detached: s }), l = new Map, d = 0;
|
|
418
421
|
function p(c) {
|
|
419
422
|
if (!(!i.pid || i.exitCode !== null || i.signalCode !== null)) {
|
|
420
423
|
if (process.platform === "win32") {
|
|
421
|
-
|
|
424
|
+
ve.spawnSync("taskkill", ["/pid", String(i.pid), "/T", "/F"], { stdio: "ignore" });
|
|
422
425
|
return;
|
|
423
426
|
}
|
|
424
427
|
try {
|
|
@@ -453,16 +456,16 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
453
456
|
f(), typeof c == "number" ? process.exit(c) : (setInterval(() => {}, 1000), process.kill(process.pid, a));
|
|
454
457
|
});
|
|
455
458
|
}
|
|
456
|
-
F.exports =
|
|
457
|
-
F === __require.main &&
|
|
459
|
+
F.exports = K;
|
|
460
|
+
F === __require.main && K(process.argv.slice(2));
|
|
458
461
|
});
|
|
459
|
-
var
|
|
460
|
-
var
|
|
461
|
-
module.exports =
|
|
462
|
-
module.exports.config =
|
|
463
|
-
module.exports.configDotenv =
|
|
464
|
-
module.exports.parse =
|
|
465
|
-
module.exports.populate =
|
|
462
|
+
var j = N();
|
|
463
|
+
var qe = X();
|
|
464
|
+
module.exports = j;
|
|
465
|
+
module.exports.config = j.config;
|
|
466
|
+
module.exports.configDotenv = j.configDotenv;
|
|
467
|
+
module.exports.parse = j.parse;
|
|
468
|
+
module.exports.populate = j.populate;
|
|
466
469
|
});
|
|
467
470
|
|
|
468
471
|
// src/load-env.ts
|
|
@@ -6716,6 +6719,155 @@ var logoutCliSession = async ({
|
|
|
6716
6719
|
// src/cli.ts
|
|
6717
6720
|
import { readFileSync } from "fs";
|
|
6718
6721
|
|
|
6722
|
+
// ../utils/src/data-table-sort-keys.ts
|
|
6723
|
+
var INVENTORY_SORT_IDS = [
|
|
6724
|
+
"itemCategory",
|
|
6725
|
+
"category",
|
|
6726
|
+
"supplier",
|
|
6727
|
+
"cost",
|
|
6728
|
+
"name",
|
|
6729
|
+
"createdAt",
|
|
6730
|
+
"updatedAt"
|
|
6731
|
+
];
|
|
6732
|
+
var ITEM_CATEGORY_SORT_IDS = [
|
|
6733
|
+
"name",
|
|
6734
|
+
"itemCount",
|
|
6735
|
+
"createdAt",
|
|
6736
|
+
"createdBy"
|
|
6737
|
+
];
|
|
6738
|
+
|
|
6739
|
+
// ../db/src/generated/prisma/enums.ts
|
|
6740
|
+
var EstimationMode = {
|
|
6741
|
+
MICRO: "MICRO",
|
|
6742
|
+
MANPOWER_SPECIFIED: "MANPOWER_SPECIFIED"
|
|
6743
|
+
};
|
|
6744
|
+
var ProjectStatus = {
|
|
6745
|
+
PITCH: "PITCH",
|
|
6746
|
+
WON: "WON",
|
|
6747
|
+
COMPLETED: "COMPLETED",
|
|
6748
|
+
RECONCILED: "RECONCILED",
|
|
6749
|
+
LOST: "LOST"
|
|
6750
|
+
};
|
|
6751
|
+
var BudgetStatus = {
|
|
6752
|
+
DRAFT: "DRAFT",
|
|
6753
|
+
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6754
|
+
APPROVED: "APPROVED",
|
|
6755
|
+
REJECTED: "REJECTED",
|
|
6756
|
+
ESTIMATE_CREATED: "ESTIMATE_CREATED",
|
|
6757
|
+
ESTIMATE_SENT: "ESTIMATE_SENT",
|
|
6758
|
+
ESTIMATE_ACCEPTED: "ESTIMATE_ACCEPTED",
|
|
6759
|
+
ESTIMATE_REJECTED: "ESTIMATE_REJECTED",
|
|
6760
|
+
ESTIMATE_CLOSED: "ESTIMATE_CLOSED"
|
|
6761
|
+
};
|
|
6762
|
+
var ApprovalStatus = {
|
|
6763
|
+
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6764
|
+
APPROVED: "APPROVED",
|
|
6765
|
+
REJECTED: "REJECTED",
|
|
6766
|
+
SUPERSEDED: "SUPERSEDED"
|
|
6767
|
+
};
|
|
6768
|
+
var ApprovalType = {
|
|
6769
|
+
BUDGET: "BUDGET",
|
|
6770
|
+
SUPPLIER: "SUPPLIER",
|
|
6771
|
+
BILL: "BILL",
|
|
6772
|
+
CUSTOMER_INVOICE: "CUSTOMER_INVOICE",
|
|
6773
|
+
QUOTATION: "QUOTATION"
|
|
6774
|
+
};
|
|
6775
|
+
var ErrorSeverity = {
|
|
6776
|
+
LOW: "LOW",
|
|
6777
|
+
MEDIUM: "MEDIUM",
|
|
6778
|
+
HIGH: "HIGH",
|
|
6779
|
+
CRITICAL: "CRITICAL"
|
|
6780
|
+
};
|
|
6781
|
+
var ErrorStatus = {
|
|
6782
|
+
UNRESOLVED: "UNRESOLVED",
|
|
6783
|
+
INVESTIGATING: "INVESTIGATING",
|
|
6784
|
+
RESOLVED: "RESOLVED",
|
|
6785
|
+
IGNORED: "IGNORED"
|
|
6786
|
+
};
|
|
6787
|
+
var CustomerInvoiceBatchStatus = {
|
|
6788
|
+
CREATING: "CREATING",
|
|
6789
|
+
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6790
|
+
APPROVED: "APPROVED",
|
|
6791
|
+
REJECTED_VOIDED: "REJECTED_VOIDED",
|
|
6792
|
+
EXPIRED_VOIDED: "EXPIRED_VOIDED",
|
|
6793
|
+
PARTIAL_QBO_FAILURE: "PARTIAL_QBO_FAILURE"
|
|
6794
|
+
};
|
|
6795
|
+
var CustomerInvoiceStatus = {
|
|
6796
|
+
CREATED_IN_QBO: "CREATED_IN_QBO",
|
|
6797
|
+
APPROVED: "APPROVED",
|
|
6798
|
+
SENT: "SENT",
|
|
6799
|
+
PAID: "PAID",
|
|
6800
|
+
VOIDED: "VOIDED",
|
|
6801
|
+
QBO_SYNC_ERROR: "QBO_SYNC_ERROR"
|
|
6802
|
+
};
|
|
6803
|
+
var BillStatus = {
|
|
6804
|
+
DRAFT: "DRAFT",
|
|
6805
|
+
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6806
|
+
CHECKED: "CHECKED",
|
|
6807
|
+
APPROVED: "APPROVED",
|
|
6808
|
+
PAID: "PAID",
|
|
6809
|
+
REJECTED: "REJECTED"
|
|
6810
|
+
};
|
|
6811
|
+
|
|
6812
|
+
// ../utils/src/filter-enums.ts
|
|
6813
|
+
var ExtendedApprovalStatus = {
|
|
6814
|
+
...ApprovalStatus,
|
|
6815
|
+
ALL: "ALL"
|
|
6816
|
+
};
|
|
6817
|
+
var ExtendedApprovalType = {
|
|
6818
|
+
...ApprovalType,
|
|
6819
|
+
ALL: "ALL"
|
|
6820
|
+
};
|
|
6821
|
+
var ExtendedProjectStatus = {
|
|
6822
|
+
...ProjectStatus,
|
|
6823
|
+
ALL: "ALL"
|
|
6824
|
+
};
|
|
6825
|
+
var ExtendedBudgetStatus = {
|
|
6826
|
+
...BudgetStatus,
|
|
6827
|
+
ALL: "ALL"
|
|
6828
|
+
};
|
|
6829
|
+
var ExtendedBillStatus = {
|
|
6830
|
+
...BillStatus,
|
|
6831
|
+
ALL: "ALL"
|
|
6832
|
+
};
|
|
6833
|
+
var ExtendedEstimationMode = {
|
|
6834
|
+
...EstimationMode,
|
|
6835
|
+
ALL: "ALL"
|
|
6836
|
+
};
|
|
6837
|
+
var BudgetRole = {
|
|
6838
|
+
ALL: "ALL",
|
|
6839
|
+
BD: "BD",
|
|
6840
|
+
CREATOR: "CREATOR",
|
|
6841
|
+
INSIDE_SALES: "INSIDE_SALES"
|
|
6842
|
+
};
|
|
6843
|
+
var Deals = {
|
|
6844
|
+
ALL: "ALL",
|
|
6845
|
+
SUCCESSFUL: "SUCCESSFUL",
|
|
6846
|
+
LOST: "LOST"
|
|
6847
|
+
};
|
|
6848
|
+
var TimeFrame = {
|
|
6849
|
+
ALL: "ALL",
|
|
6850
|
+
LAST_YEAR: "LAST_YEAR",
|
|
6851
|
+
LAST_6_MONTHS: "LAST_6_MONTHS",
|
|
6852
|
+
LAST_3_MONTHS: "LAST_3_MONTHS",
|
|
6853
|
+
CUSTOM: "CUSTOM"
|
|
6854
|
+
};
|
|
6855
|
+
var ChartTimeFrame = {
|
|
6856
|
+
LAST_30_DAYS: "last_30_days",
|
|
6857
|
+
LAST_3_MONTHS: "last_3_months",
|
|
6858
|
+
LAST_6_MONTHS: "last_6_months",
|
|
6859
|
+
LAST_1_YEAR: "last_1_year",
|
|
6860
|
+
ALL_TIME: "all_time"
|
|
6861
|
+
};
|
|
6862
|
+
var ExtendedErrorSeverity = {
|
|
6863
|
+
ALL: "ALL",
|
|
6864
|
+
...ErrorSeverity
|
|
6865
|
+
};
|
|
6866
|
+
var ExtendedErrorStatus = {
|
|
6867
|
+
ALL: "ALL",
|
|
6868
|
+
...ErrorStatus
|
|
6869
|
+
};
|
|
6870
|
+
|
|
6719
6871
|
// src/cli-trace.ts
|
|
6720
6872
|
var cliQuietSession = false;
|
|
6721
6873
|
var setCliQuiet = (quiet) => {
|
|
@@ -6737,6 +6889,7 @@ var SENSITIVE_FLAG = new Set([
|
|
|
6737
6889
|
"authorization"
|
|
6738
6890
|
]);
|
|
6739
6891
|
var SENSITIVE_TRACE_FIELD = new Set([
|
|
6892
|
+
"secret",
|
|
6740
6893
|
"paymentproof",
|
|
6741
6894
|
"paymentproofattachments",
|
|
6742
6895
|
"paymentproofpath",
|
|
@@ -6754,6 +6907,14 @@ var sanitizeValueForTrace = (value, seen = new WeakSet) => {
|
|
|
6754
6907
|
if (Array.isArray(value)) {
|
|
6755
6908
|
return value.map((item) => sanitizeValueForTrace(item, seen));
|
|
6756
6909
|
}
|
|
6910
|
+
if (value instanceof Error) {
|
|
6911
|
+
return sanitizeValueForTrace({
|
|
6912
|
+
...value,
|
|
6913
|
+
name: value.name,
|
|
6914
|
+
message: value.message,
|
|
6915
|
+
stack: value.stack
|
|
6916
|
+
}, seen);
|
|
6917
|
+
}
|
|
6757
6918
|
const prototype = Object.getPrototypeOf(value);
|
|
6758
6919
|
if (prototype !== Object.prototype && prototype !== null)
|
|
6759
6920
|
return value;
|
|
@@ -6776,9 +6937,8 @@ var sanitizeFlagsForTrace = (flags) => {
|
|
|
6776
6937
|
};
|
|
6777
6938
|
var consumeCliQuietFlags = (flags) => {
|
|
6778
6939
|
const fromEnv = process.env.BB_CLI_QUIET === "1";
|
|
6779
|
-
const fromFlags = flags.quiet === true
|
|
6940
|
+
const fromFlags = flags.quiet === true;
|
|
6780
6941
|
delete flags.quiet;
|
|
6781
|
-
delete flags.q;
|
|
6782
6942
|
return fromEnv || fromFlags;
|
|
6783
6943
|
};
|
|
6784
6944
|
var logCliAction = (record) => {
|
|
@@ -6864,7 +7024,7 @@ var api2 = new Proxy({}, {
|
|
|
6864
7024
|
});
|
|
6865
7025
|
|
|
6866
7026
|
// src/prisma-enums.ts
|
|
6867
|
-
var
|
|
7027
|
+
var ProjectStatus2 = {
|
|
6868
7028
|
PITCH: "PITCH",
|
|
6869
7029
|
WON: "WON",
|
|
6870
7030
|
COMPLETED: "COMPLETED",
|
|
@@ -6878,7 +7038,7 @@ var SupplierQuotationStatus = {
|
|
|
6878
7038
|
REJECTED: "REJECTED",
|
|
6879
7039
|
SUPERSEDED: "SUPERSEDED"
|
|
6880
7040
|
};
|
|
6881
|
-
var
|
|
7041
|
+
var BudgetStatus2 = {
|
|
6882
7042
|
DRAFT: "DRAFT",
|
|
6883
7043
|
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6884
7044
|
APPROVED: "APPROVED",
|
|
@@ -6889,13 +7049,13 @@ var BudgetStatus = {
|
|
|
6889
7049
|
ESTIMATE_REJECTED: "ESTIMATE_REJECTED",
|
|
6890
7050
|
ESTIMATE_CLOSED: "ESTIMATE_CLOSED"
|
|
6891
7051
|
};
|
|
6892
|
-
var
|
|
7052
|
+
var ApprovalStatus2 = {
|
|
6893
7053
|
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6894
7054
|
APPROVED: "APPROVED",
|
|
6895
7055
|
REJECTED: "REJECTED",
|
|
6896
7056
|
SUPERSEDED: "SUPERSEDED"
|
|
6897
7057
|
};
|
|
6898
|
-
var
|
|
7058
|
+
var ApprovalType2 = {
|
|
6899
7059
|
BUDGET: "BUDGET",
|
|
6900
7060
|
SUPPLIER: "SUPPLIER",
|
|
6901
7061
|
BILL: "BILL",
|
|
@@ -6909,7 +7069,7 @@ var UserRole = {
|
|
|
6909
7069
|
INSIDE_SALES: "INSIDE_SALES",
|
|
6910
7070
|
ACCOUNTING_TEAM: "ACCOUNTING_TEAM"
|
|
6911
7071
|
};
|
|
6912
|
-
var
|
|
7072
|
+
var BillStatus2 = {
|
|
6913
7073
|
DRAFT: "DRAFT",
|
|
6914
7074
|
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6915
7075
|
CHECKED: "CHECKED",
|
|
@@ -6950,222 +7110,97 @@ import { readFile as readFile2, writeFile } from "fs/promises";
|
|
|
6950
7110
|
import { basename } from "path";
|
|
6951
7111
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
6952
7112
|
|
|
6953
|
-
//
|
|
6954
|
-
var
|
|
6955
|
-
|
|
6956
|
-
|
|
7113
|
+
// src/runtime/error.ts
|
|
7114
|
+
var invocationErrorCodes = new Set([
|
|
7115
|
+
"USAGE",
|
|
7116
|
+
"VALIDATION",
|
|
7117
|
+
"CONFIRMATION_REQUIRED"
|
|
7118
|
+
]);
|
|
7119
|
+
var trpcCodeMap = {
|
|
7120
|
+
BAD_REQUEST: "VALIDATION",
|
|
7121
|
+
CONFLICT: "CONFLICT",
|
|
7122
|
+
FORBIDDEN: "AUTHORIZATION",
|
|
7123
|
+
INTERNAL_SERVER_ERROR: "API",
|
|
7124
|
+
METHOD_NOT_SUPPORTED: "API",
|
|
7125
|
+
NOT_FOUND: "NOT_FOUND",
|
|
7126
|
+
PARSE_ERROR: "VALIDATION",
|
|
7127
|
+
PAYLOAD_TOO_LARGE: "VALIDATION",
|
|
7128
|
+
PRECONDITION_FAILED: "CONFLICT",
|
|
7129
|
+
TIMEOUT: "NETWORK",
|
|
7130
|
+
TOO_MANY_REQUESTS: "API",
|
|
7131
|
+
UNAUTHORIZED: "AUTHENTICATION",
|
|
7132
|
+
UNPROCESSABLE_CONTENT: "VALIDATION"
|
|
6957
7133
|
};
|
|
6958
|
-
var
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
7134
|
+
var cliErrorCodes = new Set([
|
|
7135
|
+
"USAGE",
|
|
7136
|
+
"VALIDATION",
|
|
7137
|
+
"CONFIRMATION_REQUIRED",
|
|
7138
|
+
"AUTHENTICATION",
|
|
7139
|
+
"AUTHORIZATION",
|
|
7140
|
+
"NOT_FOUND",
|
|
7141
|
+
"CONFLICT",
|
|
7142
|
+
"API",
|
|
7143
|
+
"NETWORK",
|
|
7144
|
+
"ABORTED",
|
|
7145
|
+
"INTERRUPTED",
|
|
7146
|
+
"INTERNAL"
|
|
7147
|
+
]);
|
|
7148
|
+
|
|
7149
|
+
class CliRuntimeError extends Error {
|
|
7150
|
+
code;
|
|
7151
|
+
details;
|
|
7152
|
+
requestId;
|
|
7153
|
+
constructor(code, message, options = {}) {
|
|
7154
|
+
super(message);
|
|
7155
|
+
this.name = "CliRuntimeError";
|
|
7156
|
+
this.code = code;
|
|
7157
|
+
this.details = options.details;
|
|
7158
|
+
this.requestId = options.requestId;
|
|
7159
|
+
}
|
|
7160
|
+
}
|
|
7161
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7162
|
+
var asNonEmptyString = (value) => typeof value === "string" && value.trim() !== "" ? value : undefined;
|
|
7163
|
+
var formatValidationMessage = (message, data) => {
|
|
7164
|
+
const zodError = isRecord(data?.zodError) ? data.zodError : undefined;
|
|
7165
|
+
const fieldErrors = isRecord(zodError?.fieldErrors) ? zodError.fieldErrors : undefined;
|
|
7166
|
+
const fields = fieldErrors ? Object.entries(fieldErrors).flatMap(([field, errors]) => Array.isArray(errors) ? errors.filter((entry) => typeof entry === "string").map((entry) => `${field}: ${entry}`) : []) : [];
|
|
7167
|
+
const formErrors = Array.isArray(zodError?.formErrors) ? zodError.formErrors.filter((entry) => typeof entry === "string") : [];
|
|
7168
|
+
const validationIssues = [...fields, ...formErrors];
|
|
7169
|
+
if (validationIssues.length > 0)
|
|
7170
|
+
return validationIssues.join("; ");
|
|
7171
|
+
let parsed = message;
|
|
7172
|
+
for (let depth = 0;depth < 3 && typeof parsed === "string"; depth++) {
|
|
7173
|
+
try {
|
|
7174
|
+
parsed = JSON.parse(parsed);
|
|
7175
|
+
} catch {
|
|
7176
|
+
return message;
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7179
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every(isRecord))
|
|
7180
|
+
return message;
|
|
7181
|
+
const issues = parsed.map((issue) => {
|
|
7182
|
+
if (!Array.isArray(issue.path) || typeof issue.message !== "string" || typeof issue.code !== "string")
|
|
7183
|
+
return;
|
|
7184
|
+
const path = issue.path.filter((part) => typeof part === "string" || typeof part === "number").join(".") || "payload";
|
|
7185
|
+
if (issue.code === "invalid_type" && typeof issue.expected === "string" && issue.message.toLowerCase().includes("required")) {
|
|
7186
|
+
return `${path} must be a ${issue.expected}${path === "cost" ? ', e.g. "19"' : ""}`;
|
|
7187
|
+
}
|
|
7188
|
+
if (issue.code === "invalid_format" && issue.format === "regex" && path === "name" && String(issue.pattern ?? issue.message).includes("A-Za-z0-9,.?@&!#'~* _;+-")) {
|
|
7189
|
+
return `${path} contains characters that are not allowed. Allowed: letters, numbers, spaces and , . ? @ & ! # ' ~ * _ ; + -`;
|
|
7190
|
+
}
|
|
7191
|
+
return `${path}: ${issue.message}`;
|
|
7192
|
+
});
|
|
7193
|
+
return issues.every((issue) => issue !== undefined) ? issues.join("; ") : message;
|
|
6964
7194
|
};
|
|
6965
|
-
var
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
ESTIMATE_CLOSED: "ESTIMATE_CLOSED"
|
|
6975
|
-
};
|
|
6976
|
-
var ApprovalStatus2 = {
|
|
6977
|
-
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
6978
|
-
APPROVED: "APPROVED",
|
|
6979
|
-
REJECTED: "REJECTED",
|
|
6980
|
-
SUPERSEDED: "SUPERSEDED"
|
|
6981
|
-
};
|
|
6982
|
-
var ApprovalType2 = {
|
|
6983
|
-
BUDGET: "BUDGET",
|
|
6984
|
-
SUPPLIER: "SUPPLIER",
|
|
6985
|
-
BILL: "BILL",
|
|
6986
|
-
CUSTOMER_INVOICE: "CUSTOMER_INVOICE",
|
|
6987
|
-
QUOTATION: "QUOTATION"
|
|
6988
|
-
};
|
|
6989
|
-
var ErrorSeverity = {
|
|
6990
|
-
LOW: "LOW",
|
|
6991
|
-
MEDIUM: "MEDIUM",
|
|
6992
|
-
HIGH: "HIGH",
|
|
6993
|
-
CRITICAL: "CRITICAL"
|
|
6994
|
-
};
|
|
6995
|
-
var ErrorStatus = {
|
|
6996
|
-
UNRESOLVED: "UNRESOLVED",
|
|
6997
|
-
INVESTIGATING: "INVESTIGATING",
|
|
6998
|
-
RESOLVED: "RESOLVED",
|
|
6999
|
-
IGNORED: "IGNORED"
|
|
7000
|
-
};
|
|
7001
|
-
var CustomerInvoiceBatchStatus = {
|
|
7002
|
-
CREATING: "CREATING",
|
|
7003
|
-
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
7004
|
-
APPROVED: "APPROVED",
|
|
7005
|
-
REJECTED_VOIDED: "REJECTED_VOIDED",
|
|
7006
|
-
EXPIRED_VOIDED: "EXPIRED_VOIDED",
|
|
7007
|
-
PARTIAL_QBO_FAILURE: "PARTIAL_QBO_FAILURE"
|
|
7008
|
-
};
|
|
7009
|
-
var CustomerInvoiceStatus = {
|
|
7010
|
-
CREATED_IN_QBO: "CREATED_IN_QBO",
|
|
7011
|
-
APPROVED: "APPROVED",
|
|
7012
|
-
SENT: "SENT",
|
|
7013
|
-
PAID: "PAID",
|
|
7014
|
-
VOIDED: "VOIDED",
|
|
7015
|
-
QBO_SYNC_ERROR: "QBO_SYNC_ERROR"
|
|
7016
|
-
};
|
|
7017
|
-
var BillStatus2 = {
|
|
7018
|
-
DRAFT: "DRAFT",
|
|
7019
|
-
PENDING_APPROVAL: "PENDING_APPROVAL",
|
|
7020
|
-
CHECKED: "CHECKED",
|
|
7021
|
-
APPROVED: "APPROVED",
|
|
7022
|
-
PAID: "PAID",
|
|
7023
|
-
REJECTED: "REJECTED"
|
|
7024
|
-
};
|
|
7025
|
-
|
|
7026
|
-
// ../utils/src/filter-enums.ts
|
|
7027
|
-
var ExtendedApprovalStatus = {
|
|
7028
|
-
...ApprovalStatus2,
|
|
7029
|
-
ALL: "ALL"
|
|
7030
|
-
};
|
|
7031
|
-
var ExtendedApprovalType = {
|
|
7032
|
-
...ApprovalType2,
|
|
7033
|
-
ALL: "ALL"
|
|
7034
|
-
};
|
|
7035
|
-
var ExtendedProjectStatus = {
|
|
7036
|
-
...ProjectStatus2,
|
|
7037
|
-
ALL: "ALL"
|
|
7038
|
-
};
|
|
7039
|
-
var ExtendedBudgetStatus = {
|
|
7040
|
-
...BudgetStatus2,
|
|
7041
|
-
ALL: "ALL"
|
|
7042
|
-
};
|
|
7043
|
-
var ExtendedBillStatus = {
|
|
7044
|
-
...BillStatus2,
|
|
7045
|
-
ALL: "ALL"
|
|
7046
|
-
};
|
|
7047
|
-
var ExtendedEstimationMode = {
|
|
7048
|
-
...EstimationMode,
|
|
7049
|
-
ALL: "ALL"
|
|
7050
|
-
};
|
|
7051
|
-
var BudgetRole = {
|
|
7052
|
-
ALL: "ALL",
|
|
7053
|
-
BD: "BD",
|
|
7054
|
-
CREATOR: "CREATOR",
|
|
7055
|
-
INSIDE_SALES: "INSIDE_SALES"
|
|
7056
|
-
};
|
|
7057
|
-
var Deals = {
|
|
7058
|
-
ALL: "ALL",
|
|
7059
|
-
SUCCESSFUL: "SUCCESSFUL",
|
|
7060
|
-
LOST: "LOST"
|
|
7061
|
-
};
|
|
7062
|
-
var TimeFrame = {
|
|
7063
|
-
ALL: "ALL",
|
|
7064
|
-
LAST_YEAR: "LAST_YEAR",
|
|
7065
|
-
LAST_6_MONTHS: "LAST_6_MONTHS",
|
|
7066
|
-
LAST_3_MONTHS: "LAST_3_MONTHS",
|
|
7067
|
-
CUSTOM: "CUSTOM"
|
|
7068
|
-
};
|
|
7069
|
-
var ExtendedErrorSeverity = {
|
|
7070
|
-
ALL: "ALL",
|
|
7071
|
-
...ErrorSeverity
|
|
7072
|
-
};
|
|
7073
|
-
var ExtendedErrorStatus = {
|
|
7074
|
-
ALL: "ALL",
|
|
7075
|
-
...ErrorStatus
|
|
7076
|
-
};
|
|
7077
|
-
|
|
7078
|
-
// src/runtime/error.ts
|
|
7079
|
-
var invocationErrorCodes = new Set([
|
|
7080
|
-
"USAGE",
|
|
7081
|
-
"VALIDATION",
|
|
7082
|
-
"CONFIRMATION_REQUIRED"
|
|
7083
|
-
]);
|
|
7084
|
-
var trpcCodeMap = {
|
|
7085
|
-
BAD_REQUEST: "VALIDATION",
|
|
7086
|
-
CONFLICT: "CONFLICT",
|
|
7087
|
-
FORBIDDEN: "AUTHORIZATION",
|
|
7088
|
-
INTERNAL_SERVER_ERROR: "API",
|
|
7089
|
-
METHOD_NOT_SUPPORTED: "API",
|
|
7090
|
-
NOT_FOUND: "NOT_FOUND",
|
|
7091
|
-
PARSE_ERROR: "VALIDATION",
|
|
7092
|
-
PAYLOAD_TOO_LARGE: "VALIDATION",
|
|
7093
|
-
PRECONDITION_FAILED: "CONFLICT",
|
|
7094
|
-
TIMEOUT: "NETWORK",
|
|
7095
|
-
TOO_MANY_REQUESTS: "API",
|
|
7096
|
-
UNAUTHORIZED: "AUTHENTICATION",
|
|
7097
|
-
UNPROCESSABLE_CONTENT: "VALIDATION"
|
|
7098
|
-
};
|
|
7099
|
-
var cliErrorCodes = new Set([
|
|
7100
|
-
"USAGE",
|
|
7101
|
-
"VALIDATION",
|
|
7102
|
-
"CONFIRMATION_REQUIRED",
|
|
7103
|
-
"AUTHENTICATION",
|
|
7104
|
-
"AUTHORIZATION",
|
|
7105
|
-
"NOT_FOUND",
|
|
7106
|
-
"CONFLICT",
|
|
7107
|
-
"API",
|
|
7108
|
-
"NETWORK",
|
|
7109
|
-
"ABORTED",
|
|
7110
|
-
"INTERRUPTED",
|
|
7111
|
-
"INTERNAL"
|
|
7112
|
-
]);
|
|
7113
|
-
|
|
7114
|
-
class CliRuntimeError extends Error {
|
|
7115
|
-
code;
|
|
7116
|
-
details;
|
|
7117
|
-
requestId;
|
|
7118
|
-
constructor(code, message, options = {}) {
|
|
7119
|
-
super(message);
|
|
7120
|
-
this.name = "CliRuntimeError";
|
|
7121
|
-
this.code = code;
|
|
7122
|
-
this.details = options.details;
|
|
7123
|
-
this.requestId = options.requestId;
|
|
7124
|
-
}
|
|
7125
|
-
}
|
|
7126
|
-
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7127
|
-
var asNonEmptyString = (value) => typeof value === "string" && value.trim() !== "" ? value : undefined;
|
|
7128
|
-
var formatValidationMessage = (message, data) => {
|
|
7129
|
-
const zodError = isRecord(data?.zodError) ? data.zodError : undefined;
|
|
7130
|
-
const fieldErrors = isRecord(zodError?.fieldErrors) ? zodError.fieldErrors : undefined;
|
|
7131
|
-
const fields = fieldErrors ? Object.entries(fieldErrors).flatMap(([field, errors]) => Array.isArray(errors) ? errors.filter((entry) => typeof entry === "string").map((entry) => `${field}: ${entry}`) : []) : [];
|
|
7132
|
-
const formErrors = Array.isArray(zodError?.formErrors) ? zodError.formErrors.filter((entry) => typeof entry === "string") : [];
|
|
7133
|
-
const validationIssues = [...fields, ...formErrors];
|
|
7134
|
-
if (validationIssues.length > 0)
|
|
7135
|
-
return validationIssues.join("; ");
|
|
7136
|
-
let parsed = message;
|
|
7137
|
-
for (let depth = 0;depth < 3 && typeof parsed === "string"; depth++) {
|
|
7138
|
-
try {
|
|
7139
|
-
parsed = JSON.parse(parsed);
|
|
7140
|
-
} catch {
|
|
7141
|
-
return message;
|
|
7142
|
-
}
|
|
7143
|
-
}
|
|
7144
|
-
if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every(isRecord))
|
|
7145
|
-
return message;
|
|
7146
|
-
const issues = parsed.map((issue) => {
|
|
7147
|
-
if (!Array.isArray(issue.path) || typeof issue.message !== "string" || typeof issue.code !== "string")
|
|
7148
|
-
return;
|
|
7149
|
-
const path = issue.path.filter((part) => typeof part === "string" || typeof part === "number").join(".") || "payload";
|
|
7150
|
-
if (issue.code === "invalid_type" && typeof issue.expected === "string" && issue.message.toLowerCase().includes("required")) {
|
|
7151
|
-
return `${path} must be a ${issue.expected}${path === "cost" ? ', e.g. "19"' : ""}`;
|
|
7152
|
-
}
|
|
7153
|
-
if (issue.code === "invalid_format" && issue.format === "regex" && path === "name" && String(issue.pattern ?? issue.message).includes("A-Za-z0-9,.?@&!#'~* _;+-")) {
|
|
7154
|
-
return `${path} contains characters that are not allowed. Allowed: letters, numbers, spaces and , . ? @ & ! # ' ~ * _ ; + -`;
|
|
7155
|
-
}
|
|
7156
|
-
return `${path}: ${issue.message}`;
|
|
7157
|
-
});
|
|
7158
|
-
return issues.every((issue) => issue !== undefined) ? issues.join("; ") : message;
|
|
7159
|
-
};
|
|
7160
|
-
var asDetails = (value) => {
|
|
7161
|
-
if (!isRecord(value))
|
|
7162
|
-
return;
|
|
7163
|
-
const details = {};
|
|
7164
|
-
for (const [key, nestedValue] of Object.entries(value)) {
|
|
7165
|
-
if (isJsonValue(nestedValue))
|
|
7166
|
-
details[key] = nestedValue;
|
|
7167
|
-
}
|
|
7168
|
-
return Object.keys(details).length > 0 ? details : undefined;
|
|
7195
|
+
var asDetails = (value) => {
|
|
7196
|
+
if (!isRecord(value))
|
|
7197
|
+
return;
|
|
7198
|
+
const details = {};
|
|
7199
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
7200
|
+
if (isJsonValue(nestedValue))
|
|
7201
|
+
details[key] = nestedValue;
|
|
7202
|
+
}
|
|
7203
|
+
return Object.keys(details).length > 0 ? details : undefined;
|
|
7169
7204
|
};
|
|
7170
7205
|
var isJsonValue = (value) => {
|
|
7171
7206
|
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number") {
|
|
@@ -7277,9 +7312,9 @@ var customerInvoiceLifecycleStatuses = [
|
|
|
7277
7312
|
];
|
|
7278
7313
|
|
|
7279
7314
|
// src/parse-cli-enums.ts
|
|
7280
|
-
var BUDGET_STATUS_VALUES = new Set(Object.values(
|
|
7281
|
-
var BILL_STATUS_VALUES = new Set(Object.values(
|
|
7282
|
-
var PROJECT_STATUS_VALUES = new Set(Object.values(
|
|
7315
|
+
var BUDGET_STATUS_VALUES = new Set(Object.values(BudgetStatus2));
|
|
7316
|
+
var BILL_STATUS_VALUES = new Set(Object.values(BillStatus2));
|
|
7317
|
+
var PROJECT_STATUS_VALUES = new Set(Object.values(ProjectStatus2));
|
|
7283
7318
|
var SUPPLIER_QUOTATION_STATUS_VALUES = new Set(Object.values(SupplierQuotationStatus));
|
|
7284
7319
|
var CUSTOMER_INVOICE_LIFECYCLE_STATUS_VALUES = new Set(customerInvoiceLifecycleStatuses);
|
|
7285
7320
|
var USER_ROLE_VALUES = new Set(Object.values(UserRole));
|
|
@@ -7326,7 +7361,7 @@ function parseBillStatusForUpdate(raw) {
|
|
|
7326
7361
|
if (!BILL_STATUS_VALUES.has(raw)) {
|
|
7327
7362
|
throw new Error(`Invalid bill status "${raw}". Use one of: ${[...BILL_STATUS_VALUES].join(", ")}.`);
|
|
7328
7363
|
}
|
|
7329
|
-
if (raw ===
|
|
7364
|
+
if (raw === BillStatus2.PENDING_APPROVAL) {
|
|
7330
7365
|
throw new Error("Cannot set PENDING_APPROVAL via update-bill-status. Use create-bill-approval <billId> instead.");
|
|
7331
7366
|
}
|
|
7332
7367
|
return raw;
|
|
@@ -7373,6 +7408,16 @@ var PROJECT_HUB_SORT_FIELDS = new Set([
|
|
|
7373
7408
|
"companyName",
|
|
7374
7409
|
"status"
|
|
7375
7410
|
]);
|
|
7411
|
+
function parseOptionalIsoDateFlag(raw, flagName, { endOfDay = false } = {}) {
|
|
7412
|
+
if (raw === undefined || raw === "")
|
|
7413
|
+
return;
|
|
7414
|
+
const value = /^\d{4}-\d{2}-\d{2}$/.test(raw) ? `${raw}T${endOfDay ? "23:59:59.999" : "00:00:00.000"}Z` : /T\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(raw) ? `${raw}Z` : raw;
|
|
7415
|
+
const parsed = new Date(value);
|
|
7416
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
7417
|
+
throw new Error(`${flagName} must be an ISO date (YYYY-MM-DD) or ISO datetime.`);
|
|
7418
|
+
}
|
|
7419
|
+
return parsed;
|
|
7420
|
+
}
|
|
7376
7421
|
function parseOptionalProjectHubSortBy(raw) {
|
|
7377
7422
|
if (raw === undefined || raw === "")
|
|
7378
7423
|
return;
|
|
@@ -7565,10 +7610,10 @@ function parseApprovalTypeFlag(raw) {
|
|
|
7565
7610
|
}
|
|
7566
7611
|
return u;
|
|
7567
7612
|
}
|
|
7568
|
-
var budgetStatusesForHelp = Object.values(
|
|
7569
|
-
var billStatusesForHelp = Object.values(
|
|
7570
|
-
var billStatusesForUpdateHelp = Object.values(
|
|
7571
|
-
var projectStatusesForHelp = Object.values(
|
|
7613
|
+
var budgetStatusesForHelp = Object.values(BudgetStatus2);
|
|
7614
|
+
var billStatusesForHelp = Object.values(BillStatus2);
|
|
7615
|
+
var billStatusesForUpdateHelp = Object.values(BillStatus2).filter((s) => s !== BillStatus2.PENDING_APPROVAL);
|
|
7616
|
+
var projectStatusesForHelp = Object.values(ProjectStatus2);
|
|
7572
7617
|
var userRolesForHelp = Object.values(UserRole);
|
|
7573
7618
|
|
|
7574
7619
|
// ../utils/src/rich-text.ts
|
|
@@ -8494,11 +8539,11 @@ var confirmCurrentCommand = async (input) => {
|
|
|
8494
8539
|
};
|
|
8495
8540
|
// src/commands/index.ts
|
|
8496
8541
|
import { contentType } from "mime-types";
|
|
8497
|
-
var BUDGET =
|
|
8498
|
-
var BILL =
|
|
8499
|
-
var SUPPLIER =
|
|
8500
|
-
var QUOTATION =
|
|
8501
|
-
var CUSTOMER_INVOICE =
|
|
8542
|
+
var BUDGET = ApprovalType2.BUDGET;
|
|
8543
|
+
var BILL = ApprovalType2.BILL;
|
|
8544
|
+
var SUPPLIER = ApprovalType2.SUPPLIER;
|
|
8545
|
+
var QUOTATION = ApprovalType2.QUOTATION;
|
|
8546
|
+
var CUSTOMER_INVOICE = ApprovalType2.CUSTOMER_INVOICE;
|
|
8502
8547
|
var ASANA_WON_LOST_SECTION_GIDS = new Set([
|
|
8503
8548
|
"1211678338364908",
|
|
8504
8549
|
"1211678338364907"
|
|
@@ -8555,7 +8600,7 @@ var createApprovalEmailDeliveryFailure = (error) => ({
|
|
|
8555
8600
|
error
|
|
8556
8601
|
});
|
|
8557
8602
|
function isPendingRequest(n) {
|
|
8558
|
-
return n.notificationType === "request" && n.status ===
|
|
8603
|
+
return n.notificationType === "request" && n.status === ApprovalStatus2.PENDING_APPROVAL;
|
|
8559
8604
|
}
|
|
8560
8605
|
var out = (data) => {
|
|
8561
8606
|
emitCommandResult(data);
|
|
@@ -8762,11 +8807,11 @@ var quotationAttachmentContentTypeForFileName = (fileName) => {
|
|
|
8762
8807
|
throw new Error(`Unsupported quotation attachment type: ${fileName}. Use PDF, JPEG, or PNG.`);
|
|
8763
8808
|
};
|
|
8764
8809
|
var LOCKED_BUDGET_STATUSES_REQUIRING_CONFIRMATION = new Set([
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8810
|
+
BudgetStatus2.ESTIMATE_CREATED,
|
|
8811
|
+
BudgetStatus2.ESTIMATE_SENT,
|
|
8812
|
+
BudgetStatus2.ESTIMATE_ACCEPTED,
|
|
8813
|
+
BudgetStatus2.ESTIMATE_REJECTED,
|
|
8814
|
+
BudgetStatus2.ESTIMATE_CLOSED
|
|
8770
8815
|
]);
|
|
8771
8816
|
var lockedBudgetStatusLabels = {
|
|
8772
8817
|
ESTIMATE_CREATED: "Estimate Created",
|
|
@@ -8888,36 +8933,20 @@ var updateProjectWithEstimateInvalidationConfirmation = async (input) => {
|
|
|
8888
8933
|
});
|
|
8889
8934
|
}
|
|
8890
8935
|
};
|
|
8891
|
-
async
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
dateFrom: opts.dateFrom,
|
|
8898
|
-
dateTo: opts.dateTo,
|
|
8899
|
-
active: opts.active,
|
|
8900
|
-
sortBy: opts.sortBy,
|
|
8901
|
-
sortDir: opts.sortDir,
|
|
8902
|
-
page: opts.page ?? 1,
|
|
8903
|
-
perPage: opts.perPage ?? 20,
|
|
8904
|
-
includeDetails: opts.includeDetails ?? true
|
|
8905
|
-
};
|
|
8906
|
-
const result = await api2.budget.getAllBudgets.query(input);
|
|
8907
|
-
out(result);
|
|
8908
|
-
}
|
|
8936
|
+
var listBudgets = async (input) => {
|
|
8937
|
+
out(await api2.budget.getAllBudgets.query(input));
|
|
8938
|
+
};
|
|
8939
|
+
var countBudgets = async (input) => {
|
|
8940
|
+
out(await api2.budget.getCounts.query(input));
|
|
8941
|
+
};
|
|
8909
8942
|
async function getBudget(id, opts) {
|
|
8910
|
-
const
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
})
|
|
8915
|
-
api2.budget.getBudgetItems.query({
|
|
8916
|
-
budgetId: id,
|
|
8917
|
-
includeInactive: opts?.includeInactive ?? false
|
|
8918
|
-
})
|
|
8943
|
+
const includeInactive = opts?.includeInactive ?? false;
|
|
8944
|
+
const [budget, items, totals] = await Promise.all([
|
|
8945
|
+
api2.budget.getBudget.query({ id, includeInactive }),
|
|
8946
|
+
api2.budget.getBudgetItems.query({ budgetId: id, includeInactive }),
|
|
8947
|
+
api2.budget.getBudgetItemTotals.query({ budgetId: id, includeInactive })
|
|
8919
8948
|
]);
|
|
8920
|
-
out({ budget, items });
|
|
8949
|
+
out({ budget, items: { ...items, totals } });
|
|
8921
8950
|
}
|
|
8922
8951
|
async function updateBudgetStatus(budgetId, status, opts) {
|
|
8923
8952
|
await assertSensitiveWorkflowConfirmed({
|
|
@@ -8944,7 +8973,7 @@ async function updateBudgetStatus(budgetId, status, opts) {
|
|
|
8944
8973
|
});
|
|
8945
8974
|
out({
|
|
8946
8975
|
...result,
|
|
8947
|
-
invoiceSetup: result.newStatus ===
|
|
8976
|
+
invoiceSetup: result.newStatus === BudgetStatus2.ESTIMATE_ACCEPTED && result.hasQuickbooksEstimate ? invoiceSplitSetupNextAction(budgetId) : null
|
|
8948
8977
|
});
|
|
8949
8978
|
}
|
|
8950
8979
|
var assertBudgetActionReadiness = async ({
|
|
@@ -9011,22 +9040,22 @@ var runBudgetPreflight = async (budgetId, preflight) => {
|
|
|
9011
9040
|
await updateProjectWithEstimateInvalidationConfirmation(payload);
|
|
9012
9041
|
}
|
|
9013
9042
|
};
|
|
9014
|
-
async
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
}
|
|
9043
|
+
var listBills = async (input) => {
|
|
9044
|
+
out(await api2.bill.getAll.query({
|
|
9045
|
+
...input,
|
|
9046
|
+
statuses: billStatusesForApi(input.statuses),
|
|
9047
|
+
search: input.search?.trim() || undefined,
|
|
9048
|
+
createdByIds: input.createdByIds?.length ? input.createdByIds : undefined
|
|
9049
|
+
}));
|
|
9050
|
+
};
|
|
9051
|
+
var countBills = async (input) => {
|
|
9052
|
+
out(await api2.bill.getCounts.query({
|
|
9053
|
+
...input,
|
|
9054
|
+
statuses: billStatusesForApi(input.statuses),
|
|
9055
|
+
search: input.search?.trim() || undefined,
|
|
9056
|
+
createdByIds: input.createdByIds?.length ? input.createdByIds : undefined
|
|
9057
|
+
}));
|
|
9058
|
+
};
|
|
9030
9059
|
async function approveBill(billId, overBudgetOverrideReason) {
|
|
9031
9060
|
await assertSensitiveWorkflowConfirmed({
|
|
9032
9061
|
action: "Approve bill",
|
|
@@ -9041,7 +9070,7 @@ async function approveBill(billId, overBudgetOverrideReason) {
|
|
|
9041
9070
|
}
|
|
9042
9071
|
const result = await api2.bill.updateApproval.mutate({
|
|
9043
9072
|
billApprovalId: approval.id,
|
|
9044
|
-
status:
|
|
9073
|
+
status: ApprovalStatus2.APPROVED,
|
|
9045
9074
|
overBudgetOverrideReason
|
|
9046
9075
|
});
|
|
9047
9076
|
if (result.processing) {
|
|
@@ -9098,20 +9127,12 @@ async function listApprovals(opts) {
|
|
|
9098
9127
|
});
|
|
9099
9128
|
out({ items });
|
|
9100
9129
|
}
|
|
9101
|
-
async
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
createdBy: opts.createdBy,
|
|
9108
|
-
gstRegistered: opts.gstRegistered ?? null,
|
|
9109
|
-
status: opts.status,
|
|
9110
|
-
supplierTags: opts.supplierTags,
|
|
9111
|
-
active: opts.active ?? true
|
|
9112
|
-
});
|
|
9113
|
-
out(result);
|
|
9114
|
-
}
|
|
9130
|
+
var listSuppliers = async (opts) => {
|
|
9131
|
+
out(await api2.supplier.getSuppliers.query(opts));
|
|
9132
|
+
};
|
|
9133
|
+
var countSuppliers = async (opts) => {
|
|
9134
|
+
out(await api2.supplier.getSummary.query(opts));
|
|
9135
|
+
};
|
|
9115
9136
|
async function createBillApproval(billId) {
|
|
9116
9137
|
await assertSensitiveWorkflowConfirmed({
|
|
9117
9138
|
action: "Create bill approval request",
|
|
@@ -9137,10 +9158,10 @@ async function createBillApproval(billId) {
|
|
|
9137
9158
|
});
|
|
9138
9159
|
}
|
|
9139
9160
|
var validateBillStatusUpdateOptions = (opts) => {
|
|
9140
|
-
if (opts.status ===
|
|
9161
|
+
if (opts.status === BillStatus2.PAID && !opts.paymentReference?.trim()) {
|
|
9141
9162
|
throw new Error("update-bill-status requires --paymentReference when status is PAID.");
|
|
9142
9163
|
}
|
|
9143
|
-
if (opts.status !==
|
|
9164
|
+
if (opts.status !== BillStatus2.PAID && opts.paymentProofPath !== undefined) {
|
|
9144
9165
|
throw new Error("--paymentProof can only be used when status is PAID.");
|
|
9145
9166
|
}
|
|
9146
9167
|
if (opts.paymentProofPath !== undefined && !opts.paymentProofPath.trim()) {
|
|
@@ -9148,13 +9169,10 @@ var validateBillStatusUpdateOptions = (opts) => {
|
|
|
9148
9169
|
}
|
|
9149
9170
|
};
|
|
9150
9171
|
var deleteStagedPaymentProof = async (projectId, key) => {
|
|
9151
|
-
|
|
9172
|
+
await api2.attachment.deleteStagedBillAttachments.mutate({
|
|
9152
9173
|
projectId,
|
|
9153
9174
|
keys: [key]
|
|
9154
9175
|
});
|
|
9155
|
-
if (cleanup.failedKeys.includes(key)) {
|
|
9156
|
-
throw new Error(`Failed to delete staged payment proof ${key}.`);
|
|
9157
|
-
}
|
|
9158
9176
|
};
|
|
9159
9177
|
var rethrowAfterStagedPaymentProofCleanup = async (error, cleanup) => {
|
|
9160
9178
|
if (cleanup) {
|
|
@@ -9288,10 +9306,9 @@ async function patchBillInvoiceNumber(id, invoiceNumber) {
|
|
|
9288
9306
|
});
|
|
9289
9307
|
out(result);
|
|
9290
9308
|
}
|
|
9291
|
-
async
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
}
|
|
9309
|
+
var getBillAttachments = async (input) => {
|
|
9310
|
+
out(await api2.bill.getAttachments.query(input));
|
|
9311
|
+
};
|
|
9295
9312
|
async function stageBillAttachmentsFromPaths(projectId, filePaths) {
|
|
9296
9313
|
const attachments = [];
|
|
9297
9314
|
for (const filePath of filePaths) {
|
|
@@ -9499,7 +9516,7 @@ async function uploadBudgetWinProofFromPath(budgetId, filePath, opts) {
|
|
|
9499
9516
|
});
|
|
9500
9517
|
const result = await api2.budget.updateBudgetStatus.mutate({
|
|
9501
9518
|
id: budgetId,
|
|
9502
|
-
status:
|
|
9519
|
+
status: BudgetStatus2.ESTIMATE_ACCEPTED,
|
|
9503
9520
|
...opts?.projectManagerId !== undefined && {
|
|
9504
9521
|
projectManagerId: opts.projectManagerId
|
|
9505
9522
|
},
|
|
@@ -9523,11 +9540,12 @@ async function getBillDetails(id) {
|
|
|
9523
9540
|
out(result);
|
|
9524
9541
|
}
|
|
9525
9542
|
async function getBudgetItemsOnly(budgetId, opts) {
|
|
9526
|
-
const
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9543
|
+
const includeInactive = opts?.includeInactive ?? false;
|
|
9544
|
+
const [items, totals] = await Promise.all([
|
|
9545
|
+
api2.budget.getBudgetItems.query({ budgetId, includeInactive }),
|
|
9546
|
+
api2.budget.getBudgetItemTotals.query({ budgetId, includeInactive })
|
|
9547
|
+
]);
|
|
9548
|
+
out({ ...items, totals });
|
|
9531
9549
|
}
|
|
9532
9550
|
async function addBudgetItems(opts) {
|
|
9533
9551
|
await confirmLockedBudgetChangeByBudgetId(opts.budgetId, "Add budget items");
|
|
@@ -9564,10 +9582,9 @@ var approveUnavailableItemException = async (input) => {
|
|
|
9564
9582
|
const result = await api2.budgetItem.approveUnavailableItemException.mutate(input);
|
|
9565
9583
|
out(result);
|
|
9566
9584
|
};
|
|
9567
|
-
async
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
}
|
|
9585
|
+
var getBudgetCategories = async (input) => {
|
|
9586
|
+
out(await api2.budget.searchBudgetCategories.query(input));
|
|
9587
|
+
};
|
|
9571
9588
|
var getBudgetVersions = async (budgetId, options = {}) => {
|
|
9572
9589
|
if (options.all && options.cursor !== undefined) {
|
|
9573
9590
|
throw new CliRuntimeError("USAGE", "--all cannot be combined with --cursor.");
|
|
@@ -9576,20 +9593,20 @@ var getBudgetVersions = async (budgetId, options = {}) => {
|
|
|
9576
9593
|
const seenCursors = new Set;
|
|
9577
9594
|
let cursor = options.cursor;
|
|
9578
9595
|
do {
|
|
9579
|
-
const page = await api2.budgetVersion.
|
|
9596
|
+
const page = await api2.budgetVersion.getBudgetVersions.query({
|
|
9580
9597
|
budgetId,
|
|
9581
9598
|
limit: options.limit,
|
|
9582
9599
|
cursor
|
|
9583
9600
|
});
|
|
9584
|
-
versions.push(...page.
|
|
9585
|
-
cursor = page.nextCursor;
|
|
9586
|
-
if (!options.all || cursor ===
|
|
9601
|
+
versions.push(...page.items);
|
|
9602
|
+
cursor = page.pageInfo.nextCursor;
|
|
9603
|
+
if (!options.all || cursor === null)
|
|
9587
9604
|
break;
|
|
9588
9605
|
if (seenCursors.has(cursor)) {
|
|
9589
9606
|
throw new Error("Budget history pagination did not advance; export aborted.");
|
|
9590
9607
|
}
|
|
9591
9608
|
seenCursors.add(cursor);
|
|
9592
|
-
} while (cursor !==
|
|
9609
|
+
} while (cursor !== null);
|
|
9593
9610
|
out({ versions, nextCursor: cursor ?? null });
|
|
9594
9611
|
};
|
|
9595
9612
|
async function createBudgetApproval(budgetId, preflight) {
|
|
@@ -9840,10 +9857,12 @@ async function createBillFromPayload(raw, draftOnlyFlag, quotationExempt = false
|
|
|
9840
9857
|
}) : await api2.bill.create.mutate(input);
|
|
9841
9858
|
out(result);
|
|
9842
9859
|
}
|
|
9843
|
-
async
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9860
|
+
var listQuotations = async (input) => {
|
|
9861
|
+
out(await api2.quotation.listPage.query(input));
|
|
9862
|
+
};
|
|
9863
|
+
var countQuotations = async (input) => {
|
|
9864
|
+
out(await api2.quotation.getCounts.query(input));
|
|
9865
|
+
};
|
|
9847
9866
|
async function getQuotationDetails(id) {
|
|
9848
9867
|
const result = await api2.quotation.getById.query({ id });
|
|
9849
9868
|
out(result);
|
|
@@ -9888,8 +9907,10 @@ var checkCustomerInvoiceReadiness = async (budgetId) => {
|
|
|
9888
9907
|
out(result);
|
|
9889
9908
|
};
|
|
9890
9909
|
var listCustomerInvoices = async (input) => {
|
|
9891
|
-
|
|
9892
|
-
|
|
9910
|
+
out(await api2.customerInvoice.list.query(input));
|
|
9911
|
+
};
|
|
9912
|
+
var countCustomerInvoices = async (input) => {
|
|
9913
|
+
out(await api2.customerInvoice.getCounts.query(input));
|
|
9893
9914
|
};
|
|
9894
9915
|
var listEligibleCustomerInvoiceBudgets = async (projectId) => {
|
|
9895
9916
|
const result = await api2.customerInvoice.getEligibleBudgets.query({
|
|
@@ -9945,7 +9966,7 @@ var createCustomerInvoice = async (raw) => {
|
|
|
9945
9966
|
await assertSensitiveWorkflowConfirmed({
|
|
9946
9967
|
action: "Create customer invoice",
|
|
9947
9968
|
entity: `budget ${input.budgetId}`,
|
|
9948
|
-
details: `
|
|
9969
|
+
details: `queues ${input.splits.length} invoice(s) for creation in QuickBooks from the budget's remaining uninvoiced balance: ${input.splits.map((split) => `${split.label} (${split.percentage}% of the estimate), due ${new Date(split.dueDate).toISOString().slice(0, 10)}`).join("; ")}. Admin creation is auto-approved; other creators request approval. No customer email is sent.`
|
|
9949
9970
|
});
|
|
9950
9971
|
const result = await api2.customerInvoice.createInvoiceBatch.mutate(input);
|
|
9951
9972
|
out(result);
|
|
@@ -9965,7 +9986,7 @@ var deleteCustomerInvoice = async (batchId) => {
|
|
|
9965
9986
|
await assertSensitiveWorkflowConfirmed({
|
|
9966
9987
|
action: "Delete customer invoice",
|
|
9967
9988
|
entity: `invoice batch ${batchId}`,
|
|
9968
|
-
details: "
|
|
9989
|
+
details: "queues deletion of its invoices in QuickBooks; the local batch is removed once QuickBooks confirms; paid invoices are blocked until their QBO payments are reversed; removing approved coverage may reopen the estimate"
|
|
9969
9990
|
});
|
|
9970
9991
|
const result = await api2.customerInvoice.deleteInvoiceBatch.mutate({
|
|
9971
9992
|
batchId
|
|
@@ -9976,7 +9997,7 @@ var voidCustomerInvoice = async (batchId) => {
|
|
|
9976
9997
|
await assertSensitiveWorkflowConfirmed({
|
|
9977
9998
|
action: "Void customer invoice",
|
|
9978
9999
|
entity: `invoice batch ${batchId}`,
|
|
9979
|
-
details: "
|
|
10000
|
+
details: "queues a void of its invoices in QuickBooks; Budget Builder updates once QuickBooks confirms; paid invoices are blocked until their QBO payments are reversed; removing approved coverage may reopen the estimate"
|
|
9980
10001
|
});
|
|
9981
10002
|
const result = await api2.customerInvoice.voidInvoiceBatch.mutate({ batchId });
|
|
9982
10003
|
out(result);
|
|
@@ -9996,7 +10017,7 @@ var rejectCustomerInvoice = async (batchId, rejectionReason) => {
|
|
|
9996
10017
|
await assertSensitiveWorkflowConfirmed({
|
|
9997
10018
|
action: "Reject customer invoice",
|
|
9998
10019
|
entity: `invoice batch ${batchId}`,
|
|
9999
|
-
details: `
|
|
10020
|
+
details: `queues a void of its invoices in QuickBooks; once QuickBooks confirms, records the rejection reason, notifies its creator, and reopens a prematurely closed estimate when applicable`
|
|
10000
10021
|
});
|
|
10001
10022
|
const result = await api2.customerInvoice.rejectInvoiceBatch.mutate({
|
|
10002
10023
|
batchId,
|
|
@@ -10080,7 +10101,7 @@ async function createSupplierFromPayload(raw) {
|
|
|
10080
10101
|
throw new CliRuntimeError(normalized.code, `Supplier creation outcome is uncertain for ${JSON.stringify(input.name)}. Run list-suppliers and inspect matching supplier details before retrying; names may not be unique, so do not retry create-supplier until you can verify that no supplier was created. Original error: ${normalized.message}`);
|
|
10081
10102
|
}
|
|
10082
10103
|
const supplier = created.result;
|
|
10083
|
-
if (supplier.status !==
|
|
10104
|
+
if (supplier.status !== ApprovalStatus2.PENDING_APPROVAL) {
|
|
10084
10105
|
out(created);
|
|
10085
10106
|
return;
|
|
10086
10107
|
}
|
|
@@ -10147,6 +10168,10 @@ async function updateProjectFromPayload(raw) {
|
|
|
10147
10168
|
const result = await updateProjectWithEstimateInvalidationConfirmation(input);
|
|
10148
10169
|
out(result);
|
|
10149
10170
|
}
|
|
10171
|
+
var getCompanyQuickBooksSyncStatus = async (companyId) => {
|
|
10172
|
+
const result = await api2.company.getQuickBooksSyncStatus.query({ companyId });
|
|
10173
|
+
out(result);
|
|
10174
|
+
};
|
|
10150
10175
|
async function updateCompanyFromPayload(raw) {
|
|
10151
10176
|
const input = parseCompanyUpdatePayload(raw);
|
|
10152
10177
|
const result = await api2.company.updateCompany.mutate(input);
|
|
@@ -10398,16 +10423,14 @@ async function rejectQuotation(quotationId, reason) {
|
|
|
10398
10423
|
});
|
|
10399
10424
|
out(result);
|
|
10400
10425
|
}
|
|
10401
|
-
async
|
|
10402
|
-
const result = await api2.company.getCompanies.query(
|
|
10403
|
-
name: opts.name,
|
|
10404
|
-
createdBy: opts.createdBy,
|
|
10405
|
-
active: opts.active,
|
|
10406
|
-
page: opts.page ?? 1,
|
|
10407
|
-
perPage: opts.perPage ?? 20
|
|
10408
|
-
});
|
|
10426
|
+
var listCompanies = async (input) => {
|
|
10427
|
+
const result = await api2.company.getCompanies.query(input);
|
|
10409
10428
|
out(result);
|
|
10410
|
-
}
|
|
10429
|
+
};
|
|
10430
|
+
var countCompanies = async (input) => {
|
|
10431
|
+
const result = await api2.company.getCompanyCounts.query(input);
|
|
10432
|
+
out(result);
|
|
10433
|
+
};
|
|
10411
10434
|
async function getCompany(id) {
|
|
10412
10435
|
const company = await api2.company.getCompanyById.query({ id });
|
|
10413
10436
|
out(company);
|
|
@@ -10416,31 +10439,26 @@ async function createCompany(opts) {
|
|
|
10416
10439
|
const result = await api2.company.createCompany.mutate(opts);
|
|
10417
10440
|
out(result);
|
|
10418
10441
|
}
|
|
10419
|
-
var searchExistingCompanies = async (
|
|
10420
|
-
out(await api2.company.searchExistingCompanies.query(
|
|
10442
|
+
var searchExistingCompanies = async (input) => {
|
|
10443
|
+
out(await api2.company.searchExistingCompanies.query(input));
|
|
10421
10444
|
};
|
|
10422
10445
|
var reuseExistingCompany = async (input) => {
|
|
10423
10446
|
out(await api2.company.useExistingCompany.mutate(input));
|
|
10424
10447
|
};
|
|
10425
|
-
async
|
|
10426
|
-
const result = await api2.project.getAllProjects.query(
|
|
10427
|
-
companyId: opts.companyId,
|
|
10428
|
-
name: opts.name,
|
|
10429
|
-
status: opts.status,
|
|
10430
|
-
active: opts.active,
|
|
10431
|
-
page: opts.page ?? 1,
|
|
10432
|
-
perPage: opts.perPage ?? 20
|
|
10433
|
-
});
|
|
10448
|
+
var listProjects = async (input) => {
|
|
10449
|
+
const result = await api2.project.getAllProjects.query(input);
|
|
10434
10450
|
out(result);
|
|
10435
|
-
}
|
|
10436
|
-
var
|
|
10437
|
-
const result = await api2.project.
|
|
10438
|
-
...opts,
|
|
10439
|
-
page: opts.page ?? 1,
|
|
10440
|
-
perPage: opts.perPage ?? 20
|
|
10441
|
-
});
|
|
10451
|
+
};
|
|
10452
|
+
var countProjects = async (input) => {
|
|
10453
|
+
const result = await api2.project.getProjectCounts.query(input);
|
|
10442
10454
|
out(result);
|
|
10443
10455
|
};
|
|
10456
|
+
var listProjectHubs = async (input) => {
|
|
10457
|
+
out(await api2.project.getAllProjectHubs.query(input));
|
|
10458
|
+
};
|
|
10459
|
+
var countProjectHubs = async (input) => {
|
|
10460
|
+
out(await api2.project.getProjectHubCounts.query(input));
|
|
10461
|
+
};
|
|
10444
10462
|
async function getProject(id) {
|
|
10445
10463
|
const [project, budgetsOverview, billsOverview] = await Promise.all([
|
|
10446
10464
|
api2.project.getProjectDetailsById.query({ id }),
|
|
@@ -10536,7 +10554,7 @@ var reconcileProject = async (projectId) => {
|
|
|
10536
10554
|
out(result);
|
|
10537
10555
|
};
|
|
10538
10556
|
var completeProject = async (projectId) => {
|
|
10539
|
-
await updateProjectStatus(projectId,
|
|
10557
|
+
await updateProjectStatus(projectId, ProjectStatus2.COMPLETED);
|
|
10540
10558
|
};
|
|
10541
10559
|
var importQuickBooksProjectId = async (projectId, projectUrl) => {
|
|
10542
10560
|
const result = await api2.project.importQboProjectId.mutate({
|
|
@@ -10545,14 +10563,71 @@ var importQuickBooksProjectId = async (projectId, projectUrl) => {
|
|
|
10545
10563
|
});
|
|
10546
10564
|
out(result);
|
|
10547
10565
|
};
|
|
10548
|
-
var
|
|
10549
|
-
|
|
10550
|
-
out(result);
|
|
10566
|
+
var listWebhookEventTypes = async () => {
|
|
10567
|
+
out(await api2.webhook.listEventTypes.query());
|
|
10551
10568
|
};
|
|
10552
|
-
var
|
|
10553
|
-
await
|
|
10554
|
-
|
|
10555
|
-
|
|
10569
|
+
var listWebhookEndpoints = async () => {
|
|
10570
|
+
out(await api2.webhook.listEndpoints.query());
|
|
10571
|
+
};
|
|
10572
|
+
var getWebhookEndpoint = async (id) => {
|
|
10573
|
+
out(await api2.webhook.getEndpoint.query({ id }));
|
|
10574
|
+
};
|
|
10575
|
+
var createWebhookEndpoint = async (input) => {
|
|
10576
|
+
const result = await api2.webhook.createEndpoint.mutate(input);
|
|
10577
|
+
out({
|
|
10578
|
+
...result,
|
|
10579
|
+
note: "Store the signing secret now; Budget Builder never shows it again."
|
|
10580
|
+
});
|
|
10581
|
+
};
|
|
10582
|
+
var updateWebhookEndpoint = async (input) => {
|
|
10583
|
+
out(await api2.webhook.updateEndpoint.mutate(input));
|
|
10584
|
+
};
|
|
10585
|
+
var deleteWebhookEndpoint = async (id) => {
|
|
10586
|
+
await assertSensitiveWorkflowConfirmed({
|
|
10587
|
+
action: "Delete webhook endpoint and its delivery history",
|
|
10588
|
+
entity: `webhook endpoint ${id}`
|
|
10589
|
+
});
|
|
10590
|
+
out(await api2.webhook.deleteEndpoint.mutate({ id }));
|
|
10591
|
+
};
|
|
10592
|
+
var rotateWebhookSecret = async (input) => {
|
|
10593
|
+
await assertSensitiveWorkflowConfirmed({
|
|
10594
|
+
action: "Rotate webhook signing secret",
|
|
10595
|
+
entity: `webhook endpoint ${input.id}`,
|
|
10596
|
+
details: `previous secrets keep signing for ${input.previousSecretTtlHours ?? 24}h`
|
|
10597
|
+
});
|
|
10598
|
+
const result = await api2.webhook.rotateSecret.mutate(input);
|
|
10599
|
+
out({
|
|
10600
|
+
...result,
|
|
10601
|
+
note: "Store the new signing secret now; Budget Builder never shows it again."
|
|
10602
|
+
});
|
|
10603
|
+
};
|
|
10604
|
+
var sendWebhookTestEvent = async (id) => {
|
|
10605
|
+
out(await api2.webhook.sendTestEvent.mutate({ id }));
|
|
10606
|
+
};
|
|
10607
|
+
var listWebhookDeliveries = async (input) => {
|
|
10608
|
+
out(await api2.webhook.listDeliveries.query(input));
|
|
10609
|
+
};
|
|
10610
|
+
var getWebhookDelivery = async (deliveryId) => {
|
|
10611
|
+
out(await api2.webhook.getDelivery.query({ deliveryId }));
|
|
10612
|
+
};
|
|
10613
|
+
var replayWebhookDelivery = async (deliveryId) => {
|
|
10614
|
+
out(await api2.webhook.replayDelivery.mutate({ deliveryId }));
|
|
10615
|
+
};
|
|
10616
|
+
var listIntegrationOperations = async (input) => {
|
|
10617
|
+
const result = await api2.integration.listOperations.query(input);
|
|
10618
|
+
out(result);
|
|
10619
|
+
};
|
|
10620
|
+
var getIntegrationOperation = async (operationId) => {
|
|
10621
|
+
const result = await api2.integration.getOperation.query({ operationId });
|
|
10622
|
+
out(result);
|
|
10623
|
+
};
|
|
10624
|
+
var countIntegrationOperations = async (input) => {
|
|
10625
|
+
out(await api2.integration.getCounts.query(input));
|
|
10626
|
+
};
|
|
10627
|
+
var retryIntegrationOperation = async (operationId, confirmExternalStateReconciled, outboundEmailResolution, providerMessageId) => {
|
|
10628
|
+
await assertSensitiveWorkflowConfirmed({
|
|
10629
|
+
action: outboundEmailResolution === "ACCEPTED" ? "Reconcile integration operation as completed" : "Retry integration operation (QuickBooks jobs with a saved attempt check QuickBooks first and never resend an applied change)",
|
|
10630
|
+
entity: `operation ${operationId}`,
|
|
10556
10631
|
details: outboundEmailResolution === "ACCEPTED" ? `mark provider-accepted email sent with message ID ${providerMessageId ?? "<missing>"}` : outboundEmailResolution === "NOT_ACCEPTED_RETRY" ? "rotate the Resend idempotency key and retry provider delivery" : confirmExternalStateReconciled ? "after confirming the external state has been reconciled" : undefined
|
|
10557
10632
|
});
|
|
10558
10633
|
const result = await api2.integration.retryOperation.mutate({
|
|
@@ -10563,10 +10638,25 @@ var retryIntegrationOperation = async (operationId, confirmExternalStateReconcil
|
|
|
10563
10638
|
});
|
|
10564
10639
|
out(result);
|
|
10565
10640
|
};
|
|
10641
|
+
var reconcileResourceOperation = async (operationId) => {
|
|
10642
|
+
await assertSensitiveWorkflowConfirmed({
|
|
10643
|
+
action: "Verify QuickBooks resource outcome",
|
|
10644
|
+
entity: `operation ${operationId}`,
|
|
10645
|
+
details: "verify the saved receipt or read QuickBooks when the attempt is uncertain, then queue local update/archive/reactivation finalization without repeating the provider mutation"
|
|
10646
|
+
});
|
|
10647
|
+
const result = await api2.integration.reconcileResourceOperation.mutate({
|
|
10648
|
+
operationId
|
|
10649
|
+
});
|
|
10650
|
+
out(result);
|
|
10651
|
+
};
|
|
10566
10652
|
var listInboundSources = async (input) => {
|
|
10567
10653
|
const result = await api2.inbound.listSources.query(input);
|
|
10568
10654
|
out(result);
|
|
10569
10655
|
};
|
|
10656
|
+
var countInboundSources = async (input) => {
|
|
10657
|
+
const result = await api2.inbound.countSources.query(input);
|
|
10658
|
+
out(result);
|
|
10659
|
+
};
|
|
10570
10660
|
var createInboundSource = async (input) => {
|
|
10571
10661
|
const result = await api2.inbound.createSource.mutate(input);
|
|
10572
10662
|
out(result);
|
|
@@ -10583,6 +10673,9 @@ var listInboundSubmissions = async (input) => {
|
|
|
10583
10673
|
const result = await api2.inbound.listSubmissions.query(input);
|
|
10584
10674
|
out(result);
|
|
10585
10675
|
};
|
|
10676
|
+
var countInboundSubmissions = async (input) => {
|
|
10677
|
+
out(await api2.inbound.countSubmissions.query(input));
|
|
10678
|
+
};
|
|
10586
10679
|
var getInboundSubmission = async (submissionId) => {
|
|
10587
10680
|
const result = await api2.inbound.getSubmission.query({ submissionId });
|
|
10588
10681
|
out(result);
|
|
@@ -10610,39 +10703,32 @@ async function listContacts(companyId) {
|
|
|
10610
10703
|
});
|
|
10611
10704
|
out(contacts);
|
|
10612
10705
|
}
|
|
10613
|
-
async
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
const [items, { total, counts }] = await Promise.all([
|
|
10620
|
-
api2.item.getItems.query({ ...filters, page: opts.page ?? 1, perPage }),
|
|
10621
|
-
api2.item.getItemCounts.query(filters)
|
|
10622
|
-
]);
|
|
10623
|
-
out({ items, pageCount: Math.ceil(total / perPage), counts });
|
|
10624
|
-
}
|
|
10706
|
+
var listItems = async (input) => {
|
|
10707
|
+
out(await api2.item.getItems.query(input));
|
|
10708
|
+
};
|
|
10709
|
+
var countItems = async (input) => {
|
|
10710
|
+
out(await api2.item.getItemCounts.query(input));
|
|
10711
|
+
};
|
|
10625
10712
|
async function getItem(id) {
|
|
10626
10713
|
const item = await api2.item.getItem.query({ id });
|
|
10627
10714
|
out(item);
|
|
10628
10715
|
}
|
|
10629
|
-
async
|
|
10630
|
-
const result = await api2.
|
|
10631
|
-
page: opts.page ?? 1,
|
|
10632
|
-
perPage: opts.perPage ?? 50
|
|
10633
|
-
});
|
|
10716
|
+
var getItemQuickBooksSyncStatus = async (itemId) => {
|
|
10717
|
+
const result = await api2.item.getQuickBooksSyncStatus.query({ id: itemId });
|
|
10634
10718
|
out(result);
|
|
10635
|
-
}
|
|
10636
|
-
async
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
|
|
10642
|
-
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
10719
|
+
};
|
|
10720
|
+
var listItemCategories = async (input) => {
|
|
10721
|
+
out(await api2.itemCategory.getItemCategories.query(input));
|
|
10722
|
+
};
|
|
10723
|
+
var countItemCategories = async (input) => {
|
|
10724
|
+
out(await api2.itemCategory.getCounts.query(input));
|
|
10725
|
+
};
|
|
10726
|
+
var getSupplierAnalytics = async (input) => {
|
|
10727
|
+
out(await api2.dashboard.getSupplierTableData.query(input));
|
|
10728
|
+
};
|
|
10729
|
+
var countSupplierAnalytics = async (input) => {
|
|
10730
|
+
out(await api2.dashboard.getSupplierTableCounts.query(input));
|
|
10731
|
+
};
|
|
10646
10732
|
async function createUser(input) {
|
|
10647
10733
|
const user = await api2.user.create.mutate(input);
|
|
10648
10734
|
out(user);
|
|
@@ -10659,10 +10745,12 @@ async function revokeApiKeyForUser(input) {
|
|
|
10659
10745
|
const result = await api2.mcpApiKey.revoke.mutate(input);
|
|
10660
10746
|
out(result);
|
|
10661
10747
|
}
|
|
10662
|
-
async
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10748
|
+
var listUsers = async (input) => {
|
|
10749
|
+
out(await api2.user.searchUsers.query(input));
|
|
10750
|
+
};
|
|
10751
|
+
var countUsers = async (input) => {
|
|
10752
|
+
out(await api2.user.getCounts.query(input));
|
|
10753
|
+
};
|
|
10666
10754
|
async function whoAmI() {
|
|
10667
10755
|
const user = await api2.user.getCurrentUser.query();
|
|
10668
10756
|
out(user);
|
|
@@ -10726,33 +10814,34 @@ async function getFinancialOverview(input) {
|
|
|
10726
10814
|
});
|
|
10727
10815
|
out(result);
|
|
10728
10816
|
}
|
|
10729
|
-
async
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
});
|
|
10736
|
-
out(result);
|
|
10737
|
-
}
|
|
10817
|
+
var getRecentErrors = async (input) => {
|
|
10818
|
+
out(await api2.errorLog.getRecentErrors.query(input));
|
|
10819
|
+
};
|
|
10820
|
+
var countErrors = async (input) => {
|
|
10821
|
+
out(await api2.errorLog.countErrors.query(input));
|
|
10822
|
+
};
|
|
10738
10823
|
async function getErrorMetrics() {
|
|
10739
10824
|
const result = await api2.errorLog.getErrorMetrics.query({});
|
|
10740
10825
|
out(result);
|
|
10741
10826
|
}
|
|
10742
10827
|
async function getApprovedBudgets(opts) {
|
|
10743
|
-
const
|
|
10744
|
-
const { budgets, totalCount } = await api2.budget.getAllBudgets.query({
|
|
10828
|
+
const filters = {
|
|
10745
10829
|
projectId: opts.projectId,
|
|
10746
10830
|
statuses: [
|
|
10747
10831
|
ExtendedBudgetStatus.APPROVED,
|
|
10748
10832
|
ExtendedBudgetStatus.ESTIMATE_ACCEPTED,
|
|
10749
10833
|
ExtendedBudgetStatus.ESTIMATE_CLOSED
|
|
10750
|
-
]
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10834
|
+
]
|
|
10835
|
+
};
|
|
10836
|
+
const [{ items: budgets }, { totalCount }] = await Promise.all([
|
|
10837
|
+
api2.budget.getAllBudgets.query({
|
|
10838
|
+
...filters,
|
|
10839
|
+
limit: Math.min(opts.limit ?? 50, 100),
|
|
10840
|
+
includeDetails: false
|
|
10841
|
+
}),
|
|
10842
|
+
api2.budget.getCounts.query(filters)
|
|
10843
|
+
]);
|
|
10844
|
+
const items = budgets.map((b) => {
|
|
10756
10845
|
const calc = b;
|
|
10757
10846
|
const revenue = calc.totalSellingAfterDiscount ?? 0;
|
|
10758
10847
|
const cost = calc.totalCostWithoutGst ?? 0;
|
|
@@ -10840,7 +10929,7 @@ function parseArgs(argv) {
|
|
|
10840
10929
|
}
|
|
10841
10930
|
}
|
|
10842
10931
|
} else if (arg === "-q") {
|
|
10843
|
-
flags.
|
|
10932
|
+
flags.quiet = true;
|
|
10844
10933
|
} else {
|
|
10845
10934
|
positional.push(arg);
|
|
10846
10935
|
}
|
|
@@ -11192,6 +11281,7 @@ var financialWriteTargets = new Set([
|
|
|
11192
11281
|
]);
|
|
11193
11282
|
var deleteTargets = new Set([
|
|
11194
11283
|
"cleanup-staged-bill-attachments",
|
|
11284
|
+
"delete-webhook-endpoint",
|
|
11195
11285
|
"cleanup-staged-quotation-attachments",
|
|
11196
11286
|
"discard-customer-invoice",
|
|
11197
11287
|
"complete-project",
|
|
@@ -11200,7 +11290,14 @@ var deleteTargets = new Set([
|
|
|
11200
11290
|
"restore-budget-version",
|
|
11201
11291
|
"update-project-status"
|
|
11202
11292
|
]);
|
|
11293
|
+
var explicitEffects = {
|
|
11294
|
+
"rotate-webhook-secret": ["state-change"],
|
|
11295
|
+
"replay-webhook-delivery": ["state-change", "external-write"]
|
|
11296
|
+
};
|
|
11203
11297
|
var effectsFor = (legacyTarget) => {
|
|
11298
|
+
const explicit = explicitEffects[legacyTarget];
|
|
11299
|
+
if (explicit)
|
|
11300
|
+
return explicit;
|
|
11204
11301
|
const effects = new Set;
|
|
11205
11302
|
if (mutationPrefixes.some((prefix) => legacyTarget.startsWith(prefix))) {
|
|
11206
11303
|
effects.add("state-change");
|
|
@@ -11218,16 +11315,56 @@ var effectsFor = (legacyTarget) => {
|
|
|
11218
11315
|
};
|
|
11219
11316
|
var titleCase = (value) => value.split("-").map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`).join(" ");
|
|
11220
11317
|
var summaryFor = (legacyTarget) => {
|
|
11318
|
+
if (legacyTarget === "update-budget-status")
|
|
11319
|
+
return "Update budget status. APPROVED requires a current Lead/Admin role; budget management permission alone is insufficient. Ordinary users must request approval. Status changes invalidate old pending requests.";
|
|
11320
|
+
if (legacyTarget === "approve-budget" || legacyTarget === "reject-budget")
|
|
11321
|
+
return "Decide your assigned pending budget approval as a current Lead/Admin. Material edits supersede old requests; inspect the latest content and use a fresh request after edits.";
|
|
11322
|
+
if (legacyTarget === "create-budget-approval")
|
|
11323
|
+
return "Request budget approval for the current content, superseding older pending requests. Existing Lead/Admin autoapproval remains available.";
|
|
11324
|
+
if (legacyTarget === "update-budget-item-supplier")
|
|
11325
|
+
return "Change a budget item's eligible supplier/GST snapshot as a material financial edit. Supersede pending approvals and apply the standard budget-to-DRAFT reset policy; inspect and request approval again. An unchanged supplier is a no-op.";
|
|
11326
|
+
if (legacyTarget === "submit-quotation")
|
|
11327
|
+
return "Submit a quotation for signing and approval. Claim the captured revision and exact allocation selection; concurrent edits, budget-item deletion or restore cascades conflict instead of attaching old signed PDFs. Refresh and resubmit the current content.";
|
|
11328
|
+
if (legacyTarget === "approve-quotation")
|
|
11329
|
+
return "Approve your assigned pending quotation as a current Admin. Claim the captured revision and exact allocation selection after signing; concurrent changes conflict and roll back the decision, signed attachment and email/outbox. Refresh and review the current content before retrying.";
|
|
11221
11330
|
if (legacyTarget === "approve-supplier")
|
|
11222
11331
|
return "Approve a pending supplier request and send a requester reply email, or directly re-approve a rejected supplier as Admin/Lead without a pending request or email. QuickBooks is synchronized; archived suppliers remain archived. Argument: <supplierId>.";
|
|
11332
|
+
if (legacyTarget === "get-bill-attachments")
|
|
11333
|
+
return "List bill attachments with cursor pagination. <billId> [--limit 1-50] [--cursor <token>] Newest first. Returns { items, pageInfo }; follow nextCursor.";
|
|
11334
|
+
if (legacyTarget === "get-budget-categories")
|
|
11335
|
+
return "List budget categories with cursor pagination. [--q] [--limit 1-100] [--cursor <token>] Active categories, name A\u2013Z. Returns { items, pageInfo }; follow nextCursor with the same --q.";
|
|
11336
|
+
if (legacyTarget === "get-supplier-analytics")
|
|
11337
|
+
return "List supplier analytics rows with cursor pagination. [--name] [--status CSV] [--gstRegistered true|false] [--createdBy <text>] [--timeFrame ALL|LAST_YEAR|LAST_6_MONTHS|LAST_3_MONTHS|CUSTOM] [--startDate <ISO> --endDate <ISO>] [--sortBy name|gstRegistered|status|phone|email|updatedAt|createdAt] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward] Admin. Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.";
|
|
11338
|
+
if (legacyTarget === "list-api-keys")
|
|
11339
|
+
return "List API keys with cursor pagination. [--userId <userId>] [--limit 1-100] [--cursor <token>] (newest first, { items, pageInfo }; defaults to the caller; admin required for another user)";
|
|
11340
|
+
if (legacyTarget === "list-claims")
|
|
11341
|
+
return "List reimbursable claims with cursor pagination. Same flags as list-bills (--limit 1-100, --cursor, --direction forward|backward); ignores --isClaimable. Returns { items, pageInfo }.";
|
|
11342
|
+
if (legacyTarget === "list-bills")
|
|
11343
|
+
return "List bills with cursor pagination. [--projectId] [--budgetId] [--status CSV] [--search <text>] [--isClaimable true|false] [--createdByIds <csv>] [--sortBy createdAt|amount|status] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward] Returns { items, pageInfo }; pass nextCursor with --direction forward or previousCursor with --direction backward, keeping the same filters and sort. --page/--pageSize/--perPage are rejected.";
|
|
11344
|
+
if (legacyTarget === "list-customer-invoices")
|
|
11345
|
+
return "List customer invoice batches with cursor pagination. [budgetId] [--projectId <id>] [--companyIds CSV] [--projectIds CSV] [--budgetIds CSV] [--createdByIds CSV] [--status CSV] [--search] [--sortBy createdAt|status|totalInvoiceAmount|approvalExpiresAt] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward] Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected. No scope flag lists invoices globally. --projectId uses the project scope. A positional budgetId is a backward-compatible shortcut for --budgetIds.";
|
|
11346
|
+
if (legacyTarget === "list-quotations")
|
|
11347
|
+
return "List quotations with cursor pagination. [--projectId] [--budgetId] [--supplierId] [--status CSV] [--createdBy CSV] [--search] [--limit 1-100] [--cursor <token>] [--direction forward|backward] Newest first; returns { items, pageInfo }. Follow nextCursor/previousCursor with the same filters. --page/--pageSize/--perPage are rejected; --requesterIds remains an alias for --createdBy.";
|
|
11348
|
+
if (legacyTarget === "list-users")
|
|
11349
|
+
return "List users with cursor pagination. [--q] [--limit 1-100] [--cursor <token>] Name A\u2013Z. Returns { items, pageInfo }; follow nextCursor with the same --q. --page/--perPage are rejected.";
|
|
11350
|
+
if (legacyTarget === "list-companies")
|
|
11351
|
+
return "List companies with cursor pagination. Returns { items, pageInfo }; default sort is createdAt descending with limit 20. Pass nextCursor forward or previousCursor backward unchanged. Legacy page/perPage flags are rejected.";
|
|
11352
|
+
if (legacyTarget === "count-companies")
|
|
11353
|
+
return "Count companies independently from list pagination. Returns { totalCount, counts: { active: { true, false } } }; accepts filters only and rejects pagination/sorting flags.";
|
|
11354
|
+
if (legacyTarget === "list-projects")
|
|
11355
|
+
return "List projects with cursor pagination. Returns { items, pageInfo }; default sort is createdAt descending with limit 20. Supports legacy --status plus optional --statuses, WON-date filters (--wonFrom, --wonTo, --wonWithinDays) and --sortBy wonAt; pass nextCursor forward or previousCursor backward unchanged. Legacy page/perPage flags are rejected.";
|
|
11356
|
+
if (legacyTarget === "count-projects")
|
|
11357
|
+
return "Count projects independently from list pagination. Returns { totalCount, counts: { status, active: { true, false } } }; accepts project filters only and rejects pagination/sorting flags.";
|
|
11223
11358
|
if (legacyTarget === "search-existing-companies")
|
|
11224
|
-
return "Search BB and QuickBooks companies without writes. --query <name> [--
|
|
11359
|
+
return "Search BB and QuickBooks companies without writes. --query <name> [--limit 1-50] [--cursor <token>]. Returns { items, totalCount, pageInfo }; follow pageInfo.nextCursor with the same --query. Legacy --page is rejected.";
|
|
11225
11360
|
if (legacyTarget === "use-existing-company")
|
|
11226
11361
|
return "Reuse a company in BB and QuickBooks, creating only its missing counterpart. Supply --companyId <bbId> and/or --quickbooksId <qboId>; both explicitly connect records with different names. --website <url> fills a missing QBO import website only. --confirmDistinct true confirms no similar record represents this entity.";
|
|
11227
11362
|
if (legacyTarget === "create-company")
|
|
11228
11363
|
return "Create or reuse a company in BB and QuickBooks. --name <name> --website <url>. Similar names require --confirmDistinct true; inactive companies are never reactivated.";
|
|
11229
11364
|
if (legacyTarget === "create-project")
|
|
11230
11365
|
return "Create a project linked to an existing Asana Deals lead task. Supply --asanaTaskId in non-interactive use; interactive use searches for and selects a lead task (optionally --asanaSearch). The Slack channel is resolved from the selected Asana task unless all three Slack channel flags are supplied. For a new direct client, create the lead task using the website form first.";
|
|
11366
|
+
if (legacyTarget === "create-supplier")
|
|
11367
|
+
return "Create a supplier using --payload JSON; pending-approval suppliers also request approval and send emails. Reusing an archived name requires Admin; normal users and Leads must ask an Admin to reactivate it before editing. Recreation preserves the existing approval status and creator.";
|
|
11231
11368
|
if (legacyTarget === "preview-qbo-customer-invoice") {
|
|
11232
11369
|
return "Preview an available QuickBooks invoice selected for a BB budget using read-only QBO access. Arguments: <budgetId> <qboInvoiceId>.";
|
|
11233
11370
|
}
|
|
@@ -11243,8 +11380,22 @@ var summaryFor = (legacyTarget) => {
|
|
|
11243
11380
|
if (legacyTarget === "whoami")
|
|
11244
11381
|
return "Show the active API-key identity.";
|
|
11245
11382
|
if (legacyTarget === "list-budgets") {
|
|
11246
|
-
return "List budgets. Omit --active for active budgets only; use --active false or --active all for Admin-only historical reads.";
|
|
11247
|
-
}
|
|
11383
|
+
return "List one cursor page of budgets ({ items, pageInfo }; --limit/--cursor/--direction). Omit --active for active budgets only; use --active false or --active all for Admin-only historical reads.";
|
|
11384
|
+
}
|
|
11385
|
+
if (legacyTarget === "list-items")
|
|
11386
|
+
return "List one cursor page of catalogue items ({ items, pageInfo }; --limit/--cursor/--direction, optional --sortBy/--sortDir). --page/--perPage are rejected.";
|
|
11387
|
+
if (legacyTarget === "list-item-categories")
|
|
11388
|
+
return "List one cursor page of active item categories ({ items, pageInfo }; --limit/--cursor/--direction, optional --name/--sortBy/--sortDir). --page/--perPage are rejected.";
|
|
11389
|
+
if (legacyTarget === "count-item-categories")
|
|
11390
|
+
return "Count active item categories matching --name: { totalCount }.";
|
|
11391
|
+
if (legacyTarget === "list-integration-operations")
|
|
11392
|
+
return "List one cursor page of integration operations, newest first ({ items, pageInfo }; --limit/--cursor/--direction). --page/--perPage are rejected. Admin only.";
|
|
11393
|
+
if (legacyTarget === "count-integration-operations")
|
|
11394
|
+
return "Count integration operations matching filters: { totalCount, filterOptions }. Admin only.";
|
|
11395
|
+
if (legacyTarget === "count-items")
|
|
11396
|
+
return "Count catalogue items matching filters: total plus category and supplier facets (each ignores its own filter).";
|
|
11397
|
+
if (legacyTarget === "count-budgets")
|
|
11398
|
+
return "Count budgets matching filters: totalCount plus status and active facets. Omit --active for active budgets only.";
|
|
11248
11399
|
if (legacyTarget === "get-budget") {
|
|
11249
11400
|
return "Get a budget by ID. Omit --includeInactive for active budgets only; --includeInactive is an Admin-only historical read.";
|
|
11250
11401
|
}
|
|
@@ -11270,6 +11421,8 @@ var summaryFor = (legacyTarget) => {
|
|
|
11270
11421
|
if (legacyTarget === "create-quotation") {
|
|
11271
11422
|
return 'Create a quotation with an approved supplier using --payload JSON. Include projectId, budgetId, supplierId, budgetItemIds, amountWithoutGst, gstAmount, and one uploaded attachment in attachments. Multiple budget items require lineAmounts: [{"budgetItemId":"<first-id>","amount":750},{"budgetItemId":"<second-id>","amount":450}], covering every selected budget-item ID exactly once and summing to amountWithoutGst. Amounts exclude GST; use gstAmount: 0 for no GST. Example: amountWithoutGst: 1200 with line amounts 750 and 450.';
|
|
11272
11423
|
}
|
|
11424
|
+
if (legacyTarget === "cleanup-staged-quotation-attachments")
|
|
11425
|
+
return "Queue independent cleanup operations for unattached staged quotation uploads; returns operation IDs and queued/skipped counts, not deletion confirmation. Arguments: <projectId> --keys <csv>.";
|
|
11273
11426
|
if (legacyTarget === "update-quotation") {
|
|
11274
11427
|
return 'Update a DRAFT or REJECTED quotation using --payload JSON with id and the complete creation payload. Multiple budget items require lineAmounts: [{"budgetItemId":"<first-id>","amount":750},{"budgetItemId":"<second-id>","amount":450}], covering every budgetItemIds entry exactly once and summing to amountWithoutGst. Amounts exclude GST; use gstAmount: 0 for no GST.';
|
|
11275
11428
|
}
|
|
@@ -11279,6 +11432,30 @@ var summaryFor = (legacyTarget) => {
|
|
|
11279
11432
|
if (legacyTarget === "send-customer-invoice-to-contact-person") {
|
|
11280
11433
|
return "Send a customer invoice and update the project billing email.";
|
|
11281
11434
|
}
|
|
11435
|
+
if (legacyTarget === "update-company")
|
|
11436
|
+
return "Save company fields in BB and queue independent QuickBooks name/website synchronization; returns operation ID, not provider completion.";
|
|
11437
|
+
if (legacyTarget === "get-company-quickbooks-sync-status")
|
|
11438
|
+
return "Read saved company synchronization status without provider calls or polling; use companyId.";
|
|
11439
|
+
if (legacyTarget === "get-item-quickbooks-sync-status")
|
|
11440
|
+
return "Read saved item QuickBooks synchronization status without provider calls or polling; use itemId.";
|
|
11441
|
+
if (legacyTarget === "create-webhook-endpoint")
|
|
11442
|
+
return "Admin-only: subscribe an HTTPS endpoint to BB events. --name --url --events <type|prefix.*|*,...>. Prints the whsec_ signing secret once; deliveries use Standard Webhooks headers.";
|
|
11443
|
+
if (legacyTarget === "rotate-webhook-secret")
|
|
11444
|
+
return "Admin-only: issue a new signing secret; older secrets keep signing for --previousSecretTtlHours (default 24). Prints the new secret once. Argument: <endpointId>.";
|
|
11445
|
+
if (legacyTarget === "send-webhook-test-event")
|
|
11446
|
+
return "Admin-only: send a signed webhook.test event to one endpoint. Argument: <endpointId>.";
|
|
11447
|
+
if (legacyTarget === "replay-webhook-delivery")
|
|
11448
|
+
return "Admin-only: resend a finished webhook delivery with the same eventId on a fresh attempt chain. Argument: <deliveryId>.";
|
|
11449
|
+
if (legacyTarget === "get-webhook-delivery")
|
|
11450
|
+
return "Admin-only: one webhook delivery with payload and attempts (status codes, errors, durations). Argument: <deliveryId>.";
|
|
11451
|
+
if (legacyTarget === "list-webhook-event-types")
|
|
11452
|
+
return "List the outbound webhook event catalogue with group and live/planned status.";
|
|
11453
|
+
if (legacyTarget === "reconcile-resource-operation")
|
|
11454
|
+
return "Admin-only check of a saved QuickBooks invoice/company/item job outcome; reads the provider only when uncertain. Applied changes are finished locally without repeating the provider mutation; provably unapplied ones are queued again. Argument: <operationId>.";
|
|
11455
|
+
if (legacyTarget === "get-integration-operation")
|
|
11456
|
+
return "Admin-only read of one integration job: who queued it, the records it is for with app links, saved QuickBooks progress, admin actions and Retry state. No provider calls. Argument: <operationId>.";
|
|
11457
|
+
if (legacyTarget === "retry-integration-operation")
|
|
11458
|
+
return "Admin-only retry of a failed integration job. QuickBooks jobs with a saved attempt check QuickBooks first: applied changes finish without resending, provably unapplied ones are sent again, unprovable ones stay stopped with the reason. Argument: <operationId>.";
|
|
11282
11459
|
if (legacyTarget.startsWith("list-")) {
|
|
11283
11460
|
return `List ${legacyTarget.slice("list-".length).replaceAll("-", " ")}.`;
|
|
11284
11461
|
}
|
|
@@ -11329,6 +11506,24 @@ var registry2 = [
|
|
|
11329
11506
|
authCommand("logout", "Revoke the interactive CLI session and remove its local credential."),
|
|
11330
11507
|
legacyCommand("whoami", ["auth", "whoami"]),
|
|
11331
11508
|
legacyCommand("list-budgets", ["budget", "list"], [], [
|
|
11509
|
+
{
|
|
11510
|
+
name: "--active <true|false|all>",
|
|
11511
|
+
description: "Omit for active budgets only; false or all requires Admin access."
|
|
11512
|
+
},
|
|
11513
|
+
{
|
|
11514
|
+
name: "--limit <1-100>",
|
|
11515
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11516
|
+
},
|
|
11517
|
+
{
|
|
11518
|
+
name: "--cursor <token>",
|
|
11519
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
11520
|
+
},
|
|
11521
|
+
{
|
|
11522
|
+
name: "--direction <forward|backward>",
|
|
11523
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
11524
|
+
}
|
|
11525
|
+
]),
|
|
11526
|
+
legacyCommand("count-budgets", ["budget", "count"], [], [
|
|
11332
11527
|
{
|
|
11333
11528
|
name: "--active <true|false|all>",
|
|
11334
11529
|
description: "Omit for active budgets only; false or all requires Admin access."
|
|
@@ -11354,7 +11549,20 @@ var registry2 = [
|
|
|
11354
11549
|
description: "Include inactive historical budgets; Admin only."
|
|
11355
11550
|
}
|
|
11356
11551
|
]),
|
|
11357
|
-
legacyCommand("get-budget-categories", ["budget", "category", "list"]
|
|
11552
|
+
legacyCommand("get-budget-categories", ["budget", "category", "list"], [], [
|
|
11553
|
+
{
|
|
11554
|
+
name: "--q <text>",
|
|
11555
|
+
description: "Search active category names (name A\u2013Z). A bare --q is rejected; use -q/--quiet to hide logs."
|
|
11556
|
+
},
|
|
11557
|
+
{
|
|
11558
|
+
name: "--limit <1-100>",
|
|
11559
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11560
|
+
},
|
|
11561
|
+
{
|
|
11562
|
+
name: "--cursor <token>",
|
|
11563
|
+
description: "pageInfo.nextCursor from the last page, unchanged; pages forward only."
|
|
11564
|
+
}
|
|
11565
|
+
]),
|
|
11358
11566
|
legacyCommand("get-budget-versions", ["budget", "version", "list"], [], [
|
|
11359
11567
|
{
|
|
11360
11568
|
name: "--limit <1-50>",
|
|
@@ -11414,8 +11622,36 @@ var registry2 = [
|
|
|
11414
11622
|
"placeholder-bill",
|
|
11415
11623
|
"create"
|
|
11416
11624
|
]),
|
|
11417
|
-
legacyCommand("list-bills", ["bill", "list"]
|
|
11418
|
-
|
|
11625
|
+
legacyCommand("list-bills", ["bill", "list"], [], [
|
|
11626
|
+
{
|
|
11627
|
+
name: "--limit <1-100>",
|
|
11628
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11629
|
+
},
|
|
11630
|
+
{
|
|
11631
|
+
name: "--cursor <token>",
|
|
11632
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
11633
|
+
},
|
|
11634
|
+
{
|
|
11635
|
+
name: "--direction <forward|backward>",
|
|
11636
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
11637
|
+
}
|
|
11638
|
+
]),
|
|
11639
|
+
legacyCommand("list-claims", ["claim", "list"], [], [
|
|
11640
|
+
{
|
|
11641
|
+
name: "--limit <1-100>",
|
|
11642
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11643
|
+
},
|
|
11644
|
+
{
|
|
11645
|
+
name: "--cursor <token>",
|
|
11646
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
11647
|
+
},
|
|
11648
|
+
{
|
|
11649
|
+
name: "--direction <forward|backward>",
|
|
11650
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
11651
|
+
}
|
|
11652
|
+
]),
|
|
11653
|
+
legacyCommand("count-bills", ["bill", "count"]),
|
|
11654
|
+
legacyCommand("count-claims", ["claim", "count"]),
|
|
11419
11655
|
legacyCommand("create-bill-approval", ["bill", "approval", "create"]),
|
|
11420
11656
|
legacyCommand("create-bill", ["bill", "create"], [], [
|
|
11421
11657
|
{
|
|
@@ -11471,7 +11707,16 @@ var registry2 = [
|
|
|
11471
11707
|
"invoice-number",
|
|
11472
11708
|
"patch"
|
|
11473
11709
|
]),
|
|
11474
|
-
legacyCommand("get-bill-attachments", ["bill", "attachment", "list"]
|
|
11710
|
+
legacyCommand("get-bill-attachments", ["bill", "attachment", "list"], [], [
|
|
11711
|
+
{
|
|
11712
|
+
name: "--limit <1-50>",
|
|
11713
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11714
|
+
},
|
|
11715
|
+
{
|
|
11716
|
+
name: "--cursor <token>",
|
|
11717
|
+
description: "pageInfo.nextCursor from the last page, unchanged; pages forward only."
|
|
11718
|
+
}
|
|
11719
|
+
]),
|
|
11475
11720
|
legacyCommand("stage-bill-attachment", ["bill", "attachment", "stage"]),
|
|
11476
11721
|
legacyCommand("cleanup-staged-bill-attachments", [
|
|
11477
11722
|
"bill",
|
|
@@ -11487,7 +11732,21 @@ var registry2 = [
|
|
|
11487
11732
|
]),
|
|
11488
11733
|
legacyCommand("attach-bill-documents", ["bill", "document", "attach"]),
|
|
11489
11734
|
legacyCommand("get-bill-details", ["bill", "get"]),
|
|
11490
|
-
legacyCommand("list-quotations", ["quotation", "list"]
|
|
11735
|
+
legacyCommand("list-quotations", ["quotation", "list"], [], [
|
|
11736
|
+
{
|
|
11737
|
+
name: "--limit <1-100>",
|
|
11738
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11739
|
+
},
|
|
11740
|
+
{
|
|
11741
|
+
name: "--cursor <token>",
|
|
11742
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
11743
|
+
},
|
|
11744
|
+
{
|
|
11745
|
+
name: "--direction <forward|backward>",
|
|
11746
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
11747
|
+
}
|
|
11748
|
+
]),
|
|
11749
|
+
legacyCommand("count-quotations", ["quotation", "count"]),
|
|
11491
11750
|
legacyCommand("get-quotation", ["quotation", "get"]),
|
|
11492
11751
|
legacyCommand("upload-quotation-attachment", [
|
|
11493
11752
|
"quotation",
|
|
@@ -11539,7 +11798,21 @@ var registry2 = [
|
|
|
11539
11798
|
"existing",
|
|
11540
11799
|
"list"
|
|
11541
11800
|
]),
|
|
11542
|
-
legacyCommand("list-customer-invoices", ["customer-invoice", "list"]
|
|
11801
|
+
legacyCommand("list-customer-invoices", ["customer-invoice", "list"], [], [
|
|
11802
|
+
{
|
|
11803
|
+
name: "--limit <1-100>",
|
|
11804
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
11805
|
+
},
|
|
11806
|
+
{
|
|
11807
|
+
name: "--cursor <token>",
|
|
11808
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
11809
|
+
},
|
|
11810
|
+
{
|
|
11811
|
+
name: "--direction <forward|backward>",
|
|
11812
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
11813
|
+
}
|
|
11814
|
+
]),
|
|
11815
|
+
legacyCommand("count-customer-invoices", ["customer-invoice", "count"]),
|
|
11543
11816
|
legacyCommand("get-customer-invoice", ["customer-invoice", "get"]),
|
|
11544
11817
|
legacyCommand("get-customer-invoice-email-context", [
|
|
11545
11818
|
"customer-invoice",
|
|
@@ -11578,7 +11851,62 @@ var registry2 = [
|
|
|
11578
11851
|
legacyCommand("approve-supplier", ["supplier", "approve"]),
|
|
11579
11852
|
legacyCommand("reject-supplier", ["supplier", "reject"]),
|
|
11580
11853
|
legacyCommand("get-supplier-details", ["supplier", "detail", "get"]),
|
|
11581
|
-
legacyCommand("list-companies", ["company", "list"]
|
|
11854
|
+
legacyCommand("list-companies", ["company", "list"], [], [
|
|
11855
|
+
{
|
|
11856
|
+
name: "--name <text>",
|
|
11857
|
+
description: "Filter by company name substring."
|
|
11858
|
+
},
|
|
11859
|
+
{
|
|
11860
|
+
name: "--createdBy <userId>",
|
|
11861
|
+
description: "Filter by one creator user ID."
|
|
11862
|
+
},
|
|
11863
|
+
{
|
|
11864
|
+
name: "--createdByIds <csv>",
|
|
11865
|
+
description: "Filter by a comma-separated creator user ID list."
|
|
11866
|
+
},
|
|
11867
|
+
{
|
|
11868
|
+
name: "--active <true|false>",
|
|
11869
|
+
description: "Filter by active status; omit to include both states."
|
|
11870
|
+
},
|
|
11871
|
+
{
|
|
11872
|
+
name: "--sortBy <name|createdAt>",
|
|
11873
|
+
description: "Sort field (default createdAt)."
|
|
11874
|
+
},
|
|
11875
|
+
{
|
|
11876
|
+
name: "--sortDir <asc|desc>",
|
|
11877
|
+
description: "Sort direction (default desc)."
|
|
11878
|
+
},
|
|
11879
|
+
{
|
|
11880
|
+
name: "--limit <1-100>",
|
|
11881
|
+
description: "Bounded page size (default 20)."
|
|
11882
|
+
},
|
|
11883
|
+
{
|
|
11884
|
+
name: "--cursor <token>",
|
|
11885
|
+
description: "Opaque pageInfo cursor; pass nextCursor forward or previousCursor backward unchanged."
|
|
11886
|
+
},
|
|
11887
|
+
{
|
|
11888
|
+
name: "--direction <forward|backward>",
|
|
11889
|
+
description: "Use forward by default; backward requires --cursor."
|
|
11890
|
+
}
|
|
11891
|
+
]),
|
|
11892
|
+
legacyCommand("count-companies", ["company", "count"], [], [
|
|
11893
|
+
{
|
|
11894
|
+
name: "--name <text>",
|
|
11895
|
+
description: "Filter by company name substring."
|
|
11896
|
+
},
|
|
11897
|
+
{
|
|
11898
|
+
name: "--createdBy <userId>",
|
|
11899
|
+
description: "Filter by one creator user ID."
|
|
11900
|
+
},
|
|
11901
|
+
{
|
|
11902
|
+
name: "--createdByIds <csv>",
|
|
11903
|
+
description: "Filter by a comma-separated creator user ID list."
|
|
11904
|
+
},
|
|
11905
|
+
{
|
|
11906
|
+
name: "--active <true|false>",
|
|
11907
|
+
description: "Filter by active status; facets omit this self-filter."
|
|
11908
|
+
}
|
|
11909
|
+
]),
|
|
11582
11910
|
legacyCommand("get-company", ["company", "get"]),
|
|
11583
11911
|
legacyCommand("search-existing-companies", ["company", "search"], [], [
|
|
11584
11912
|
{
|
|
@@ -11586,8 +11914,12 @@ var registry2 = [
|
|
|
11586
11914
|
description: "Company name to search in BB and QuickBooks."
|
|
11587
11915
|
},
|
|
11588
11916
|
{
|
|
11589
|
-
name: "--
|
|
11590
|
-
description: "
|
|
11917
|
+
name: "--limit",
|
|
11918
|
+
description: "Matches per page, 1\u201350 (default 8)."
|
|
11919
|
+
},
|
|
11920
|
+
{
|
|
11921
|
+
name: "--cursor",
|
|
11922
|
+
description: "pageInfo.nextCursor from the previous page, unchanged."
|
|
11591
11923
|
}
|
|
11592
11924
|
]),
|
|
11593
11925
|
legacyCommand("use-existing-company", ["company", "use"], [], [
|
|
@@ -11615,8 +11947,94 @@ var registry2 = [
|
|
|
11615
11947
|
}
|
|
11616
11948
|
]),
|
|
11617
11949
|
legacyCommand("update-company", ["company", "update"]),
|
|
11950
|
+
legacyCommand("get-company-quickbooks-sync-status", [
|
|
11951
|
+
"company",
|
|
11952
|
+
"sync",
|
|
11953
|
+
"status"
|
|
11954
|
+
]),
|
|
11618
11955
|
legacyCommand("delete-company", ["company", "delete"]),
|
|
11619
|
-
legacyCommand("list-projects", ["project", "list"]
|
|
11956
|
+
legacyCommand("list-projects", ["project", "list"], [], [
|
|
11957
|
+
{ name: "--companyId <id>", description: "Filter by company ID." },
|
|
11958
|
+
{
|
|
11959
|
+
name: "--name <text>",
|
|
11960
|
+
description: "Filter by project name substring."
|
|
11961
|
+
},
|
|
11962
|
+
{
|
|
11963
|
+
name: "--status <status|ALL>",
|
|
11964
|
+
description: "Legacy single-status filter; use --statuses for multiple statuses."
|
|
11965
|
+
},
|
|
11966
|
+
{
|
|
11967
|
+
name: "--statuses <csv>",
|
|
11968
|
+
description: "Filter by a comma-separated project status list."
|
|
11969
|
+
},
|
|
11970
|
+
{
|
|
11971
|
+
name: "--active <true|false>",
|
|
11972
|
+
description: "Filter by active status; omit to include both states."
|
|
11973
|
+
},
|
|
11974
|
+
{
|
|
11975
|
+
name: "--wonFrom <iso>",
|
|
11976
|
+
description: "Only projects marked WON on or after this ISO date or datetime (UTC)."
|
|
11977
|
+
},
|
|
11978
|
+
{
|
|
11979
|
+
name: "--wonTo <iso>",
|
|
11980
|
+
description: "Only projects marked WON on or before this ISO date (inclusive) or datetime (UTC)."
|
|
11981
|
+
},
|
|
11982
|
+
{
|
|
11983
|
+
name: "--wonWithinDays <1-3650>",
|
|
11984
|
+
description: "Only projects marked WON in the last N days."
|
|
11985
|
+
},
|
|
11986
|
+
{
|
|
11987
|
+
name: "--limit <1-100>",
|
|
11988
|
+
description: "Bounded page size (default 20)."
|
|
11989
|
+
},
|
|
11990
|
+
{
|
|
11991
|
+
name: "--cursor <token>",
|
|
11992
|
+
description: "Opaque pageInfo cursor; pass nextCursor forward or previousCursor backward unchanged."
|
|
11993
|
+
},
|
|
11994
|
+
{
|
|
11995
|
+
name: "--direction <forward|backward>",
|
|
11996
|
+
description: "Use forward by default; backward requires --cursor."
|
|
11997
|
+
},
|
|
11998
|
+
{
|
|
11999
|
+
name: "--sortBy <name|createdAt|status|companyName|wonAt>",
|
|
12000
|
+
description: "Sort field (default createdAt); wonAt puts unwon projects last."
|
|
12001
|
+
},
|
|
12002
|
+
{
|
|
12003
|
+
name: "--sortDir <asc|desc>",
|
|
12004
|
+
description: "Sort direction (default desc)."
|
|
12005
|
+
}
|
|
12006
|
+
]),
|
|
12007
|
+
legacyCommand("count-projects", ["project", "count"], [], [
|
|
12008
|
+
{ name: "--companyId <id>", description: "Filter by company ID." },
|
|
12009
|
+
{
|
|
12010
|
+
name: "--name <text>",
|
|
12011
|
+
description: "Filter by project name substring."
|
|
12012
|
+
},
|
|
12013
|
+
{
|
|
12014
|
+
name: "--status <status|ALL>",
|
|
12015
|
+
description: "Legacy single-status filter."
|
|
12016
|
+
},
|
|
12017
|
+
{
|
|
12018
|
+
name: "--statuses <csv>",
|
|
12019
|
+
description: "Filter by a comma-separated project status list."
|
|
12020
|
+
},
|
|
12021
|
+
{
|
|
12022
|
+
name: "--active <true|false>",
|
|
12023
|
+
description: "Filter by active status; facets exclude this self-filter."
|
|
12024
|
+
},
|
|
12025
|
+
{
|
|
12026
|
+
name: "--wonFrom <iso>",
|
|
12027
|
+
description: "Only projects marked WON on or after this ISO date or datetime (UTC)."
|
|
12028
|
+
},
|
|
12029
|
+
{
|
|
12030
|
+
name: "--wonTo <iso>",
|
|
12031
|
+
description: "Only projects marked WON on or before this ISO date (inclusive) or datetime (UTC)."
|
|
12032
|
+
},
|
|
12033
|
+
{
|
|
12034
|
+
name: "--wonWithinDays <1-3650>",
|
|
12035
|
+
description: "Only projects marked WON in the last N days."
|
|
12036
|
+
}
|
|
12037
|
+
]),
|
|
11620
12038
|
legacyCommand("list-project-hubs", ["project", "hub", "list"], [], [
|
|
11621
12039
|
{
|
|
11622
12040
|
name: "--q",
|
|
@@ -11626,14 +12044,31 @@ var registry2 = [
|
|
|
11626
12044
|
name: "--status",
|
|
11627
12045
|
description: "Filter by comma-separated project statuses."
|
|
11628
12046
|
},
|
|
11629
|
-
{ name: "--
|
|
11630
|
-
{
|
|
12047
|
+
{ name: "--limit", description: "Page size, 1-100 (default 20)." },
|
|
12048
|
+
{
|
|
12049
|
+
name: "--cursor",
|
|
12050
|
+
description: "Opaque nextCursor/previousCursor from the last page."
|
|
12051
|
+
},
|
|
12052
|
+
{
|
|
12053
|
+
name: "--direction",
|
|
12054
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
12055
|
+
},
|
|
11631
12056
|
{
|
|
11632
12057
|
name: "--sortBy",
|
|
11633
12058
|
description: "Sort by startDate, name, companyName, or status."
|
|
11634
12059
|
},
|
|
11635
12060
|
{ name: "--sortDir", description: "Sort in asc or desc order." }
|
|
11636
12061
|
]),
|
|
12062
|
+
legacyCommand("count-project-hubs", ["project", "hub", "count"], [], [
|
|
12063
|
+
{
|
|
12064
|
+
name: "--q",
|
|
12065
|
+
description: "Search project and company names."
|
|
12066
|
+
},
|
|
12067
|
+
{
|
|
12068
|
+
name: "--status",
|
|
12069
|
+
description: "Filter by comma-separated project statuses."
|
|
12070
|
+
}
|
|
12071
|
+
]),
|
|
11637
12072
|
legacyCommand("get-project", ["project", "get"]),
|
|
11638
12073
|
legacyCommand("get-project-hub-status", ["project", "hub", "status"]),
|
|
11639
12074
|
legacyCommand("setup-project-hub", ["project", "hub", "setup"]),
|
|
@@ -11657,7 +12092,67 @@ var registry2 = [
|
|
|
11657
12092
|
legacyCommand("list-contacts", ["contact", "list"]),
|
|
11658
12093
|
legacyCommand("create-contact-person", ["contact", "create"]),
|
|
11659
12094
|
legacyCommand("update-contact-person", ["contact", "update"]),
|
|
11660
|
-
legacyCommand("list-suppliers", ["supplier", "list"]
|
|
12095
|
+
legacyCommand("list-suppliers", ["supplier", "list"], [], [
|
|
12096
|
+
{ name: "--name <text>", description: "Filter supplier name or email." },
|
|
12097
|
+
{ name: "--createdBy <csv>", description: "Filter by creator IDs." },
|
|
12098
|
+
{
|
|
12099
|
+
name: "--gstRegistered <true|false>",
|
|
12100
|
+
description: "Filter GST registration."
|
|
12101
|
+
},
|
|
12102
|
+
{
|
|
12103
|
+
name: "--status <csv>",
|
|
12104
|
+
description: "Filter approval statuses; ALL means no status filter."
|
|
12105
|
+
},
|
|
12106
|
+
{
|
|
12107
|
+
name: "--supplierTags <csv>",
|
|
12108
|
+
description: "Filter by supplier tag IDs."
|
|
12109
|
+
},
|
|
12110
|
+
{
|
|
12111
|
+
name: "--active <true|false>",
|
|
12112
|
+
description: "Active by default; false selects archived."
|
|
12113
|
+
},
|
|
12114
|
+
{
|
|
12115
|
+
name: "--limit <1-100>",
|
|
12116
|
+
description: "Bounded page size (default 10). Retired page/perPage flags are rejected."
|
|
12117
|
+
},
|
|
12118
|
+
{
|
|
12119
|
+
name: "--cursor <token>",
|
|
12120
|
+
description: "Opaque nextCursor or previousCursor from items/pageInfo."
|
|
12121
|
+
},
|
|
12122
|
+
{
|
|
12123
|
+
name: "--direction <forward|backward>",
|
|
12124
|
+
description: "Forward by default; backward requires a cursor."
|
|
12125
|
+
},
|
|
12126
|
+
{
|
|
12127
|
+
name: "--sortBy <field>",
|
|
12128
|
+
description: "name, email, phone, gstRegistered, status, active, createdAt or updatedAt."
|
|
12129
|
+
},
|
|
12130
|
+
{
|
|
12131
|
+
name: "--sortDir <asc|desc>",
|
|
12132
|
+
description: "Descending createdAt by default."
|
|
12133
|
+
},
|
|
12134
|
+
{
|
|
12135
|
+
name: "--sort <json>",
|
|
12136
|
+
description: "Ordered {id,desc} array for multi-column sorting; cannot combine with sortBy/sortDir."
|
|
12137
|
+
}
|
|
12138
|
+
]),
|
|
12139
|
+
legacyCommand("count-suppliers", ["supplier", "count"], [], [
|
|
12140
|
+
{ name: "--name <text>", description: "Filter supplier name or email." },
|
|
12141
|
+
{ name: "--createdBy <csv>", description: "Filter by creator IDs." },
|
|
12142
|
+
{
|
|
12143
|
+
name: "--gstRegistered <true|false>",
|
|
12144
|
+
description: "Filter GST registration."
|
|
12145
|
+
},
|
|
12146
|
+
{ name: "--status <csv>", description: "Filter approval statuses." },
|
|
12147
|
+
{
|
|
12148
|
+
name: "--supplierTags <csv>",
|
|
12149
|
+
description: "Filter by supplier tag IDs."
|
|
12150
|
+
},
|
|
12151
|
+
{
|
|
12152
|
+
name: "--active <true|false>",
|
|
12153
|
+
description: "Active by default; false selects archived. No pagination/sort flags."
|
|
12154
|
+
}
|
|
12155
|
+
]),
|
|
11661
12156
|
legacyCommand("create-supplier", ["supplier", "create"]),
|
|
11662
12157
|
legacyCommand("update-supplier", ["supplier", "update"]),
|
|
11663
12158
|
legacyCommand("delete-suppliers", ["supplier", "delete"]),
|
|
@@ -11674,21 +12169,87 @@ var registry2 = [
|
|
|
11674
12169
|
]),
|
|
11675
12170
|
legacyCommand("create-supplier-role", ["supplier", "role", "create"]),
|
|
11676
12171
|
legacyCommand("create-supplier-tag", ["supplier", "tag", "create"]),
|
|
11677
|
-
legacyCommand("get-supplier-analytics", ["supplier", "analytics", "get"]
|
|
11678
|
-
|
|
12172
|
+
legacyCommand("get-supplier-analytics", ["supplier", "analytics", "get"], [], [
|
|
12173
|
+
{
|
|
12174
|
+
name: "--limit <1-100>",
|
|
12175
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12176
|
+
},
|
|
12177
|
+
{
|
|
12178
|
+
name: "--cursor <token>",
|
|
12179
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
12180
|
+
},
|
|
12181
|
+
{
|
|
12182
|
+
name: "--direction <forward|backward>",
|
|
12183
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
12184
|
+
}
|
|
12185
|
+
]),
|
|
12186
|
+
legacyCommand("count-supplier-analytics", ["supplier", "analytics", "count"]),
|
|
12187
|
+
legacyCommand("list-items", ["item", "list"], [], [
|
|
12188
|
+
{
|
|
12189
|
+
name: "--limit <1-100>",
|
|
12190
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12191
|
+
},
|
|
12192
|
+
{
|
|
12193
|
+
name: "--cursor <token>",
|
|
12194
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
12195
|
+
},
|
|
12196
|
+
{
|
|
12197
|
+
name: "--direction <forward|backward>",
|
|
12198
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
12199
|
+
}
|
|
12200
|
+
]),
|
|
12201
|
+
legacyCommand("count-items", ["item", "count"]),
|
|
11679
12202
|
legacyCommand("get-item", ["item", "get"]),
|
|
12203
|
+
legacyCommand("get-item-quickbooks-sync-status", ["item", "sync", "status"]),
|
|
11680
12204
|
legacyCommand("create-item", ["item", "create"]),
|
|
11681
12205
|
legacyCommand("update-item", ["item", "update"]),
|
|
11682
12206
|
legacyCommand("archive-items", ["item", "archive"]),
|
|
11683
12207
|
legacyCommand("delete-item", ["item", "delete"]),
|
|
11684
|
-
legacyCommand("list-item-categories", ["item", "category", "list"]
|
|
12208
|
+
legacyCommand("list-item-categories", ["item", "category", "list"], [], [
|
|
12209
|
+
{
|
|
12210
|
+
name: "--limit <1-100>",
|
|
12211
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12212
|
+
},
|
|
12213
|
+
{
|
|
12214
|
+
name: "--cursor <token>",
|
|
12215
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
12216
|
+
},
|
|
12217
|
+
{
|
|
12218
|
+
name: "--direction <forward|backward>",
|
|
12219
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
12220
|
+
}
|
|
12221
|
+
]),
|
|
12222
|
+
legacyCommand("count-item-categories", ["item", "category", "count"]),
|
|
11685
12223
|
legacyCommand("create-item-category", ["item", "category", "create"]),
|
|
11686
12224
|
legacyCommand("update-item-category", ["item", "category", "update"]),
|
|
11687
12225
|
legacyCommand("delete-item-categories", ["item", "category", "delete"]),
|
|
11688
|
-
legacyCommand("list-users", ["user", "list"]
|
|
12226
|
+
legacyCommand("list-users", ["user", "list"], [], [
|
|
12227
|
+
{
|
|
12228
|
+
name: "--q <text>",
|
|
12229
|
+
description: "Search user names and emails (name A\u2013Z). A bare --q is rejected; use -q/--quiet to hide logs."
|
|
12230
|
+
},
|
|
12231
|
+
{
|
|
12232
|
+
name: "--limit <1-100>",
|
|
12233
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12234
|
+
},
|
|
12235
|
+
{
|
|
12236
|
+
name: "--cursor <token>",
|
|
12237
|
+
description: "pageInfo.nextCursor from the last page, unchanged; pages forward only."
|
|
12238
|
+
}
|
|
12239
|
+
]),
|
|
12240
|
+
legacyCommand("count-users", ["user", "count"]),
|
|
11689
12241
|
legacyCommand("create-user", ["user", "create"]),
|
|
11690
12242
|
legacyCommand("create-api-key", ["user", "api-key", "create"]),
|
|
11691
|
-
legacyCommand("list-api-keys", ["user", "api-key", "list"]
|
|
12243
|
+
legacyCommand("list-api-keys", ["user", "api-key", "list"], [], [
|
|
12244
|
+
{
|
|
12245
|
+
name: "--limit <1-100>",
|
|
12246
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12247
|
+
},
|
|
12248
|
+
{
|
|
12249
|
+
name: "--cursor <token>",
|
|
12250
|
+
description: "pageInfo.nextCursor from the last page, unchanged; pages forward only."
|
|
12251
|
+
}
|
|
12252
|
+
]),
|
|
11692
12253
|
legacyCommand("revoke-api-key", ["user", "api-key", "revoke"]),
|
|
11693
12254
|
legacyCommand("get-user-performance", ["user", "performance", "get"]),
|
|
11694
12255
|
legacyCommand("get-dashboard", ["dashboard", "get"]),
|
|
@@ -11704,23 +12265,143 @@ var registry2 = [
|
|
|
11704
12265
|
"financial-overview",
|
|
11705
12266
|
"get"
|
|
11706
12267
|
]),
|
|
11707
|
-
legacyCommand("get-recent-errors", ["error", "recent", "list"]
|
|
12268
|
+
legacyCommand("get-recent-errors", ["error", "recent", "list"], [], [
|
|
12269
|
+
{
|
|
12270
|
+
name: "--cursor <token>",
|
|
12271
|
+
description: "Pass a returned pageInfo boundary unchanged, with the same filters."
|
|
12272
|
+
},
|
|
12273
|
+
{
|
|
12274
|
+
name: "--direction <direction>",
|
|
12275
|
+
description: "forward (default) uses nextCursor; backward uses previousCursor."
|
|
12276
|
+
},
|
|
12277
|
+
{
|
|
12278
|
+
name: "--limit <number>",
|
|
12279
|
+
description: "1\u2013100 rows (default 10). Returns items and pageInfo, without a total."
|
|
12280
|
+
},
|
|
12281
|
+
{ name: "--severity <severity>", description: "Error severity or ALL." },
|
|
12282
|
+
{ name: "--status <status>", description: "Error status or ALL." },
|
|
12283
|
+
{
|
|
12284
|
+
name: "--timeFrame <period>",
|
|
12285
|
+
description: "all_time (default), last_30_days, last_3_months, last_6_months or last_1_year."
|
|
12286
|
+
}
|
|
12287
|
+
]),
|
|
12288
|
+
legacyCommand("count-errors", ["error", "recent", "count"], [], [
|
|
12289
|
+
{ name: "--severity <severity>", description: "Error severity or ALL." },
|
|
12290
|
+
{ name: "--status <status>", description: "Error status or ALL." },
|
|
12291
|
+
{
|
|
12292
|
+
name: "--timeFrame <period>",
|
|
12293
|
+
description: "Same filters as error recent list; returns independent totalCount."
|
|
12294
|
+
}
|
|
12295
|
+
]),
|
|
11708
12296
|
legacyCommand("get-error-metrics", ["error", "metrics", "get"]),
|
|
11709
|
-
legacyCommand("list-integration-operations", [
|
|
12297
|
+
legacyCommand("list-integration-operations", ["integration", "operation", "list"], [], [
|
|
12298
|
+
{
|
|
12299
|
+
name: "--limit <1-100>",
|
|
12300
|
+
description: "Rows per page. Output is { items, pageInfo }."
|
|
12301
|
+
},
|
|
12302
|
+
{
|
|
12303
|
+
name: "--cursor <token>",
|
|
12304
|
+
description: "pageInfo.nextCursor (or previousCursor with --direction backward) from the last page, unchanged; keep the same filters and sort."
|
|
12305
|
+
},
|
|
12306
|
+
{
|
|
12307
|
+
name: "--direction <forward|backward>",
|
|
12308
|
+
description: "forward (default) or backward; backward needs --cursor."
|
|
12309
|
+
}
|
|
12310
|
+
]),
|
|
12311
|
+
legacyCommand("count-integration-operations", [
|
|
11710
12312
|
"integration",
|
|
11711
12313
|
"operation",
|
|
11712
|
-
"
|
|
12314
|
+
"count"
|
|
12315
|
+
]),
|
|
12316
|
+
legacyCommand("get-integration-operation", [
|
|
12317
|
+
"integration",
|
|
12318
|
+
"operation",
|
|
12319
|
+
"get"
|
|
11713
12320
|
]),
|
|
11714
12321
|
legacyCommand("retry-integration-operation", [
|
|
11715
12322
|
"integration",
|
|
11716
12323
|
"operation",
|
|
11717
12324
|
"retry"
|
|
11718
12325
|
]),
|
|
11719
|
-
legacyCommand("
|
|
12326
|
+
legacyCommand("reconcile-resource-operation", [
|
|
12327
|
+
"integration",
|
|
12328
|
+
"operation",
|
|
12329
|
+
"reconcile-resource"
|
|
12330
|
+
]),
|
|
12331
|
+
legacyCommand("list-webhook-event-types", ["webhook", "event-type", "list"]),
|
|
12332
|
+
legacyCommand("list-webhook-endpoints", ["webhook", "endpoint", "list"]),
|
|
12333
|
+
legacyCommand("get-webhook-endpoint", ["webhook", "endpoint", "get"]),
|
|
12334
|
+
legacyCommand("create-webhook-endpoint", ["webhook", "endpoint", "create"]),
|
|
12335
|
+
legacyCommand("update-webhook-endpoint", ["webhook", "endpoint", "update"]),
|
|
12336
|
+
legacyCommand("delete-webhook-endpoint", ["webhook", "endpoint", "delete"]),
|
|
12337
|
+
legacyCommand("rotate-webhook-secret", ["webhook", "secret", "rotate"]),
|
|
12338
|
+
legacyCommand("send-webhook-test-event", ["webhook", "endpoint", "test"]),
|
|
12339
|
+
legacyCommand("list-webhook-deliveries", ["webhook", "delivery", "list"]),
|
|
12340
|
+
legacyCommand("get-webhook-delivery", ["webhook", "delivery", "get"]),
|
|
12341
|
+
legacyCommand("replay-webhook-delivery", ["webhook", "delivery", "replay"]),
|
|
12342
|
+
legacyCommand("list-inbound-sources", ["inbound", "source", "list"], [], [
|
|
12343
|
+
{
|
|
12344
|
+
name: "--limit <n>",
|
|
12345
|
+
description: "Rows per cursor page (1..100; default 25)."
|
|
12346
|
+
},
|
|
12347
|
+
{
|
|
12348
|
+
name: "--cursor <token>",
|
|
12349
|
+
description: "Opaque source continuation token returned by pageInfo."
|
|
12350
|
+
},
|
|
12351
|
+
{
|
|
12352
|
+
name: "--direction <value>",
|
|
12353
|
+
description: "forward or backward (default forward; backward requires cursor)."
|
|
12354
|
+
},
|
|
12355
|
+
{
|
|
12356
|
+
name: "--search <text>",
|
|
12357
|
+
description: "Search source name or Typeform form ID."
|
|
12358
|
+
},
|
|
12359
|
+
{
|
|
12360
|
+
name: "--processingEnabled <boolean>",
|
|
12361
|
+
description: "Filter processing enabled state."
|
|
12362
|
+
},
|
|
12363
|
+
{
|
|
12364
|
+
name: "--processingMode <mode>",
|
|
12365
|
+
description: "ACTIVE, COLLECT_ONLY or SHADOW."
|
|
12366
|
+
}
|
|
12367
|
+
]),
|
|
12368
|
+
legacyCommand("count-inbound-sources", ["inbound", "source", "count"], [], [
|
|
12369
|
+
{
|
|
12370
|
+
name: "--search <text>",
|
|
12371
|
+
description: "Search source name or Typeform form ID."
|
|
12372
|
+
},
|
|
12373
|
+
{
|
|
12374
|
+
name: "--processingEnabled <boolean>",
|
|
12375
|
+
description: "Filter processing enabled state."
|
|
12376
|
+
},
|
|
12377
|
+
{
|
|
12378
|
+
name: "--processingMode <mode>",
|
|
12379
|
+
description: "ACTIVE, COLLECT_ONLY or SHADOW."
|
|
12380
|
+
}
|
|
12381
|
+
]),
|
|
11720
12382
|
legacyCommand("create-inbound-source", ["inbound", "source", "create"]),
|
|
11721
12383
|
legacyCommand("get-inbound-source", ["inbound", "source", "get"]),
|
|
11722
12384
|
legacyCommand("update-inbound-source", ["inbound", "source", "update"]),
|
|
11723
|
-
legacyCommand("list-inbound-submissions", ["inbound", "submission", "list"]
|
|
12385
|
+
legacyCommand("list-inbound-submissions", ["inbound", "submission", "list"], [], [
|
|
12386
|
+
{
|
|
12387
|
+
name: "--limit <number>",
|
|
12388
|
+
description: "Page size from 1 to 100 (default 25). Returns submissions, hasMore and nextCursor; no total."
|
|
12389
|
+
},
|
|
12390
|
+
{
|
|
12391
|
+
name: "--cursor <token>",
|
|
12392
|
+
description: "Pass the previous response's nextCursor unchanged. Omit for newest submissions. Replaces --page/--perPage."
|
|
12393
|
+
},
|
|
12394
|
+
{
|
|
12395
|
+
name: "--sourceId <id>",
|
|
12396
|
+
description: "Filter submissions to this source; keep the same filter while following cursors."
|
|
12397
|
+
}
|
|
12398
|
+
]),
|
|
12399
|
+
legacyCommand("count-inbound-submissions", ["inbound", "submission", "count"], [], [
|
|
12400
|
+
{
|
|
12401
|
+
name: "--sourceId <id>",
|
|
12402
|
+
description: "Optional source filter. Returns an independently calculated exact totalCount, not a list snapshot."
|
|
12403
|
+
}
|
|
12404
|
+
]),
|
|
11724
12405
|
legacyCommand("get-inbound-submission", ["inbound", "submission", "get"]),
|
|
11725
12406
|
legacyCommand("save-inbound-mapping", ["inbound", "mapping", "save"]),
|
|
11726
12407
|
legacyCommand("save-inbound-automation-config", [
|
|
@@ -11862,48 +12543,323 @@ var completionWords = () => {
|
|
|
11862
12543
|
words.add("completion");
|
|
11863
12544
|
return [...words].sort();
|
|
11864
12545
|
};
|
|
11865
|
-
var createCompletionScript = (shell) => {
|
|
11866
|
-
const words = completionWords().join(" ");
|
|
11867
|
-
switch (shell) {
|
|
11868
|
-
case "bash":
|
|
11869
|
-
return `# bash completion for bb
|
|
11870
|
-
_bb() {
|
|
11871
|
-
COMPREPLY=( $(compgen -W '${words}' -- "${"$"}{COMP_WORDS[COMP_CWORD]}") )
|
|
11872
|
-
}
|
|
11873
|
-
complete -F _bb bb
|
|
11874
|
-
`;
|
|
11875
|
-
case "zsh":
|
|
11876
|
-
return `#compdef bb
|
|
11877
|
-
_bb() {
|
|
11878
|
-
local -a commands
|
|
11879
|
-
commands=(${words})
|
|
11880
|
-
_describe 'bb command' commands
|
|
11881
|
-
}
|
|
11882
|
-
compdef _bb bb
|
|
11883
|
-
`;
|
|
11884
|
-
case "fish":
|
|
11885
|
-
return completionWords().map((word) => `complete -c bb -f -a '${word}'`).join(`
|
|
11886
|
-
`).concat(`
|
|
11887
|
-
`);
|
|
11888
|
-
case "powershell":
|
|
11889
|
-
return `Register-ArgumentCompleter -Native -CommandName bb -ScriptBlock {
|
|
11890
|
-
param($wordToComplete)
|
|
11891
|
-
'${words}'.Split(' ') | Where-Object { $_ -like "$wordToComplete*" }
|
|
11892
|
-
}
|
|
11893
|
-
`;
|
|
12546
|
+
var createCompletionScript = (shell) => {
|
|
12547
|
+
const words = completionWords().join(" ");
|
|
12548
|
+
switch (shell) {
|
|
12549
|
+
case "bash":
|
|
12550
|
+
return `# bash completion for bb
|
|
12551
|
+
_bb() {
|
|
12552
|
+
COMPREPLY=( $(compgen -W '${words}' -- "${"$"}{COMP_WORDS[COMP_CWORD]}") )
|
|
12553
|
+
}
|
|
12554
|
+
complete -F _bb bb
|
|
12555
|
+
`;
|
|
12556
|
+
case "zsh":
|
|
12557
|
+
return `#compdef bb
|
|
12558
|
+
_bb() {
|
|
12559
|
+
local -a commands
|
|
12560
|
+
commands=(${words})
|
|
12561
|
+
_describe 'bb command' commands
|
|
12562
|
+
}
|
|
12563
|
+
compdef _bb bb
|
|
12564
|
+
`;
|
|
12565
|
+
case "fish":
|
|
12566
|
+
return completionWords().map((word) => `complete -c bb -f -a '${word}'`).join(`
|
|
12567
|
+
`).concat(`
|
|
12568
|
+
`);
|
|
12569
|
+
case "powershell":
|
|
12570
|
+
return `Register-ArgumentCompleter -Native -CommandName bb -ScriptBlock {
|
|
12571
|
+
param($wordToComplete)
|
|
12572
|
+
'${words}'.Split(' ') | Where-Object { $_ -like "$wordToComplete*" }
|
|
12573
|
+
}
|
|
12574
|
+
`;
|
|
12575
|
+
}
|
|
12576
|
+
};
|
|
12577
|
+
|
|
12578
|
+
// src/cli.ts
|
|
12579
|
+
var SUPPLIER_ANALYTICS_SORT_IDS = [
|
|
12580
|
+
"name",
|
|
12581
|
+
"gstRegistered",
|
|
12582
|
+
"status",
|
|
12583
|
+
"phone",
|
|
12584
|
+
"email",
|
|
12585
|
+
"updatedAt",
|
|
12586
|
+
"createdAt"
|
|
12587
|
+
];
|
|
12588
|
+
function parsePositiveIntFlag(value, flagName) {
|
|
12589
|
+
if (value === undefined)
|
|
12590
|
+
return;
|
|
12591
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
12592
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12593
|
+
throw new Error(`${flagName} must be a positive integer.`);
|
|
12594
|
+
}
|
|
12595
|
+
return parsed;
|
|
12596
|
+
}
|
|
12597
|
+
var COMPANY_SORT_FIELDS = ["name", "createdAt"];
|
|
12598
|
+
var COMPANY_SORT_DIRECTIONS = ["asc", "desc"];
|
|
12599
|
+
var COMPANY_PAGE_FLAGS = [
|
|
12600
|
+
"page",
|
|
12601
|
+
"perPage",
|
|
12602
|
+
"pageSize",
|
|
12603
|
+
"page-size",
|
|
12604
|
+
"per-page",
|
|
12605
|
+
"page_size",
|
|
12606
|
+
"per_page"
|
|
12607
|
+
];
|
|
12608
|
+
var rejectBareFlag = (flags, key) => {
|
|
12609
|
+
if (flags[key] === true) {
|
|
12610
|
+
throw new Error(`--${key} requires a value.`);
|
|
12611
|
+
}
|
|
12612
|
+
};
|
|
12613
|
+
var rejectCompanyPageFlags = (flags, command) => {
|
|
12614
|
+
for (const key of COMPANY_PAGE_FLAGS) {
|
|
12615
|
+
if (flags[key] !== undefined) {
|
|
12616
|
+
throw new Error(`--${key} is not supported by company ${command}; use --limit and --cursor for list or company count for totals.`);
|
|
12617
|
+
}
|
|
12618
|
+
}
|
|
12619
|
+
};
|
|
12620
|
+
var parseCompanyLimit = (value) => {
|
|
12621
|
+
if (value === undefined)
|
|
12622
|
+
return 20;
|
|
12623
|
+
const parsed = Number(String(value));
|
|
12624
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 100) {
|
|
12625
|
+
throw new Error("--limit must be an integer from 1 to 100.");
|
|
12626
|
+
}
|
|
12627
|
+
return parsed;
|
|
12628
|
+
};
|
|
12629
|
+
var parseCompanySortBy = (value) => {
|
|
12630
|
+
if (value === undefined)
|
|
12631
|
+
return "createdAt";
|
|
12632
|
+
if (!COMPANY_SORT_FIELDS.includes(value)) {
|
|
12633
|
+
throw new Error(`Invalid --sortBy "${value}". Use one of: ${COMPANY_SORT_FIELDS.join(", ")}.`);
|
|
12634
|
+
}
|
|
12635
|
+
return value;
|
|
12636
|
+
};
|
|
12637
|
+
var parseCompanySortDir = (value) => {
|
|
12638
|
+
if (value === undefined)
|
|
12639
|
+
return "desc";
|
|
12640
|
+
if (!COMPANY_SORT_DIRECTIONS.includes(value)) {
|
|
12641
|
+
throw new Error(`Invalid --sortDir "${value}". Use one of: ${COMPANY_SORT_DIRECTIONS.join(", ")}.`);
|
|
12642
|
+
}
|
|
12643
|
+
return value;
|
|
12644
|
+
};
|
|
12645
|
+
var parseCompanyDirection = (value) => {
|
|
12646
|
+
if (value === undefined)
|
|
12647
|
+
return "forward";
|
|
12648
|
+
if (value !== "forward" && value !== "backward") {
|
|
12649
|
+
throw new Error('--direction must be "forward" or "backward".');
|
|
12650
|
+
}
|
|
12651
|
+
return value;
|
|
12652
|
+
};
|
|
12653
|
+
var parseCompanyListFlags = (flags) => {
|
|
12654
|
+
rejectCompanyPageFlags(flags, "list");
|
|
12655
|
+
for (const key of [
|
|
12656
|
+
"name",
|
|
12657
|
+
"createdBy",
|
|
12658
|
+
"createdByIds",
|
|
12659
|
+
"active",
|
|
12660
|
+
"limit",
|
|
12661
|
+
"cursor",
|
|
12662
|
+
"direction",
|
|
12663
|
+
"sortBy",
|
|
12664
|
+
"sortDir"
|
|
12665
|
+
]) {
|
|
12666
|
+
rejectBareFlag(flags, key);
|
|
12667
|
+
}
|
|
12668
|
+
const cursor = getFlag(flags, "cursor");
|
|
12669
|
+
const direction = parseCompanyDirection(getFlag(flags, "direction"));
|
|
12670
|
+
if (direction === "backward" && cursor === undefined) {
|
|
12671
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
12672
|
+
}
|
|
12673
|
+
if (cursor === "")
|
|
12674
|
+
throw new Error("--cursor requires a non-empty token.");
|
|
12675
|
+
return {
|
|
12676
|
+
name: getFlag(flags, "name"),
|
|
12677
|
+
createdBy: getFlag(flags, "createdBy"),
|
|
12678
|
+
createdByIds: parseCommaSeparatedIds(getFlag(flags, "createdByIds")),
|
|
12679
|
+
active: parseOptionalBoolFlag(flags, "active"),
|
|
12680
|
+
limit: parseCompanyLimit(getFlag(flags, "limit")),
|
|
12681
|
+
cursor,
|
|
12682
|
+
direction,
|
|
12683
|
+
sortBy: parseCompanySortBy(getFlag(flags, "sortBy")),
|
|
12684
|
+
sortDir: parseCompanySortDir(getFlag(flags, "sortDir"))
|
|
12685
|
+
};
|
|
12686
|
+
};
|
|
12687
|
+
var parseCompanyCountFlags = (flags) => {
|
|
12688
|
+
rejectCompanyPageFlags(flags, "count");
|
|
12689
|
+
for (const key of [
|
|
12690
|
+
"name",
|
|
12691
|
+
"createdBy",
|
|
12692
|
+
"createdByIds",
|
|
12693
|
+
"active",
|
|
12694
|
+
"limit",
|
|
12695
|
+
"cursor",
|
|
12696
|
+
"direction",
|
|
12697
|
+
"sortBy",
|
|
12698
|
+
"sortDir"
|
|
12699
|
+
]) {
|
|
12700
|
+
rejectBareFlag(flags, key);
|
|
12701
|
+
}
|
|
12702
|
+
if (flags.limit !== undefined || flags.cursor !== undefined || flags.direction !== undefined) {
|
|
12703
|
+
throw new Error("company count does not accept list pagination flags.");
|
|
12704
|
+
}
|
|
12705
|
+
if (flags.sortBy !== undefined || flags.sortDir !== undefined) {
|
|
12706
|
+
throw new Error("company count does not accept list sorting flags.");
|
|
12707
|
+
}
|
|
12708
|
+
return {
|
|
12709
|
+
name: getFlag(flags, "name"),
|
|
12710
|
+
createdBy: getFlag(flags, "createdBy"),
|
|
12711
|
+
createdByIds: parseCommaSeparatedIds(getFlag(flags, "createdByIds")),
|
|
12712
|
+
active: parseOptionalBoolFlag(flags, "active")
|
|
12713
|
+
};
|
|
12714
|
+
};
|
|
12715
|
+
var PROJECT_SORT_FIELDS = [
|
|
12716
|
+
"name",
|
|
12717
|
+
"createdAt",
|
|
12718
|
+
"status",
|
|
12719
|
+
"companyName",
|
|
12720
|
+
"wonAt"
|
|
12721
|
+
];
|
|
12722
|
+
var PROJECT_SORT_DIRECTIONS = ["asc", "desc"];
|
|
12723
|
+
var PROJECT_PAGE_FLAGS = [
|
|
12724
|
+
"page",
|
|
12725
|
+
"perPage",
|
|
12726
|
+
"pageSize",
|
|
12727
|
+
"page-size",
|
|
12728
|
+
"per-page",
|
|
12729
|
+
"page_size",
|
|
12730
|
+
"per_page"
|
|
12731
|
+
];
|
|
12732
|
+
var rejectProjectPageFlags = (flags, command) => {
|
|
12733
|
+
for (const key of PROJECT_PAGE_FLAGS) {
|
|
12734
|
+
if (flags[key] !== undefined) {
|
|
12735
|
+
throw new Error(`--${key} is not supported by project ${command}; use --limit and --cursor for list or project count for totals.`);
|
|
12736
|
+
}
|
|
12737
|
+
}
|
|
12738
|
+
};
|
|
12739
|
+
var parseProjectLimit = (value) => {
|
|
12740
|
+
if (value === undefined)
|
|
12741
|
+
return 20;
|
|
12742
|
+
const parsed = Number(String(value));
|
|
12743
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 100) {
|
|
12744
|
+
throw new Error("--limit must be an integer from 1 to 100.");
|
|
12745
|
+
}
|
|
12746
|
+
return parsed;
|
|
12747
|
+
};
|
|
12748
|
+
var parseProjectSortBy = (value) => {
|
|
12749
|
+
if (value === undefined)
|
|
12750
|
+
return "createdAt";
|
|
12751
|
+
if (!PROJECT_SORT_FIELDS.includes(value)) {
|
|
12752
|
+
throw new Error(`Invalid --sortBy "${value}". Use one of: ${PROJECT_SORT_FIELDS.join(", ")}.`);
|
|
12753
|
+
}
|
|
12754
|
+
return value;
|
|
12755
|
+
};
|
|
12756
|
+
var parseProjectSortDir = (value) => {
|
|
12757
|
+
if (value === undefined)
|
|
12758
|
+
return "desc";
|
|
12759
|
+
if (!PROJECT_SORT_DIRECTIONS.includes(value)) {
|
|
12760
|
+
throw new Error(`Invalid --sortDir "${value}". Use one of: ${PROJECT_SORT_DIRECTIONS.join(", ")}.`);
|
|
11894
12761
|
}
|
|
12762
|
+
return value;
|
|
11895
12763
|
};
|
|
11896
|
-
|
|
11897
|
-
// src/cli.ts
|
|
11898
|
-
function parsePositiveIntFlag(value, flagName) {
|
|
12764
|
+
var parseProjectWonWithinDays = (value) => {
|
|
11899
12765
|
if (value === undefined)
|
|
11900
12766
|
return;
|
|
11901
|
-
const parsed = Number
|
|
11902
|
-
if (!Number.
|
|
11903
|
-
throw new Error(
|
|
12767
|
+
const parsed = Number(value);
|
|
12768
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 3650) {
|
|
12769
|
+
throw new Error("--wonWithinDays must be an integer from 1 to 3650.");
|
|
11904
12770
|
}
|
|
11905
12771
|
return parsed;
|
|
11906
|
-
}
|
|
12772
|
+
};
|
|
12773
|
+
var parseProjectDirection = (value) => {
|
|
12774
|
+
if (value === undefined)
|
|
12775
|
+
return "forward";
|
|
12776
|
+
if (value !== "forward" && value !== "backward") {
|
|
12777
|
+
throw new Error('--direction must be "forward" or "backward".');
|
|
12778
|
+
}
|
|
12779
|
+
return value;
|
|
12780
|
+
};
|
|
12781
|
+
var parseProjectListFlags = (flags) => {
|
|
12782
|
+
rejectProjectPageFlags(flags, "list");
|
|
12783
|
+
for (const key of [
|
|
12784
|
+
"companyId",
|
|
12785
|
+
"name",
|
|
12786
|
+
"status",
|
|
12787
|
+
"statuses",
|
|
12788
|
+
"active",
|
|
12789
|
+
"wonFrom",
|
|
12790
|
+
"wonTo",
|
|
12791
|
+
"wonWithinDays",
|
|
12792
|
+
"limit",
|
|
12793
|
+
"cursor",
|
|
12794
|
+
"direction",
|
|
12795
|
+
"sortBy",
|
|
12796
|
+
"sortDir"
|
|
12797
|
+
]) {
|
|
12798
|
+
rejectBareFlag(flags, key);
|
|
12799
|
+
}
|
|
12800
|
+
const cursor = getFlag(flags, "cursor");
|
|
12801
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
12802
|
+
if (direction === "backward" && cursor === undefined) {
|
|
12803
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
12804
|
+
}
|
|
12805
|
+
if (cursor === "")
|
|
12806
|
+
throw new Error("--cursor requires a non-empty token.");
|
|
12807
|
+
return {
|
|
12808
|
+
companyId: getFlag(flags, "companyId"),
|
|
12809
|
+
name: getFlag(flags, "name"),
|
|
12810
|
+
status: parseOptionalExtendedProjectStatus(getFlag(flags, "status")),
|
|
12811
|
+
statuses: parseCommaSeparatedProjectStatuses(getFlag(flags, "statuses")),
|
|
12812
|
+
active: parseOptionalBoolFlag(flags, "active"),
|
|
12813
|
+
wonFrom: parseOptionalIsoDateFlag(getFlag(flags, "wonFrom"), "--wonFrom"),
|
|
12814
|
+
wonTo: parseOptionalIsoDateFlag(getFlag(flags, "wonTo"), "--wonTo", {
|
|
12815
|
+
endOfDay: true
|
|
12816
|
+
}),
|
|
12817
|
+
wonWithinDays: parseProjectWonWithinDays(getFlag(flags, "wonWithinDays")),
|
|
12818
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
12819
|
+
cursor,
|
|
12820
|
+
direction,
|
|
12821
|
+
sortBy: parseProjectSortBy(getFlag(flags, "sortBy")),
|
|
12822
|
+
sortDir: parseProjectSortDir(getFlag(flags, "sortDir"))
|
|
12823
|
+
};
|
|
12824
|
+
};
|
|
12825
|
+
var parseProjectCountFlags = (flags) => {
|
|
12826
|
+
rejectProjectPageFlags(flags, "count");
|
|
12827
|
+
for (const key of [
|
|
12828
|
+
"companyId",
|
|
12829
|
+
"name",
|
|
12830
|
+
"status",
|
|
12831
|
+
"statuses",
|
|
12832
|
+
"active",
|
|
12833
|
+
"wonFrom",
|
|
12834
|
+
"wonTo",
|
|
12835
|
+
"wonWithinDays",
|
|
12836
|
+
"limit",
|
|
12837
|
+
"cursor",
|
|
12838
|
+
"direction",
|
|
12839
|
+
"sortBy",
|
|
12840
|
+
"sortDir"
|
|
12841
|
+
]) {
|
|
12842
|
+
rejectBareFlag(flags, key);
|
|
12843
|
+
}
|
|
12844
|
+
if (flags.limit !== undefined || flags.cursor !== undefined || flags.direction !== undefined) {
|
|
12845
|
+
throw new Error("project count does not accept list pagination flags.");
|
|
12846
|
+
}
|
|
12847
|
+
if (flags.sortBy !== undefined || flags.sortDir !== undefined) {
|
|
12848
|
+
throw new Error("project count does not accept list sorting flags.");
|
|
12849
|
+
}
|
|
12850
|
+
return {
|
|
12851
|
+
companyId: getFlag(flags, "companyId"),
|
|
12852
|
+
name: getFlag(flags, "name"),
|
|
12853
|
+
status: parseOptionalExtendedProjectStatus(getFlag(flags, "status")),
|
|
12854
|
+
statuses: parseCommaSeparatedProjectStatuses(getFlag(flags, "statuses")),
|
|
12855
|
+
active: parseOptionalBoolFlag(flags, "active"),
|
|
12856
|
+
wonFrom: parseOptionalIsoDateFlag(getFlag(flags, "wonFrom"), "--wonFrom"),
|
|
12857
|
+
wonTo: parseOptionalIsoDateFlag(getFlag(flags, "wonTo"), "--wonTo", {
|
|
12858
|
+
endOfDay: true
|
|
12859
|
+
}),
|
|
12860
|
+
wonWithinDays: parseProjectWonWithinDays(getFlag(flags, "wonWithinDays"))
|
|
12861
|
+
};
|
|
12862
|
+
};
|
|
11907
12863
|
function parseOptionalBoolFlag(flags, key) {
|
|
11908
12864
|
const v = flags[key];
|
|
11909
12865
|
if (v === undefined || v === true)
|
|
@@ -11954,28 +12910,72 @@ function parseCommercialRejectionProjectStatus(flags) {
|
|
|
11954
12910
|
throw new Error("--projectStatusOnCommercialRejection requires PITCH or LOST.");
|
|
11955
12911
|
}
|
|
11956
12912
|
const status = String(raw).toUpperCase();
|
|
11957
|
-
if (status ===
|
|
12913
|
+
if (status === ProjectStatus2.PITCH || status === ProjectStatus2.LOST) {
|
|
11958
12914
|
return status;
|
|
11959
12915
|
}
|
|
11960
12916
|
throw new Error("--projectStatusOnCommercialRejection must be PITCH or LOST.");
|
|
11961
12917
|
}
|
|
11962
|
-
|
|
12918
|
+
var rejectRetiredPageFlags = (flags) => {
|
|
12919
|
+
for (const key of PROJECT_PAGE_FLAGS) {
|
|
12920
|
+
if (flags[key] !== undefined)
|
|
12921
|
+
throw new Error(`--${key} is retired; use --limit/--cursor, or the matching count command for totals.`);
|
|
12922
|
+
}
|
|
12923
|
+
};
|
|
12924
|
+
var parseBillFilterFlags = (flags) => {
|
|
11963
12925
|
const statusRaw = getFlag(flags, "status");
|
|
11964
12926
|
const createdByIdsRaw = getFlag(flags, "createdByIds");
|
|
11965
12927
|
const searchRaw = getFlag(flags, "search");
|
|
11966
|
-
const sortByRaw = getFlag(flags, "sortBy");
|
|
11967
|
-
const sortDirRaw = getFlag(flags, "sortDir");
|
|
11968
12928
|
return {
|
|
11969
12929
|
projectId: getFlag(flags, "projectId"),
|
|
11970
12930
|
budgetId: getFlag(flags, "budgetId"),
|
|
11971
12931
|
statuses: parseCommaSeparatedBillStatuses(statusRaw !== undefined ? String(statusRaw) : undefined),
|
|
11972
12932
|
search: searchRaw !== undefined ? String(searchRaw) : undefined,
|
|
11973
12933
|
isClaimable: parseOptionalBoolFlag(flags, "isClaimable"),
|
|
11974
|
-
createdByIds: parseCommaSeparatedIds(createdByIdsRaw !== undefined ? String(createdByIdsRaw) : undefined)
|
|
12934
|
+
createdByIds: parseCommaSeparatedIds(createdByIdsRaw !== undefined ? String(createdByIdsRaw) : undefined)
|
|
12935
|
+
};
|
|
12936
|
+
};
|
|
12937
|
+
var parseQuotationFilterFlags = (flags) => {
|
|
12938
|
+
const createdByRaw = getFlag(flags, "createdBy") ?? getFlag(flags, "requesterIds");
|
|
12939
|
+
const searchRaw = getFlag(flags, "search");
|
|
12940
|
+
return {
|
|
12941
|
+
projectId: getFlag(flags, "projectId"),
|
|
12942
|
+
budgetId: getFlag(flags, "budgetId"),
|
|
12943
|
+
supplierId: getFlag(flags, "supplierId"),
|
|
12944
|
+
status: parseCommaSeparatedQuotationStatuses(getFlag(flags, "status")),
|
|
12945
|
+
createdBy: parseCommaSeparatedIds(createdByRaw),
|
|
12946
|
+
search: searchRaw !== undefined ? String(searchRaw).trim() || undefined : undefined
|
|
12947
|
+
};
|
|
12948
|
+
};
|
|
12949
|
+
function parseListBillsFlags(flags) {
|
|
12950
|
+
rejectRetiredPageFlags(flags);
|
|
12951
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
12952
|
+
rejectBareFlag(flags, key);
|
|
12953
|
+
const sortByRaw = getFlag(flags, "sortBy");
|
|
12954
|
+
const sortDirRaw = getFlag(flags, "sortDir");
|
|
12955
|
+
const cursor = getFlag(flags, "cursor");
|
|
12956
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
12957
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
12958
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
12959
|
+
if (direction === "backward" && !cursor)
|
|
12960
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
12961
|
+
return {
|
|
12962
|
+
...parseBillFilterFlags(flags),
|
|
11975
12963
|
sortBy: parseOptionalBillListSortBy(sortByRaw !== undefined ? String(sortByRaw) : undefined),
|
|
11976
12964
|
sortDir: parseOptionalBillListSortDir(sortDirRaw !== undefined ? String(sortDirRaw) : undefined),
|
|
11977
|
-
|
|
11978
|
-
|
|
12965
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
12966
|
+
cursor,
|
|
12967
|
+
direction
|
|
12968
|
+
};
|
|
12969
|
+
}
|
|
12970
|
+
function parseCountBillsFlags(flags) {
|
|
12971
|
+
rejectRetiredPageFlags(flags);
|
|
12972
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"]) {
|
|
12973
|
+
if (flags[key] !== undefined)
|
|
12974
|
+
throw new Error(`bill count does not accept --${key}; totals use filters only.`);
|
|
12975
|
+
}
|
|
12976
|
+
return {
|
|
12977
|
+
...parseBillFilterFlags(flags),
|
|
12978
|
+
includeMetrics: parseOptionalBoolFlag(flags, "includeMetrics") ?? false
|
|
11979
12979
|
};
|
|
11980
12980
|
}
|
|
11981
12981
|
var SUPPLIER_SORT_FIELDS = [
|
|
@@ -11996,25 +12996,89 @@ function parseOptionalSupplierSortBy(raw) {
|
|
|
11996
12996
|
}
|
|
11997
12997
|
return raw;
|
|
11998
12998
|
}
|
|
11999
|
-
|
|
12000
|
-
const
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12999
|
+
var parseSupplierFilters = (flags) => {
|
|
13000
|
+
for (const key of [
|
|
13001
|
+
"name",
|
|
13002
|
+
"createdBy",
|
|
13003
|
+
"gstRegistered",
|
|
13004
|
+
"status",
|
|
13005
|
+
"supplierTags",
|
|
13006
|
+
"active"
|
|
13007
|
+
])
|
|
13008
|
+
rejectBareFlag(flags, key);
|
|
12006
13009
|
return {
|
|
12007
13010
|
name: getFlag(flags, "name"),
|
|
12008
|
-
|
|
12009
|
-
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
status: parseCommaSeparatedSupplierStatuses(statusRaw !== undefined ? String(statusRaw) : undefined),
|
|
12014
|
-
supplierTags: parseCommaSeparatedIds(supplierTagsRaw !== undefined ? String(supplierTagsRaw) : undefined),
|
|
12015
|
-
active: parseOptionalBoolFlag(flags, "active")
|
|
13011
|
+
createdBy: parseCommaSeparatedIds(getFlag(flags, "createdBy")),
|
|
13012
|
+
gstRegistered: parseOptionalBoolFlag(flags, "gstRegistered") ?? null,
|
|
13013
|
+
status: parseCommaSeparatedSupplierStatuses(getFlag(flags, "status")),
|
|
13014
|
+
supplierTags: parseCommaSeparatedIds(getFlag(flags, "supplierTags")),
|
|
13015
|
+
active: parseOptionalBoolFlag(flags, "active") ?? true
|
|
12016
13016
|
};
|
|
12017
|
-
}
|
|
13017
|
+
};
|
|
13018
|
+
var rejectSupplierPageFlags = (flags) => {
|
|
13019
|
+
for (const key of PROJECT_PAGE_FLAGS) {
|
|
13020
|
+
if (flags[key] !== undefined)
|
|
13021
|
+
throw new Error(`--${key} is retired for suppliers; use --limit/--cursor or supplier count for totals.`);
|
|
13022
|
+
}
|
|
13023
|
+
};
|
|
13024
|
+
var parseListSuppliersFlags = (flags) => {
|
|
13025
|
+
rejectSupplierPageFlags(flags);
|
|
13026
|
+
for (const key of [
|
|
13027
|
+
"limit",
|
|
13028
|
+
"cursor",
|
|
13029
|
+
"direction",
|
|
13030
|
+
"sort",
|
|
13031
|
+
"sortBy",
|
|
13032
|
+
"sortDir"
|
|
13033
|
+
])
|
|
13034
|
+
rejectBareFlag(flags, key);
|
|
13035
|
+
const limit = getFlag(flags, "limit") === undefined ? 10 : parseProjectLimit(getFlag(flags, "limit"));
|
|
13036
|
+
const cursor = getFlag(flags, "cursor");
|
|
13037
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
13038
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
13039
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
13040
|
+
if (direction === "backward" && !cursor)
|
|
13041
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
13042
|
+
const sortRaw = getFlag(flags, "sort");
|
|
13043
|
+
let sort;
|
|
13044
|
+
if (sortRaw !== undefined) {
|
|
13045
|
+
if (flags.sortBy !== undefined || flags.sortDir !== undefined)
|
|
13046
|
+
throw new Error("Use --sort or --sortBy/--sortDir, not both.");
|
|
13047
|
+
const parsed = parseJsonFlag(sortRaw, "--sort");
|
|
13048
|
+
if (!Array.isArray(parsed) || parsed.length > 8)
|
|
13049
|
+
throw new Error("--sort must be a JSON array of at most eight {id, desc} entries.");
|
|
13050
|
+
sort = parsed.map((item) => {
|
|
13051
|
+
if (typeof item !== "object" || item === null || !("id" in item) || !("desc" in item) || typeof item.id !== "string" || typeof item.desc !== "boolean" || Object.keys(item).some((key) => key !== "id" && key !== "desc"))
|
|
13052
|
+
throw new Error("Invalid --sort entry; use {id, desc}.");
|
|
13053
|
+
const id = parseOptionalSupplierSortBy(item.id);
|
|
13054
|
+
if (!id)
|
|
13055
|
+
throw new Error("Invalid --sort field.");
|
|
13056
|
+
return { id, desc: item.desc };
|
|
13057
|
+
});
|
|
13058
|
+
} else {
|
|
13059
|
+
const sortBy = parseOptionalSupplierSortBy(getFlag(flags, "sortBy"));
|
|
13060
|
+
const sortDir = parseOptionalBillListSortDir(getFlag(flags, "sortDir"));
|
|
13061
|
+
sort = [
|
|
13062
|
+
{ id: sortBy ?? "createdAt", desc: (sortDir ?? "desc") === "desc" }
|
|
13063
|
+
];
|
|
13064
|
+
}
|
|
13065
|
+
return { ...parseSupplierFilters(flags), limit, cursor, direction, sort };
|
|
13066
|
+
};
|
|
13067
|
+
var parseCountSuppliersFlags = (flags) => {
|
|
13068
|
+
rejectSupplierPageFlags(flags);
|
|
13069
|
+
for (const key of [
|
|
13070
|
+
"limit",
|
|
13071
|
+
"cursor",
|
|
13072
|
+
"direction",
|
|
13073
|
+
"sort",
|
|
13074
|
+
"sortBy",
|
|
13075
|
+
"sortDir"
|
|
13076
|
+
]) {
|
|
13077
|
+
if (flags[key] !== undefined)
|
|
13078
|
+
throw new Error(`supplier count does not accept --${key}; totals use filters only.`);
|
|
13079
|
+
}
|
|
13080
|
+
return parseSupplierFilters(flags);
|
|
13081
|
+
};
|
|
12018
13082
|
function parseDashboardQueryFlags(flags) {
|
|
12019
13083
|
const roleRaw = getFlag(flags, "role");
|
|
12020
13084
|
const timeFrameRaw = getFlag(flags, "timeFrame");
|
|
@@ -12049,7 +13113,8 @@ pending-approver assignment. On FORBIDDEN, stop and report the identity, role,
|
|
|
12049
13113
|
command, and target; do not switch keys or try a lower-level procedure.
|
|
12050
13114
|
|
|
12051
13115
|
Sensitive workflow changes: approval decisions/requests, entity status updates,
|
|
12052
|
-
estimate emails, customer invoices, integration retries
|
|
13116
|
+
estimate emails, customer invoices, integration retries and QuickBooks outcome
|
|
13117
|
+
verification, mark-budget-won,
|
|
12053
13118
|
submit-quotation, and supplier approval request side effects require an
|
|
12054
13119
|
interactive CONFIRM prompt and abort in non-interactive shells.
|
|
12055
13120
|
AI agents must inspect the entity first, summarize the exact entity, target
|
|
@@ -12060,15 +13125,20 @@ Budget mutations return a conflict while an estimate email is queued,
|
|
|
12060
13125
|
processing, or awaiting provider reconciliation.
|
|
12061
13126
|
|
|
12062
13127
|
Budgets
|
|
12063
|
-
list-budgets [--projectId] [--name] [--status CSV] [--createdBy] [--dateFrom] [--dateTo] [--sortBy] [--sortDir] [--
|
|
13128
|
+
list-budgets [--projectId] [--name] [--status CSV] [--createdBy] [--dateFrom] [--dateTo] [--sortBy lastActivityAt|createdAt|status|budget|date|createdBy] [--sortDir] [--limit 1-100] [--cursor <token>] [--direction forward|backward] [--summary]
|
|
13129
|
+
Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
13130
|
+
count-budgets [same filter flags as list-budgets] totalCount plus status and active facets (each ignores its own filter)
|
|
12064
13131
|
get-budget <id> Budget + line items
|
|
12065
13132
|
get-budget-items <id> Line items only
|
|
12066
13133
|
get-budget-details <id> Full detail (margins, suppliers, etc.)
|
|
12067
|
-
get-budget-categories
|
|
12068
|
-
|
|
13134
|
+
get-budget-categories [--q] [--limit 1-100] [--cursor <token>]
|
|
13135
|
+
Active categories, name A\u2013Z. Returns { items, pageInfo }; follow nextCursor with the same --q.
|
|
13136
|
+
get-budget-versions <budgetId> [--limit <1-50>] [--cursor <token> | --all]
|
|
12069
13137
|
rename-budget-version <versionId> --name <text>
|
|
12070
13138
|
restore-budget-version <versionId> Replace current budget data and return it to DRAFT.
|
|
12071
13139
|
update-budget-status <id> <status> [--projectManagerId <id>] [--markProjectWon true|false] [--projectStatusOnCommercialRejection PITCH|LOST]
|
|
13140
|
+
APPROVED requires a current Lead/Admin role, regardless of budget management permissions. Ordinary users must request approval.
|
|
13141
|
+
Material edits and generic status changes invalidate older pending budget requests; decide only a fresh request for the content reviewed.
|
|
12072
13142
|
Budget-changing commands require interactive "yes" confirmation when the current budget is ESTIMATE_CREATED, ESTIMATE_SENT, ESTIMATE_ACCEPTED, ESTIMATE_REJECTED, or ESTIMATE_CLOSED.
|
|
12073
13143
|
ESTIMATE_ACCEPTED requires win proof, auto-marks PITCH or LOST projects WON, requires --projectManagerId when the project has no PM, and auto-creates the Asana project/section when enabled.
|
|
12074
13144
|
ESTIMATE_REJECTED requires --projectStatusOnCommercialRejection when rejecting the only accepted/closed budget on a commercial project.
|
|
@@ -12078,7 +13148,7 @@ Budgets
|
|
|
12078
13148
|
update-budget --payload '<json>' (budget.updateBudget; must include id)
|
|
12079
13149
|
delete-budget <budgetId>
|
|
12080
13150
|
create-budget-approval <budgetId> (also queues approval request emails)
|
|
12081
|
-
create-estimate <budgetId> (
|
|
13151
|
+
create-estimate <budgetId> (queues QuickBooks estimate creation; budget is read-only until it settles; supports preflight updates)
|
|
12082
13152
|
send-estimate-to-contact-person --payload '<json>' Send using the web contact-person workflow; payload includes recipient fields plus HTML content/signature.
|
|
12083
13153
|
add-budget-items --budgetId --items '[{"itemId":"\u2026","quantity":1,"markup":30},\u2026]'
|
|
12084
13154
|
update-budget-item --id <budgetItemId> [--description plain-text] [--note plain-text] [--quantity] [--markup] [--cost] [--unitPrice] [--isFreeOfCharge true|false] [--gstInclusive true|false] [--gstOutOfScope true|false]
|
|
@@ -12086,7 +13156,7 @@ Budgets
|
|
|
12086
13156
|
replace-budget-item --budgetItemId <id> --replacementItemId <activeCatalogueItemId>
|
|
12087
13157
|
approve-unavailable-item-exception --budgetItemId <id> --reason <text> Lead/Admin only; reason must be 5-1000 characters.
|
|
12088
13158
|
reorder-budget-items <budgetId> --itemIds <csv>
|
|
12089
|
-
update-budget-item-supplier --budgetItemId --supplierId
|
|
13159
|
+
update-budget-item-supplier --budgetItemId --supplierId Material supplier/GST edit: supersedes pending approvals and applies the standard budget reset policy; unchanged supplier is a no-op.
|
|
12090
13160
|
create-budget-category --name <text>
|
|
12091
13161
|
update-budget-category --id --name
|
|
12092
13162
|
delete-budget-category <id>
|
|
@@ -12100,8 +13170,11 @@ Budgets
|
|
|
12100
13170
|
upload-budget-attachment <budgetId> <filePath> Presigned S3 upload + confirm
|
|
12101
13171
|
|
|
12102
13172
|
Bills
|
|
12103
|
-
list-bills [--projectId] [--budgetId] [--status CSV] [--search <text>] [--isClaimable true|false] [--createdByIds <csv>] [--sortBy createdAt|amount|status] [--sortDir asc|desc] [--
|
|
13173
|
+
list-bills [--projectId] [--budgetId] [--status CSV] [--search <text>] [--isClaimable true|false] [--createdByIds <csv>] [--sortBy createdAt|amount|status] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13174
|
+
Returns { items, pageInfo }; pass nextCursor with --direction forward or previousCursor with --direction backward, keeping the same filters and sort. --page/--pageSize/--perPage are rejected.
|
|
12104
13175
|
list-claims same flags as list-bills; only reimbursable claims (ignores --isClaimable)
|
|
13176
|
+
count-bills [--projectId] [--budgetId] [--status CSV] [--search <text>] [--isClaimable true|false] [--createdByIds <csv>] [--includeMetrics true|false] totalCount, status facets (ignore --status) and optional amount metrics; no pagination/sort flags
|
|
13177
|
+
count-claims same flags as count-bills; only reimbursable claims
|
|
12105
13178
|
Both lists return summaries; use get-bill-details <billId> for full detail.
|
|
12106
13179
|
isClaimable differentiates the shared bill/claim records: false = bill, true = claim.
|
|
12107
13180
|
Create supplier bills from approved quotations from the same supplier and project. Use quotationAllocations plus lineAmounts when quotations split one bill line. Eligible exemptions require explicit --quotation-exempt intent; claims do not consume or link quotations.
|
|
@@ -12112,7 +13185,7 @@ Bills
|
|
|
12112
13185
|
validate-bill-selection --payload '<json>' [--quotationIds <csv> | --quotationId <id>] Validate an approved supplier and approved quotation coverage for each supplier-bill line. --quotationId is legacy single-quotation syntax.
|
|
12113
13186
|
link-bill-quotations <billId> (--payload '<json>' | --quotationIds <csv>) Admin-only source-link repair; payload.quotationAllocations supports same-line splits.
|
|
12114
13187
|
stage-bill-attachment <projectId> <filePath...> [--file <path>] [--files <csv>] Upload files before create-bill; returns attachment JSON for attachments/paymentProofAttachments
|
|
12115
|
-
cleanup-staged-bill-attachments <projectId> --keys <csv>
|
|
13188
|
+
cleanup-staged-bill-attachments <projectId> --keys <csv> Queue cleanup of unattached staged uploads; returns operation IDs.
|
|
12116
13189
|
update-bill --payload '<json>' (bill.update; must include id)
|
|
12117
13190
|
update-bill-payment-evidence --payload '<json>' Replace paymentReference/paymentProofAttachments for an already-paid bill.
|
|
12118
13191
|
delete-bill <billId>
|
|
@@ -12123,23 +13196,25 @@ Bills
|
|
|
12123
13196
|
patch-bill-payment <billId> [--paymentTrackingUrl] [--paymentReference] [--quickbooksBillId] [--paymentDate <ISO>]
|
|
12124
13197
|
Clear a field: --clearPaymentTrackingUrl true | --clearPaymentReference true | --clearQuickbooksBillId true | --clearPaymentDate true
|
|
12125
13198
|
patch-bill-invoice-number <billId> <invoiceNumber>
|
|
12126
|
-
get-bill-attachments <billId>
|
|
13199
|
+
get-bill-attachments <billId> [--limit 1-50] [--cursor <token>]
|
|
13200
|
+
Newest first. Returns { items, pageInfo }; follow nextCursor.
|
|
12127
13201
|
upload-bill-attachment <billId> <filePath...> [--file <path>] [--files <csv>] Attach invoice/supporting files as BILL attachments to any bill status, including PAID bills
|
|
12128
13202
|
attach-bill-payment-receipt <billId> <filePath...> [--file <path>] [--files <csv>] Attach Wise/payment-proof PDFs as BILL_PAYMENT_PROOF attachments
|
|
12129
13203
|
attach-bill-documents <billId> [--invoice <path>] [--invoices <csv>] [--paymentProof|--payment-proof|--proof <path>] [--paymentProofs|--payment-proofs|--proofs <csv>] Attach invoice and/or payment proof files with separate BB attachment types
|
|
12130
13204
|
get-bill-details <billId>
|
|
12131
13205
|
|
|
12132
13206
|
Quotations
|
|
12133
|
-
list-quotations [--projectId] [--budgetId] [--supplierId] [--status CSV] [--createdBy CSV] [--search] [--
|
|
12134
|
-
|
|
13207
|
+
list-quotations [--projectId] [--budgetId] [--supplierId] [--status CSV] [--createdBy CSV] [--search] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13208
|
+
Newest first; returns { items, pageInfo }. Follow nextCursor/previousCursor with the same filters. --page/--pageSize/--perPage are rejected; --requesterIds remains an alias for --createdBy.
|
|
13209
|
+
count-quotations [--projectId] [--budgetId] [--supplierId] [--status CSV] [--createdBy CSV] [--search] [--includeMetrics true|false] totalCount, status facets (ignore --status) and optional amount metrics
|
|
12135
13210
|
get-quotation <quotationId>
|
|
12136
13211
|
upload-quotation-attachment <projectId> <filePath> Upload one PDF, JPEG, or PNG up to 20MB; returns attachment JSON for a quotation payload.
|
|
12137
|
-
cleanup-staged-quotation-attachments <projectId> --keys <csv>
|
|
13212
|
+
cleanup-staged-quotation-attachments <projectId> --keys <csv> Queue cleanup of unattached quotation uploads; returns operation IDs.
|
|
12138
13213
|
create-quotation --payload '<json>' (quotation.createDraft; requires amountWithoutGst, gstAmount, and lineAmounts [{budgetItemId, amount}] for multiple budgetItemIds; amounts before GST must sum to amountWithoutGst)
|
|
12139
13214
|
update-quotation --payload '<json>' Update a DRAFT or REJECTED quotation; same allocation payload plus id; use lineAmounts [{budgetItemId, amount}] for every selected item.
|
|
12140
13215
|
delete-quotation <quotationId>
|
|
12141
13216
|
submit-quotation <quotationId> [--overBudgetOverrideReason <text>]
|
|
12142
|
-
approve-quotation <quotationId> [--overBudgetOverrideReason <text>]
|
|
13217
|
+
approve-quotation <quotationId> [--overBudgetOverrideReason <text>] (assigned pending request/current Admin; concurrent revision or allocation changes conflict)
|
|
12143
13218
|
reject-quotation <quotationId> --reason <text>
|
|
12144
13219
|
download-quotation-pdf <quotationId> [original|staff|final]
|
|
12145
13220
|
|
|
@@ -12148,8 +13223,10 @@ Customer invoices
|
|
|
12148
13223
|
list-eligible-customer-invoice-budgets <projectId> Accepted budgets that are ready and still have invoice coverage remaining, including estimate total, invoiced/remaining percentages, and available amount.
|
|
12149
13224
|
preview-customer-invoice-amount <budgetId> <percentage-of-estimate> Preview amount before GST, GST, and total for a percentage of the original estimate. The percentage cannot exceed the budget's remaining coverage.
|
|
12150
13225
|
list-available-qbo-customer-invoices <budgetId> List unlinked QuickBooks invoices available for this accepted or closed estimate before previewing and importing one.
|
|
12151
|
-
list-customer-invoices [budgetId] [--projectId <id>] [--companyIds CSV] [--projectIds CSV] [--budgetIds CSV] [--createdByIds CSV] [--status CSV] [--search] [--sortBy createdAt|status|totalInvoiceAmount|approvalExpiresAt] [--sortDir asc|desc] [--
|
|
13226
|
+
list-customer-invoices [budgetId] [--projectId <id>] [--companyIds CSV] [--projectIds CSV] [--budgetIds CSV] [--createdByIds CSV] [--status CSV] [--search] [--sortBy createdAt|status|totalInvoiceAmount|approvalExpiresAt] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13227
|
+
Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
12152
13228
|
No scope flag lists invoices globally. --projectId uses the project scope. A positional budgetId is a backward-compatible shortcut for --budgetIds.
|
|
13229
|
+
count-customer-invoices [budgetId] [same filter flags as list-customer-invoices] totalCount, lifecycle status facets (ignore --status) and amount metrics; no paging or sort flags
|
|
12153
13230
|
get-customer-invoice <batchId>
|
|
12154
13231
|
get-customer-invoice-email-context <batchId> Contact, required CC, budget, and project context for composing an invoice email.
|
|
12155
13232
|
preview-qbo-customer-invoice <budgetId> <qboInvoiceId> Preview an invoice selected from list-available-qbo-customer-invoices; works on accepted/closed estimates.
|
|
@@ -12174,20 +13251,28 @@ Approvals
|
|
|
12174
13251
|
reject-supplier <supplierId> --reason <text> (also sends requester reply email)
|
|
12175
13252
|
|
|
12176
13253
|
Companies & projects
|
|
12177
|
-
list-companies [--name] [--createdBy] [--active true|false] [--
|
|
12178
|
-
|
|
13254
|
+
list-companies [--name] [--createdBy] [--createdByIds CSV] [--active true|false] [--sortBy name|createdAt] [--sortDir asc|desc] [--limit 1-100] [--cursor] [--direction forward|backward]
|
|
13255
|
+
Returns { items, pageInfo }; pass nextCursor with direction forward or previousCursor with direction backward. Omit --cursor to restart.
|
|
13256
|
+
count-companies [--name] [--createdBy] [--createdByIds CSV] [--active true|false]
|
|
13257
|
+
Returns independent { totalCount, counts: { active: { true, false } } }; no pagination or sorting flags.
|
|
12179
13258
|
get-company <id>
|
|
12180
|
-
search-existing-companies --query <name> [--
|
|
13259
|
+
search-existing-companies --query <name> [--limit 1-50] [--cursor <token>] (BB + QuickBooks, read-only; follow pageInfo.nextCursor)
|
|
12181
13260
|
use-existing-company --companyId <bbId> and/or --quickbooksId <qboId> [--website <url>] [--confirmDistinct true]
|
|
12182
13261
|
Supply both IDs to explicitly connect existing records with different names.
|
|
12183
13262
|
Reuses both records, creating only the missing counterpart. Website is needed only for a QBO import without one.
|
|
12184
13263
|
create-company --name --website <url> [--confirmDistinct true]
|
|
12185
13264
|
Exact existing companies are reused. Similar names require explicit separate-entity confirmation.
|
|
12186
|
-
update-company --payload '<json>' (
|
|
13265
|
+
update-company --payload '<json>' (saves BB fields; returns queued QBO operation ID, not completion)
|
|
13266
|
+
get-company-quickbooks-sync-status <companyId> (saved status only; no provider call or polling)
|
|
12187
13267
|
delete-company <id>
|
|
12188
|
-
list-projects [--companyId] [--name] [--status] [--active true|false] [--
|
|
12189
|
-
|
|
12190
|
-
|
|
13268
|
+
list-projects [--companyId] [--name] [--status|--statuses CSV] [--active true|false] [--wonFrom ISO] [--wonTo ISO] [--wonWithinDays N] [--limit 1-100] [--cursor] [--direction forward|backward] [--sortBy name|createdAt|status|companyName|wonAt] [--sortDir asc|desc]
|
|
13269
|
+
Returns { items, pageInfo }; pass nextCursor with direction forward or previousCursor with direction backward. Legacy --page/--perPage are rejected.
|
|
13270
|
+
--sortBy wonAt orders by when the project was marked WON (unwon projects last). Each project includes wonAt, wonById, wonBy and wonAtEstimated (true for backfilled dates).
|
|
13271
|
+
count-projects [--companyId] [--name] [--status|--statuses CSV] [--active true|false] [--wonFrom ISO] [--wonTo ISO] [--wonWithinDays N]
|
|
13272
|
+
Returns independent { totalCount, counts: { status, active: { true, false } } }; no pagination or sorting flags.
|
|
13273
|
+
list-project-hubs [--q] [--status CSV] [--sortBy startDate|name|companyName|status] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13274
|
+
Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
13275
|
+
count-project-hubs [--q] [--status CSV] totalCount plus status facet
|
|
12191
13276
|
List active projects that have a Project Hub integration.
|
|
12192
13277
|
get-project <id>
|
|
12193
13278
|
Budget overview totalRevenue includes Estimate Accepted and Estimate Closed budgets only.
|
|
@@ -12209,9 +13294,10 @@ Contacts
|
|
|
12209
13294
|
update-contact-person --payload '<json>' (contactPerson.updateContactPerson; must include id)
|
|
12210
13295
|
|
|
12211
13296
|
Suppliers & items
|
|
12212
|
-
list-suppliers [--name] [--
|
|
12213
|
-
|
|
12214
|
-
|
|
13297
|
+
list-suppliers [--name] [--limit 1-100] [--cursor <token>] [--direction forward|backward] [--sortBy createdAt|updatedAt|name|email|phone|gstRegistered|status|active] [--sortDir asc|desc | --sort JSON] [--createdBy <csv>] [--gstRegistered true|false] [--status CSV] [--supplierTags <csv>] [--active true|false]
|
|
13298
|
+
count-suppliers [--name] [--createdBy <csv>] [--gstRegistered true|false] [--status CSV] [--supplierTags <csv>] [--active true|false] (independent totals/facets; no pagination/sort flags)
|
|
13299
|
+
Defaults: --active true, --limit 10, --sortBy createdAt, --sortDir desc (same as the web list); pass --active false for archived suppliers.
|
|
13300
|
+
create-supplier --payload '<json>' (supplier.createSupplier; archived-name recreation is Admin-only; auto-requests approval + emails when status is PENDING_APPROVAL)
|
|
12215
13301
|
update-supplier --payload '<json>' (authenticated; normal-user edits require server-enforced approval)
|
|
12216
13302
|
delete-suppliers --ids <csv> (supplier.deleteSuppliers; admin; archives/deactivates supplier items)
|
|
12217
13303
|
reactivate-suppliers --ids <csv> (supplier.reactivateSuppliers; admin; reactivates supplier items)
|
|
@@ -12224,20 +13310,29 @@ Suppliers & items
|
|
|
12224
13310
|
archive-items --ids <csv> (item.archiveItems; Budget Builder only; max 100; users can archive their own items, leads/admins any item; open estimates retain snapshot lines and require resolution before send/acceptance)
|
|
12225
13311
|
delete-item <id> (item.deleteItem; admin; archives in Budget Builder and makes the item inactive in QuickBooks; blocked while used by an open estimate)
|
|
12226
13312
|
get-supplier-details <supplierId>
|
|
12227
|
-
get-supplier-analytics [--name] [--
|
|
12228
|
-
|
|
13313
|
+
get-supplier-analytics [--name] [--status CSV] [--gstRegistered true|false] [--createdBy <text>] [--timeFrame ALL|LAST_YEAR|LAST_6_MONTHS|LAST_3_MONTHS|CUSTOM] [--startDate <ISO> --endDate <ISO>] [--sortBy name|gstRegistered|status|phone|email|updatedAt|createdAt] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13314
|
+
Admin. Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
13315
|
+
count-supplier-analytics [--name] [--status] [--gstRegistered] [--createdBy] [--timeFrame] [--startDate --endDate] Admin. totalCount for the same filters
|
|
13316
|
+
list-items [--name] [--includeQuickBooksDeactivationPending true] [--sortBy createdAt|updatedAt|name|cost|itemCategory|supplier] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13317
|
+
Returns { items, pageInfo }; follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
13318
|
+
count-items [same filter flags as list-items] total plus category and supplier facets
|
|
12229
13319
|
get-item <id>
|
|
12230
|
-
|
|
13320
|
+
get-item-quickbooks-sync-status <itemId> (saved status only; no provider call or polling)
|
|
13321
|
+
list-item-categories [--name] [--sortBy createdAt|name|itemCount|createdBy] [--sortDir asc|desc] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13322
|
+
Active categories only; returns { items, pageInfo }. Follow nextCursor/previousCursor with the same filters and sort. --page/--perPage are rejected.
|
|
13323
|
+
count-item-categories [--name] totalCount of active categories
|
|
12231
13324
|
create-item-category --name (admin)
|
|
12232
13325
|
update-item-category --id --name (authenticated; applies immediately)
|
|
12233
13326
|
delete-item-categories --ids <csv> (itemCategory.deleteItemCategories; admin; empty categories only)
|
|
12234
13327
|
|
|
12235
13328
|
Dashboard & users
|
|
12236
13329
|
whoami Show the user identity and role for the active API key.
|
|
12237
|
-
list-users
|
|
13330
|
+
list-users [--q] [--limit 1-100] [--cursor <token>]
|
|
13331
|
+
Name A\u2013Z. Returns { items, pageInfo }; follow nextCursor with the same --q. --page/--perPage are rejected.
|
|
13332
|
+
count-users [--q] totalCount for the same search
|
|
12238
13333
|
create-user --email <email> [--name <name>] [--role ${userRolesForHelp.join("|")}] (admin; API-only service identity with no Google sign-in)
|
|
12239
13334
|
create-api-key --name <label> [--userId <userId>] (defaults to the caller; admin required for another user; raw key is shown once)
|
|
12240
|
-
list-api-keys [--userId <userId>] (defaults to the caller; admin required for another user)
|
|
13335
|
+
list-api-keys [--userId <userId>] [--limit 1-100] [--cursor <token>] (newest first, { items, pageInfo }; defaults to the caller; admin required for another user)
|
|
12241
13336
|
revoke-api-key <apiKeyId> [--userId <userId>] (defaults to the caller; admin required for another user)
|
|
12242
13337
|
get-user-performance [--userId] (admin)
|
|
12243
13338
|
get-dashboard [--userId] [--role BD|CREATOR|INSIDE_SALES|ALL] [--deals ALL|SUCCESSFUL|LOST] [--timeFrame] [--startDate] [--endDate] (admin)
|
|
@@ -12247,12 +13342,30 @@ Dashboard & users
|
|
|
12247
13342
|
get-financial-overview [same optional flags as dashboard; role uses BudgetRole enum] (admin)
|
|
12248
13343
|
|
|
12249
13344
|
Errors
|
|
12250
|
-
get-recent-errors [--
|
|
13345
|
+
get-recent-errors [--cursor] [--direction forward|backward] [--limit] [--severity] [--status] [--timeFrame] (admin)
|
|
13346
|
+
count-errors [--severity] [--status] [--timeFrame] (admin)
|
|
12251
13347
|
get-error-metrics (admin)
|
|
12252
13348
|
|
|
12253
13349
|
Automation (admin)
|
|
12254
|
-
list-integration-operations [--search] [--destination <provider,...>] [--status <PENDING|PROCESSING|FAILED|COMPLETED,...>] [--
|
|
12255
|
-
|
|
13350
|
+
list-integration-operations [--search] [--destination <provider,...>] [--status <PENDING|PROCESSING|FAILED|COMPLETED,...>] [--limit 1-100] [--cursor <token>] [--direction forward|backward]
|
|
13351
|
+
Newest first; returns { items, pageInfo }. Follow nextCursor/previousCursor with the same filters. --page/--perPage are rejected.
|
|
13352
|
+
count-integration-operations [same filter flags] totalCount plus provider filter options
|
|
13353
|
+
get-integration-operation <operationId> (one job: who queued it, what it is for, saved progress, Retry state)
|
|
13354
|
+
retry-integration-operation <operationId> [--confirmExternalStateReconciled true|false] [--outboundEmailResolution ACCEPTED|NOT_ACCEPTED_RETRY] [--providerMessageId <id>] (QuickBooks jobs with a saved attempt check QuickBooks first: applied changes finish without resending, unapplied ones are sent again)
|
|
13355
|
+
reconcile-resource-operation <operationId> (admin: check a QuickBooks invoice/company/item job outcome without retrying; same check Retry runs first)
|
|
13356
|
+
|
|
13357
|
+
Webhooks (admin)
|
|
13358
|
+
list-webhook-event-types (event catalogue: type, group, live|planned)
|
|
13359
|
+
list-webhook-endpoints
|
|
13360
|
+
get-webhook-endpoint <endpointId>
|
|
13361
|
+
create-webhook-endpoint --name <name> --url <https-url> --events <type|prefix.*|*,...> [--enabled true|false] (prints the signing secret once)
|
|
13362
|
+
update-webhook-endpoint <endpointId> [--name] [--url] [--events <...>] [--enabled true|false]
|
|
13363
|
+
delete-webhook-endpoint <endpointId>
|
|
13364
|
+
rotate-webhook-secret <endpointId> [--previousSecretTtlHours <0-168>] (prints the new secret once)
|
|
13365
|
+
send-webhook-test-event <endpointId>
|
|
13366
|
+
list-webhook-deliveries [--endpointId] [--status PENDING|SUCCEEDED|FAILED] [--eventType] [--cursor] [--limit]
|
|
13367
|
+
get-webhook-delivery <deliveryId> (attempts with response codes)
|
|
13368
|
+
replay-webhook-delivery <deliveryId> (same eventId, new attempt chain)
|
|
12256
13369
|
|
|
12257
13370
|
Historical / benchmarks
|
|
12258
13371
|
get-approved-budgets [--projectId] [--limit] [--minRevenue] [--maxRevenue]
|
|
@@ -12594,6 +13707,8 @@ Waiting for approval\u2026
|
|
|
12594
13707
|
});
|
|
12595
13708
|
}
|
|
12596
13709
|
try {
|
|
13710
|
+
if (flags.q === true)
|
|
13711
|
+
throw new CliRuntimeError("USAGE", "--q needs a search value (--q <text> or --q=<text>). Use -q or --quiet to hide logs.");
|
|
12597
13712
|
if (runtime.env.BB_API_KEY?.trim()) {
|
|
12598
13713
|
configureAccessToken(undefined);
|
|
12599
13714
|
} else {
|
|
@@ -12625,21 +13740,49 @@ Waiting for approval\u2026
|
|
|
12625
13740
|
await whoAmI();
|
|
12626
13741
|
break;
|
|
12627
13742
|
}
|
|
12628
|
-
case "list-budgets":
|
|
13743
|
+
case "list-budgets":
|
|
13744
|
+
case "count-budgets": {
|
|
12629
13745
|
const statusStr = getFlag(flags, "status");
|
|
12630
13746
|
const statuses = parseCommaSeparatedBudgetStatuses(statusStr !== undefined ? String(statusStr) : undefined);
|
|
12631
|
-
|
|
13747
|
+
const filters = {
|
|
12632
13748
|
projectId: getFlag(flags, "projectId"),
|
|
12633
13749
|
name: getFlag(flags, "name"),
|
|
12634
13750
|
statuses,
|
|
12635
13751
|
createdBy: getFlag(flags, "createdBy"),
|
|
12636
13752
|
dateFrom: getFlag(flags, "dateFrom"),
|
|
12637
13753
|
dateTo: getFlag(flags, "dateTo"),
|
|
12638
|
-
active: parseBudgetActiveFlag(flags)
|
|
13754
|
+
active: parseBudgetActiveFlag(flags)
|
|
13755
|
+
};
|
|
13756
|
+
rejectRetiredPageFlags(flags);
|
|
13757
|
+
if (cmd === "count-budgets") {
|
|
13758
|
+
for (const key of [
|
|
13759
|
+
"limit",
|
|
13760
|
+
"cursor",
|
|
13761
|
+
"direction",
|
|
13762
|
+
"sortBy",
|
|
13763
|
+
"sortDir"
|
|
13764
|
+
]) {
|
|
13765
|
+
if (flags[key] !== undefined)
|
|
13766
|
+
throw new Error(`count-budgets does not accept --${key}; totals use filters only.`);
|
|
13767
|
+
}
|
|
13768
|
+
await countBudgets(filters);
|
|
13769
|
+
break;
|
|
13770
|
+
}
|
|
13771
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
13772
|
+
rejectBareFlag(flags, key);
|
|
13773
|
+
const cursor = getFlag(flags, "cursor");
|
|
13774
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
13775
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
13776
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
13777
|
+
if (direction === "backward" && !cursor)
|
|
13778
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
13779
|
+
await listBudgets({
|
|
13780
|
+
...filters,
|
|
13781
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
13782
|
+
cursor,
|
|
13783
|
+
direction,
|
|
12639
13784
|
sortBy: getFlag(flags, "sortBy"),
|
|
12640
13785
|
sortDir: getFlag(flags, "sortDir"),
|
|
12641
|
-
page: parsePositiveIntFlag(getFlag(flags, "page"), "--page"),
|
|
12642
|
-
perPage: parsePositiveIntFlag(getFlag(flags, "perPage"), "--perPage"),
|
|
12643
13786
|
includeDetails: flags.summary === true ? false : parseOptionalBoolFlag(flags, "includeDetails") ?? true
|
|
12644
13787
|
});
|
|
12645
13788
|
break;
|
|
@@ -12692,7 +13835,19 @@ Waiting for approval\u2026
|
|
|
12692
13835
|
break;
|
|
12693
13836
|
}
|
|
12694
13837
|
case "get-budget-categories": {
|
|
12695
|
-
|
|
13838
|
+
rejectRetiredPageFlags(flags);
|
|
13839
|
+
for (const key of ["limit", "cursor"])
|
|
13840
|
+
rejectBareFlag(flags, key);
|
|
13841
|
+
if (flags.direction !== undefined)
|
|
13842
|
+
throw new Error("get-budget-categories pages forward only; follow pageInfo.nextCursor with --cursor.");
|
|
13843
|
+
const cursor = getFlag(flags, "cursor");
|
|
13844
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
13845
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
13846
|
+
await getBudgetCategories({
|
|
13847
|
+
q: getFlag(flags, "q"),
|
|
13848
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
13849
|
+
cursor
|
|
13850
|
+
});
|
|
12696
13851
|
break;
|
|
12697
13852
|
}
|
|
12698
13853
|
case "get-budget-versions": {
|
|
@@ -12704,7 +13859,7 @@ Waiting for approval\u2026
|
|
|
12704
13859
|
throw new CliRuntimeError("USAGE", "--limit must be an integer from 1 to 50.");
|
|
12705
13860
|
}
|
|
12706
13861
|
if (flags.cursor === true || flags.cursor === "") {
|
|
12707
|
-
throw new CliRuntimeError("USAGE", "--cursor requires
|
|
13862
|
+
throw new CliRuntimeError("USAGE", "--cursor requires the nextCursor token from the previous page.");
|
|
12708
13863
|
}
|
|
12709
13864
|
await getBudgetVersions(id, {
|
|
12710
13865
|
limit,
|
|
@@ -12985,6 +14140,14 @@ Waiting for approval\u2026
|
|
|
12985
14140
|
});
|
|
12986
14141
|
break;
|
|
12987
14142
|
}
|
|
14143
|
+
case "count-bills": {
|
|
14144
|
+
await countBills(parseCountBillsFlags(flags));
|
|
14145
|
+
break;
|
|
14146
|
+
}
|
|
14147
|
+
case "count-claims": {
|
|
14148
|
+
await countBills({ ...parseCountBillsFlags(flags), isClaimable: true });
|
|
14149
|
+
break;
|
|
14150
|
+
}
|
|
12988
14151
|
case "create-bill-approval": {
|
|
12989
14152
|
const id = positional[0];
|
|
12990
14153
|
if (!id)
|
|
@@ -13185,7 +14348,19 @@ Waiting for approval\u2026
|
|
|
13185
14348
|
const id = positional[0];
|
|
13186
14349
|
if (!id)
|
|
13187
14350
|
throw new Error("get-bill-attachments requires <billId>");
|
|
13188
|
-
|
|
14351
|
+
rejectRetiredPageFlags(flags);
|
|
14352
|
+
for (const key of ["limit", "cursor"])
|
|
14353
|
+
rejectBareFlag(flags, key);
|
|
14354
|
+
if (flags.direction !== undefined)
|
|
14355
|
+
throw new Error("get-bill-attachments pages forward only; follow pageInfo.nextCursor with --cursor.");
|
|
14356
|
+
const cursor = getFlag(flags, "cursor");
|
|
14357
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
14358
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
14359
|
+
const limitFlag = getFlag(flags, "limit");
|
|
14360
|
+
const limit = limitFlag === undefined ? undefined : Number(limitFlag);
|
|
14361
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 50))
|
|
14362
|
+
throw new Error("--limit must be an integer from 1 to 50.");
|
|
14363
|
+
await getBillAttachments({ id, limit, cursor });
|
|
13189
14364
|
break;
|
|
13190
14365
|
}
|
|
13191
14366
|
case "stage-bill-attachment": {
|
|
@@ -13278,18 +14453,32 @@ Waiting for approval\u2026
|
|
|
13278
14453
|
break;
|
|
13279
14454
|
}
|
|
13280
14455
|
case "list-quotations": {
|
|
13281
|
-
|
|
13282
|
-
const
|
|
13283
|
-
|
|
14456
|
+
rejectRetiredPageFlags(flags);
|
|
14457
|
+
for (const key of ["limit", "cursor", "direction"])
|
|
14458
|
+
rejectBareFlag(flags, key);
|
|
14459
|
+
const cursor = getFlag(flags, "cursor");
|
|
14460
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
14461
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
14462
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
14463
|
+
if (direction === "backward" && !cursor)
|
|
14464
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
13284
14465
|
await listQuotations({
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
14466
|
+
...parseQuotationFilterFlags(flags),
|
|
14467
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
14468
|
+
cursor,
|
|
14469
|
+
direction
|
|
14470
|
+
});
|
|
14471
|
+
break;
|
|
14472
|
+
}
|
|
14473
|
+
case "count-quotations": {
|
|
14474
|
+
rejectRetiredPageFlags(flags);
|
|
14475
|
+
for (const key of ["limit", "cursor", "direction"]) {
|
|
14476
|
+
if (flags[key] !== undefined)
|
|
14477
|
+
throw new Error(`count-quotations does not accept --${key}; totals use filters only.`);
|
|
14478
|
+
}
|
|
14479
|
+
await countQuotations({
|
|
14480
|
+
...parseQuotationFilterFlags(flags),
|
|
14481
|
+
includeMetrics: parseOptionalBoolFlag(flags, "includeMetrics") ?? false
|
|
13293
14482
|
});
|
|
13294
14483
|
break;
|
|
13295
14484
|
}
|
|
@@ -13411,7 +14600,8 @@ Waiting for approval\u2026
|
|
|
13411
14600
|
await listAvailableQboCustomerInvoices(budgetId);
|
|
13412
14601
|
break;
|
|
13413
14602
|
}
|
|
13414
|
-
case "list-customer-invoices":
|
|
14603
|
+
case "list-customer-invoices":
|
|
14604
|
+
case "count-customer-invoices": {
|
|
13415
14605
|
const positionalBudgetId = positional[0];
|
|
13416
14606
|
const projectId = getFlag(flags, "projectId");
|
|
13417
14607
|
const projectIds = parseCommaSeparatedIds(getFlag(flags, "projectIds"));
|
|
@@ -13423,17 +14613,44 @@ Waiting for approval\u2026
|
|
|
13423
14613
|
...parseCommaSeparatedIds(getFlag(flags, "budgetIds")) ?? []
|
|
13424
14614
|
];
|
|
13425
14615
|
const statusRaw = getFlag(flags, "status");
|
|
13426
|
-
const
|
|
13427
|
-
await listCustomerInvoices({
|
|
14616
|
+
const filters = {
|
|
13428
14617
|
scope: projectId ? { type: "project", projectId } : { type: "global" },
|
|
13429
|
-
page: parsePositiveIntFlag(getFlag(flags, "page"), "--page") ?? 1,
|
|
13430
|
-
perPage: parsePositiveIntFlag(getFlag(flags, "perPage"), "--perPage") ?? 20,
|
|
13431
14618
|
q: getFlag(flags, "search") ?? "",
|
|
13432
14619
|
statuses: parseCommaSeparatedCustomerInvoiceStatuses(statusRaw !== undefined ? String(statusRaw) : undefined),
|
|
13433
14620
|
companyIds: parseCommaSeparatedIds(getFlag(flags, "companyIds")),
|
|
13434
14621
|
projectIds,
|
|
13435
14622
|
budgetIds: budgetIds.length > 0 ? [...new Set(budgetIds)] : undefined,
|
|
13436
|
-
createdByIds: parseCommaSeparatedIds(getFlag(flags, "createdByIds"))
|
|
14623
|
+
createdByIds: parseCommaSeparatedIds(getFlag(flags, "createdByIds"))
|
|
14624
|
+
};
|
|
14625
|
+
rejectRetiredPageFlags(flags);
|
|
14626
|
+
if (cmd === "count-customer-invoices") {
|
|
14627
|
+
for (const key of [
|
|
14628
|
+
"limit",
|
|
14629
|
+
"cursor",
|
|
14630
|
+
"direction",
|
|
14631
|
+
"sortBy",
|
|
14632
|
+
"sortDir"
|
|
14633
|
+
]) {
|
|
14634
|
+
if (flags[key] !== undefined)
|
|
14635
|
+
throw new Error(`count-customer-invoices does not accept --${key}; totals use filters only.`);
|
|
14636
|
+
}
|
|
14637
|
+
await countCustomerInvoices(filters);
|
|
14638
|
+
break;
|
|
14639
|
+
}
|
|
14640
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
14641
|
+
rejectBareFlag(flags, key);
|
|
14642
|
+
const cursor = getFlag(flags, "cursor");
|
|
14643
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
14644
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
14645
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
14646
|
+
if (direction === "backward" && !cursor)
|
|
14647
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
14648
|
+
const sortDir = parseOptionalBillListSortDir(getFlag(flags, "sortDir"));
|
|
14649
|
+
await listCustomerInvoices({
|
|
14650
|
+
...filters,
|
|
14651
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
14652
|
+
cursor,
|
|
14653
|
+
direction,
|
|
13437
14654
|
sortBy: parseCustomerInvoiceSortBy(getFlag(flags, "sortBy")),
|
|
13438
14655
|
sortDir: sortDir ?? "desc"
|
|
13439
14656
|
});
|
|
@@ -13612,13 +14829,11 @@ Waiting for approval\u2026
|
|
|
13612
14829
|
break;
|
|
13613
14830
|
}
|
|
13614
14831
|
case "list-companies": {
|
|
13615
|
-
await listCompanies(
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
perPage: parsePositiveIntFlag(getFlag(flags, "perPage"), "--perPage")
|
|
13621
|
-
});
|
|
14832
|
+
await listCompanies(parseCompanyListFlags(flags));
|
|
14833
|
+
break;
|
|
14834
|
+
}
|
|
14835
|
+
case "count-companies": {
|
|
14836
|
+
await countCompanies(parseCompanyCountFlags(flags));
|
|
13622
14837
|
break;
|
|
13623
14838
|
}
|
|
13624
14839
|
case "get-company": {
|
|
@@ -13645,7 +14860,17 @@ Waiting for approval\u2026
|
|
|
13645
14860
|
const query = getFlag(flags, "query");
|
|
13646
14861
|
if (!query)
|
|
13647
14862
|
throw new Error("search-existing-companies requires --query <name>");
|
|
13648
|
-
|
|
14863
|
+
rejectRetiredPageFlags(flags);
|
|
14864
|
+
for (const key of ["limit", "cursor"])
|
|
14865
|
+
rejectBareFlag(flags, key);
|
|
14866
|
+
const cursor = getFlag(flags, "cursor");
|
|
14867
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
14868
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
14869
|
+
const limitFlag = getFlag(flags, "limit");
|
|
14870
|
+
const limit = limitFlag === undefined ? undefined : Number(limitFlag);
|
|
14871
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 50))
|
|
14872
|
+
throw new Error("--limit must be an integer from 1 to 50.");
|
|
14873
|
+
await searchExistingCompanies({ query, limit, cursor });
|
|
13649
14874
|
break;
|
|
13650
14875
|
}
|
|
13651
14876
|
case "use-existing-company": {
|
|
@@ -13678,6 +14903,13 @@ Waiting for approval\u2026
|
|
|
13678
14903
|
await updateCompanyFromPayload(raw);
|
|
13679
14904
|
break;
|
|
13680
14905
|
}
|
|
14906
|
+
case "get-company-quickbooks-sync-status": {
|
|
14907
|
+
const id = positional[0];
|
|
14908
|
+
if (!id)
|
|
14909
|
+
throw new Error("get-company-quickbooks-sync-status requires <companyId>");
|
|
14910
|
+
await getCompanyQuickBooksSyncStatus(id);
|
|
14911
|
+
break;
|
|
14912
|
+
}
|
|
13681
14913
|
case "delete-company": {
|
|
13682
14914
|
const id = positional[0];
|
|
13683
14915
|
if (!id)
|
|
@@ -13686,23 +14918,46 @@ Waiting for approval\u2026
|
|
|
13686
14918
|
break;
|
|
13687
14919
|
}
|
|
13688
14920
|
case "list-projects": {
|
|
13689
|
-
|
|
13690
|
-
await listProjects({
|
|
13691
|
-
companyId: getFlag(flags, "companyId"),
|
|
13692
|
-
name: getFlag(flags, "name"),
|
|
13693
|
-
status: parseOptionalExtendedProjectStatus(statusRaw !== undefined ? String(statusRaw) : undefined),
|
|
13694
|
-
active: parseOptionalBoolFlag(flags, "active"),
|
|
13695
|
-
page: parsePositiveIntFlag(getFlag(flags, "page"), "--page"),
|
|
13696
|
-
perPage: parsePositiveIntFlag(getFlag(flags, "perPage"), "--perPage")
|
|
13697
|
-
});
|
|
14921
|
+
await listProjects(parseProjectListFlags(flags));
|
|
13698
14922
|
break;
|
|
13699
14923
|
}
|
|
13700
|
-
case "
|
|
13701
|
-
await
|
|
14924
|
+
case "count-projects": {
|
|
14925
|
+
await countProjects(parseProjectCountFlags(flags));
|
|
14926
|
+
break;
|
|
14927
|
+
}
|
|
14928
|
+
case "list-project-hubs":
|
|
14929
|
+
case "count-project-hubs": {
|
|
14930
|
+
rejectRetiredPageFlags(flags);
|
|
14931
|
+
const filters = {
|
|
13702
14932
|
q: getFlag(flags, "q"),
|
|
13703
|
-
statuses: parseCommaSeparatedProjectStatuses(getFlag(flags, "status"))
|
|
13704
|
-
|
|
13705
|
-
|
|
14933
|
+
statuses: parseCommaSeparatedProjectStatuses(getFlag(flags, "status"))
|
|
14934
|
+
};
|
|
14935
|
+
if (cmd === "count-project-hubs") {
|
|
14936
|
+
for (const key of [
|
|
14937
|
+
"limit",
|
|
14938
|
+
"cursor",
|
|
14939
|
+
"direction",
|
|
14940
|
+
"sortBy",
|
|
14941
|
+
"sortDir"
|
|
14942
|
+
])
|
|
14943
|
+
if (flags[key] !== undefined)
|
|
14944
|
+
throw new Error(`count-project-hubs does not accept --${key}; totals use filters only.`);
|
|
14945
|
+
await countProjectHubs(filters);
|
|
14946
|
+
break;
|
|
14947
|
+
}
|
|
14948
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
14949
|
+
rejectBareFlag(flags, key);
|
|
14950
|
+
const cursor = getFlag(flags, "cursor");
|
|
14951
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
14952
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
14953
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
14954
|
+
if (direction === "backward" && !cursor)
|
|
14955
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
14956
|
+
await listProjectHubs({
|
|
14957
|
+
...filters,
|
|
14958
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
14959
|
+
cursor,
|
|
14960
|
+
direction,
|
|
13706
14961
|
sortBy: parseOptionalProjectHubSortBy(getFlag(flags, "sortBy")),
|
|
13707
14962
|
sortDir: parseOptionalBillListSortDir(getFlag(flags, "sortDir"))
|
|
13708
14963
|
});
|
|
@@ -13871,6 +15126,10 @@ Waiting for approval\u2026
|
|
|
13871
15126
|
await updateContactPersonFromPayload(raw);
|
|
13872
15127
|
break;
|
|
13873
15128
|
}
|
|
15129
|
+
case "count-suppliers": {
|
|
15130
|
+
await countSuppliers(parseCountSuppliersFlags(flags));
|
|
15131
|
+
break;
|
|
15132
|
+
}
|
|
13874
15133
|
case "list-suppliers": {
|
|
13875
15134
|
await listSuppliers(parseListSuppliersFlags(flags));
|
|
13876
15135
|
break;
|
|
@@ -13945,22 +15204,117 @@ Waiting for approval\u2026
|
|
|
13945
15204
|
await createSupplierTagOption(String(name));
|
|
13946
15205
|
break;
|
|
13947
15206
|
}
|
|
13948
|
-
case "get-supplier-analytics":
|
|
15207
|
+
case "get-supplier-analytics":
|
|
15208
|
+
case "count-supplier-analytics": {
|
|
15209
|
+
rejectRetiredPageFlags(flags);
|
|
13949
15210
|
const tfRaw = getFlag(flags, "timeFrame");
|
|
13950
|
-
|
|
15211
|
+
for (const key of [
|
|
15212
|
+
"name",
|
|
15213
|
+
"status",
|
|
15214
|
+
"gstRegistered",
|
|
15215
|
+
"createdBy",
|
|
15216
|
+
"startDate",
|
|
15217
|
+
"endDate",
|
|
15218
|
+
"timeFrame"
|
|
15219
|
+
])
|
|
15220
|
+
rejectBareFlag(flags, key);
|
|
15221
|
+
const timeFrame = parseOptionalSupplierAnalyticsTimeFrame(tfRaw !== undefined ? String(tfRaw) : undefined);
|
|
15222
|
+
const startDate = getFlag(flags, "startDate");
|
|
15223
|
+
const endDate = getFlag(flags, "endDate");
|
|
15224
|
+
if ((startDate || endDate) && timeFrame !== "CUSTOM")
|
|
15225
|
+
throw new Error("--startDate/--endDate need --timeFrame CUSTOM; other time frames ignore them.");
|
|
15226
|
+
const statusRaw = getFlag(flags, "status");
|
|
15227
|
+
const status = statusRaw?.split(",").map((value) => value.trim()).filter(Boolean);
|
|
15228
|
+
const badStatus = status?.find((value) => !Object.values(ApprovalStatus2).some((s) => s === value));
|
|
15229
|
+
if (badStatus)
|
|
15230
|
+
throw new Error(`Invalid --status ${badStatus}. Use a comma list of: ${Object.values(ApprovalStatus2).join(", ")}.`);
|
|
15231
|
+
const gstRaw = getFlag(flags, "gstRegistered");
|
|
15232
|
+
if (gstRaw !== undefined && gstRaw !== "true" && gstRaw !== "false")
|
|
15233
|
+
throw new Error("--gstRegistered must be true or false.");
|
|
15234
|
+
const filters = {
|
|
13951
15235
|
name: getFlag(flags, "name"),
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
15236
|
+
timeFrame,
|
|
15237
|
+
status: status?.length ? status : undefined,
|
|
15238
|
+
gstRegistered: gstRaw === undefined ? undefined : gstRaw === "true",
|
|
15239
|
+
createdBy: getFlag(flags, "createdBy"),
|
|
15240
|
+
startDate,
|
|
15241
|
+
endDate
|
|
15242
|
+
};
|
|
15243
|
+
if (cmd === "count-supplier-analytics") {
|
|
15244
|
+
for (const key of [
|
|
15245
|
+
"limit",
|
|
15246
|
+
"cursor",
|
|
15247
|
+
"direction",
|
|
15248
|
+
"sortBy",
|
|
15249
|
+
"sortDir"
|
|
15250
|
+
])
|
|
15251
|
+
if (flags[key] !== undefined)
|
|
15252
|
+
throw new Error(`count-supplier-analytics does not accept --${key}; totals use filters only.`);
|
|
15253
|
+
await countSupplierAnalytics(filters);
|
|
15254
|
+
break;
|
|
15255
|
+
}
|
|
15256
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
15257
|
+
rejectBareFlag(flags, key);
|
|
15258
|
+
const cursor = getFlag(flags, "cursor");
|
|
15259
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15260
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15261
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
15262
|
+
if (direction === "backward" && !cursor)
|
|
15263
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
15264
|
+
const sortBy = getFlag(flags, "sortBy");
|
|
15265
|
+
if (sortBy !== undefined && !SUPPLIER_ANALYTICS_SORT_IDS.some((id) => id === sortBy))
|
|
15266
|
+
throw new Error(`--sortBy must be one of: ${SUPPLIER_ANALYTICS_SORT_IDS.join(", ")}.`);
|
|
15267
|
+
await getSupplierAnalytics({
|
|
15268
|
+
...filters,
|
|
15269
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
15270
|
+
cursor,
|
|
15271
|
+
direction,
|
|
15272
|
+
sortBy: SUPPLIER_ANALYTICS_SORT_IDS.find((id) => id === sortBy),
|
|
15273
|
+
sortDir: parseOptionalBillListSortDir(getFlag(flags, "sortDir"))
|
|
13955
15274
|
});
|
|
13956
15275
|
break;
|
|
13957
15276
|
}
|
|
13958
|
-
case "list-items":
|
|
13959
|
-
|
|
15277
|
+
case "list-items":
|
|
15278
|
+
case "count-items": {
|
|
15279
|
+
rejectRetiredPageFlags(flags);
|
|
15280
|
+
const filters = {
|
|
13960
15281
|
includeQuickBooksDeactivationPending: flags.includeQuickBooksDeactivationPending === true ? true : parseOptionalBoolFlag(flags, "includeQuickBooksDeactivationPending"),
|
|
13961
|
-
name: getFlag(flags, "name")
|
|
13962
|
-
|
|
13963
|
-
|
|
15282
|
+
name: getFlag(flags, "name")
|
|
15283
|
+
};
|
|
15284
|
+
if (cmd === "count-items") {
|
|
15285
|
+
for (const key of [
|
|
15286
|
+
"limit",
|
|
15287
|
+
"cursor",
|
|
15288
|
+
"direction",
|
|
15289
|
+
"sortBy",
|
|
15290
|
+
"sortDir"
|
|
15291
|
+
])
|
|
15292
|
+
if (flags[key] !== undefined)
|
|
15293
|
+
throw new Error(`count-items does not accept --${key}; totals use filters only.`);
|
|
15294
|
+
await countItems(filters);
|
|
15295
|
+
break;
|
|
15296
|
+
}
|
|
15297
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
15298
|
+
rejectBareFlag(flags, key);
|
|
15299
|
+
const cursor = getFlag(flags, "cursor");
|
|
15300
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15301
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15302
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
15303
|
+
if (direction === "backward" && !cursor)
|
|
15304
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
15305
|
+
const sortBy = getFlag(flags, "sortBy");
|
|
15306
|
+
const sortId = INVENTORY_SORT_IDS.find((id) => id === sortBy);
|
|
15307
|
+
if (sortBy !== undefined && !sortId)
|
|
15308
|
+
throw new Error(`Invalid --sortBy "${sortBy}". Use one of: ${INVENTORY_SORT_IDS.join(", ")}.`);
|
|
15309
|
+
const sortDir = getFlag(flags, "sortDir");
|
|
15310
|
+
if (sortDir !== undefined && sortDir !== "asc" && sortDir !== "desc")
|
|
15311
|
+
throw new Error('--sortDir must be "asc" or "desc".');
|
|
15312
|
+
await listItems({
|
|
15313
|
+
...filters,
|
|
15314
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
15315
|
+
cursor,
|
|
15316
|
+
direction,
|
|
15317
|
+
sort: sortId ? [{ id: sortId, desc: sortDir !== "asc" }] : undefined
|
|
13964
15318
|
});
|
|
13965
15319
|
break;
|
|
13966
15320
|
}
|
|
@@ -13971,6 +15325,14 @@ Waiting for approval\u2026
|
|
|
13971
15325
|
await getItem(id);
|
|
13972
15326
|
break;
|
|
13973
15327
|
}
|
|
15328
|
+
case "get-item-quickbooks-sync-status": {
|
|
15329
|
+
const id = positional[0];
|
|
15330
|
+
if (!id) {
|
|
15331
|
+
throw new Error("get-item-quickbooks-sync-status requires <itemId>");
|
|
15332
|
+
}
|
|
15333
|
+
await getItemQuickBooksSyncStatus(id);
|
|
15334
|
+
break;
|
|
15335
|
+
}
|
|
13974
15336
|
case "create-item": {
|
|
13975
15337
|
const payloadRaw = getFlag(flags, "payload");
|
|
13976
15338
|
if (!payloadRaw) {
|
|
@@ -14008,10 +15370,45 @@ Waiting for approval\u2026
|
|
|
14008
15370
|
await archiveItemsByIds(ids);
|
|
14009
15371
|
break;
|
|
14010
15372
|
}
|
|
14011
|
-
case "list-item-categories":
|
|
15373
|
+
case "list-item-categories":
|
|
15374
|
+
case "count-item-categories": {
|
|
15375
|
+
rejectRetiredPageFlags(flags);
|
|
15376
|
+
const filters = { name: getFlag(flags, "name") };
|
|
15377
|
+
if (cmd === "count-item-categories") {
|
|
15378
|
+
for (const key of [
|
|
15379
|
+
"limit",
|
|
15380
|
+
"cursor",
|
|
15381
|
+
"direction",
|
|
15382
|
+
"sortBy",
|
|
15383
|
+
"sortDir"
|
|
15384
|
+
])
|
|
15385
|
+
if (flags[key] !== undefined)
|
|
15386
|
+
throw new Error(`count-item-categories does not accept --${key}; totals use filters only.`);
|
|
15387
|
+
await countItemCategories(filters);
|
|
15388
|
+
break;
|
|
15389
|
+
}
|
|
15390
|
+
for (const key of ["limit", "cursor", "direction", "sortBy", "sortDir"])
|
|
15391
|
+
rejectBareFlag(flags, key);
|
|
15392
|
+
const cursor = getFlag(flags, "cursor");
|
|
15393
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15394
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15395
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
15396
|
+
if (direction === "backward" && !cursor)
|
|
15397
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
15398
|
+
const sortByRaw = getFlag(flags, "sortBy");
|
|
15399
|
+
const sortBy = ITEM_CATEGORY_SORT_IDS.find((id) => id === sortByRaw);
|
|
15400
|
+
if (sortByRaw !== undefined && !sortBy)
|
|
15401
|
+
throw new Error(`Invalid --sortBy "${sortByRaw}". Use one of: ${ITEM_CATEGORY_SORT_IDS.join(", ")}.`);
|
|
15402
|
+
const sortDir = getFlag(flags, "sortDir");
|
|
15403
|
+
if (sortDir !== undefined && sortDir !== "asc" && sortDir !== "desc")
|
|
15404
|
+
throw new Error('--sortDir must be "asc" or "desc".');
|
|
14012
15405
|
await listItemCategories({
|
|
14013
|
-
|
|
14014
|
-
|
|
15406
|
+
...filters,
|
|
15407
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
15408
|
+
cursor,
|
|
15409
|
+
direction,
|
|
15410
|
+
sortBy,
|
|
15411
|
+
sortDir
|
|
14015
15412
|
});
|
|
14016
15413
|
break;
|
|
14017
15414
|
}
|
|
@@ -14043,8 +15440,29 @@ Waiting for approval\u2026
|
|
|
14043
15440
|
await deleteItemCategoriesByIds(ids);
|
|
14044
15441
|
break;
|
|
14045
15442
|
}
|
|
14046
|
-
case "list-users":
|
|
14047
|
-
|
|
15443
|
+
case "list-users":
|
|
15444
|
+
case "count-users": {
|
|
15445
|
+
rejectRetiredPageFlags(flags);
|
|
15446
|
+
const q = getFlag(flags, "q");
|
|
15447
|
+
if (cmd === "count-users") {
|
|
15448
|
+
for (const key of ["limit", "cursor"])
|
|
15449
|
+
if (flags[key] !== undefined)
|
|
15450
|
+
throw new Error(`count-users does not accept --${key}; totals use --q only.`);
|
|
15451
|
+
await countUsers({ q });
|
|
15452
|
+
break;
|
|
15453
|
+
}
|
|
15454
|
+
for (const key of ["limit", "cursor"])
|
|
15455
|
+
rejectBareFlag(flags, key);
|
|
15456
|
+
if (flags.direction !== undefined)
|
|
15457
|
+
throw new Error("list-users pages forward only; follow pageInfo.nextCursor with --cursor.");
|
|
15458
|
+
const cursor = getFlag(flags, "cursor");
|
|
15459
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15460
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15461
|
+
await listUsers({
|
|
15462
|
+
q,
|
|
15463
|
+
limit: parseProjectLimit(getFlag(flags, "limit")),
|
|
15464
|
+
cursor
|
|
15465
|
+
});
|
|
14048
15466
|
break;
|
|
14049
15467
|
}
|
|
14050
15468
|
case "create-user": {
|
|
@@ -14069,7 +15487,23 @@ Waiting for approval\u2026
|
|
|
14069
15487
|
break;
|
|
14070
15488
|
}
|
|
14071
15489
|
case "list-api-keys": {
|
|
14072
|
-
|
|
15490
|
+
rejectRetiredPageFlags(flags);
|
|
15491
|
+
for (const key of ["limit", "cursor"])
|
|
15492
|
+
rejectBareFlag(flags, key);
|
|
15493
|
+
if (flags.direction !== undefined)
|
|
15494
|
+
throw new Error("list-api-keys pages forward only; follow pageInfo.nextCursor with --cursor.");
|
|
15495
|
+
const cursor = getFlag(flags, "cursor");
|
|
15496
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15497
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15498
|
+
const limitFlag = getFlag(flags, "limit");
|
|
15499
|
+
const limit = limitFlag === undefined ? undefined : Number(limitFlag);
|
|
15500
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 100))
|
|
15501
|
+
throw new Error("--limit must be an integer from 1 to 100.");
|
|
15502
|
+
await listApiKeysForUser({
|
|
15503
|
+
userId: getFlag(flags, "userId"),
|
|
15504
|
+
limit,
|
|
15505
|
+
cursor
|
|
15506
|
+
});
|
|
14073
15507
|
break;
|
|
14074
15508
|
}
|
|
14075
15509
|
case "revoke-api-key": {
|
|
@@ -14114,29 +15548,81 @@ Waiting for approval\u2026
|
|
|
14114
15548
|
});
|
|
14115
15549
|
break;
|
|
14116
15550
|
}
|
|
14117
|
-
case "get-recent-errors":
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
15551
|
+
case "get-recent-errors":
|
|
15552
|
+
case "count-errors": {
|
|
15553
|
+
if (getFlag(flags, "page") !== undefined || getFlag(flags, "perPage") !== undefined) {
|
|
15554
|
+
throw new Error("Error logs now use --cursor and --limit; --page/--perPage are no longer supported.");
|
|
15555
|
+
}
|
|
15556
|
+
const rawTimeFrame = getFlag(flags, "timeFrame");
|
|
15557
|
+
const timeFrame = Object.values(ChartTimeFrame).find((value) => value === rawTimeFrame);
|
|
15558
|
+
if (rawTimeFrame !== undefined && timeFrame === undefined) {
|
|
15559
|
+
throw new Error(`Invalid --timeFrame. Use ${Object.values(ChartTimeFrame).join(", ")}.`);
|
|
15560
|
+
}
|
|
15561
|
+
const filters = {
|
|
14121
15562
|
severity: parseOptionalErrorSeverity(getFlag(flags, "severity")),
|
|
14122
|
-
status: parseOptionalErrorStatus(getFlag(flags, "status"))
|
|
14123
|
-
|
|
15563
|
+
status: parseOptionalErrorStatus(getFlag(flags, "status")),
|
|
15564
|
+
timeFrame
|
|
15565
|
+
};
|
|
15566
|
+
if (cmd === "count-errors") {
|
|
15567
|
+
await countErrors(filters);
|
|
15568
|
+
} else {
|
|
15569
|
+
const direction = getFlag(flags, "direction");
|
|
15570
|
+
if (direction !== undefined && direction !== "forward" && direction !== "backward") {
|
|
15571
|
+
throw new Error("--direction must be forward or backward.");
|
|
15572
|
+
}
|
|
15573
|
+
await getRecentErrors({
|
|
15574
|
+
...filters,
|
|
15575
|
+
cursor: getFlag(flags, "cursor"),
|
|
15576
|
+
limit: parsePositiveIntFlag(getFlag(flags, "limit"), "--limit"),
|
|
15577
|
+
direction
|
|
15578
|
+
});
|
|
15579
|
+
}
|
|
14124
15580
|
break;
|
|
14125
15581
|
}
|
|
14126
15582
|
case "get-error-metrics": {
|
|
14127
15583
|
await getErrorMetrics();
|
|
14128
15584
|
break;
|
|
14129
15585
|
}
|
|
14130
|
-
case "list-integration-operations":
|
|
14131
|
-
|
|
15586
|
+
case "list-integration-operations":
|
|
15587
|
+
case "count-integration-operations": {
|
|
15588
|
+
rejectRetiredPageFlags(flags);
|
|
15589
|
+
const filters = {
|
|
14132
15590
|
destination: parseCommaSeparatedIds(getFlag(flags, "destination")),
|
|
14133
|
-
page: parsePositiveIntFlag(getFlag(flags, "page"), "--page") ?? 1,
|
|
14134
|
-
perPage: parsePositiveIntFlag(getFlag(flags, "perPage"), "--perPage") ?? 25,
|
|
14135
15591
|
search: getFlag(flags, "search"),
|
|
14136
15592
|
status: parseCommaSeparatedIntegrationOperationStatuses(getFlag(flags, "status"))
|
|
15593
|
+
};
|
|
15594
|
+
if (cmd === "count-integration-operations") {
|
|
15595
|
+
for (const key of ["limit", "cursor", "direction"])
|
|
15596
|
+
if (flags[key] !== undefined)
|
|
15597
|
+
throw new Error(`count-integration-operations does not accept --${key}; totals use filters only.`);
|
|
15598
|
+
await countIntegrationOperations(filters);
|
|
15599
|
+
break;
|
|
15600
|
+
}
|
|
15601
|
+
for (const key of ["limit", "cursor", "direction"])
|
|
15602
|
+
rejectBareFlag(flags, key);
|
|
15603
|
+
const cursor = getFlag(flags, "cursor");
|
|
15604
|
+
if (cursor === "" || (cursor?.length ?? 0) > 8192)
|
|
15605
|
+
throw new Error("--cursor must be a non-empty opaque token of at most 8192 characters.");
|
|
15606
|
+
const direction = parseProjectDirection(getFlag(flags, "direction"));
|
|
15607
|
+
if (direction === "backward" && !cursor)
|
|
15608
|
+
throw new Error("--direction backward requires --cursor <token>.");
|
|
15609
|
+
const limitRaw = getFlag(flags, "limit");
|
|
15610
|
+
await listIntegrationOperations({
|
|
15611
|
+
...filters,
|
|
15612
|
+
limit: limitRaw === undefined ? 25 : parseProjectLimit(limitRaw),
|
|
15613
|
+
cursor,
|
|
15614
|
+
direction
|
|
14137
15615
|
});
|
|
14138
15616
|
break;
|
|
14139
15617
|
}
|
|
15618
|
+
case "get-integration-operation": {
|
|
15619
|
+
const operationId = positional[0];
|
|
15620
|
+
if (!operationId) {
|
|
15621
|
+
throw new Error("get-integration-operation requires <operationId>");
|
|
15622
|
+
}
|
|
15623
|
+
await getIntegrationOperation(operationId);
|
|
15624
|
+
break;
|
|
15625
|
+
}
|
|
14140
15626
|
case "retry-integration-operation": {
|
|
14141
15627
|
const operationId = positional[0];
|
|
14142
15628
|
if (!operationId) {
|
|
@@ -14149,13 +15635,153 @@ Waiting for approval\u2026
|
|
|
14149
15635
|
await retryIntegrationOperation(operationId, parseOptionalBoolFlag(flags, "confirmExternalStateReconciled") ?? false, outboundEmailResolution, getFlag(flags, "providerMessageId"));
|
|
14150
15636
|
break;
|
|
14151
15637
|
}
|
|
14152
|
-
case "list-
|
|
14153
|
-
await
|
|
14154
|
-
|
|
14155
|
-
|
|
15638
|
+
case "list-webhook-event-types": {
|
|
15639
|
+
await listWebhookEventTypes();
|
|
15640
|
+
break;
|
|
15641
|
+
}
|
|
15642
|
+
case "list-webhook-endpoints": {
|
|
15643
|
+
await listWebhookEndpoints();
|
|
15644
|
+
break;
|
|
15645
|
+
}
|
|
15646
|
+
case "get-webhook-endpoint": {
|
|
15647
|
+
const id = positional[0];
|
|
15648
|
+
if (!id)
|
|
15649
|
+
throw new Error("get-webhook-endpoint requires <id>");
|
|
15650
|
+
await getWebhookEndpoint(id);
|
|
15651
|
+
break;
|
|
15652
|
+
}
|
|
15653
|
+
case "create-webhook-endpoint": {
|
|
15654
|
+
const name = getFlag(flags, "name");
|
|
15655
|
+
const url = getFlag(flags, "url");
|
|
15656
|
+
const events = parseCommaSeparatedIds(getFlag(flags, "events"));
|
|
15657
|
+
if (!name || !url || !events?.length)
|
|
15658
|
+
throw new Error("create-webhook-endpoint requires --name, --url and --events");
|
|
15659
|
+
await createWebhookEndpoint({
|
|
15660
|
+
name,
|
|
15661
|
+
url,
|
|
15662
|
+
eventPatterns: events,
|
|
15663
|
+
enabled: parseOptionalBoolFlag(flags, "enabled") ?? true
|
|
15664
|
+
});
|
|
15665
|
+
break;
|
|
15666
|
+
}
|
|
15667
|
+
case "update-webhook-endpoint": {
|
|
15668
|
+
const id = positional[0];
|
|
15669
|
+
if (!id)
|
|
15670
|
+
throw new Error("update-webhook-endpoint requires <id>");
|
|
15671
|
+
const events = parseCommaSeparatedIds(getFlag(flags, "events"));
|
|
15672
|
+
await updateWebhookEndpoint({
|
|
15673
|
+
id,
|
|
15674
|
+
name: getFlag(flags, "name"),
|
|
15675
|
+
url: getFlag(flags, "url"),
|
|
15676
|
+
eventPatterns: events?.length ? events : undefined,
|
|
15677
|
+
enabled: parseOptionalBoolFlag(flags, "enabled")
|
|
15678
|
+
});
|
|
15679
|
+
break;
|
|
15680
|
+
}
|
|
15681
|
+
case "delete-webhook-endpoint": {
|
|
15682
|
+
const id = positional[0];
|
|
15683
|
+
if (!id)
|
|
15684
|
+
throw new Error("delete-webhook-endpoint requires <id>");
|
|
15685
|
+
await deleteWebhookEndpoint(id);
|
|
15686
|
+
break;
|
|
15687
|
+
}
|
|
15688
|
+
case "rotate-webhook-secret": {
|
|
15689
|
+
const id = positional[0];
|
|
15690
|
+
if (!id)
|
|
15691
|
+
throw new Error("rotate-webhook-secret requires <id>");
|
|
15692
|
+
const ttl = getFlag(flags, "previousSecretTtlHours");
|
|
15693
|
+
await rotateWebhookSecret({
|
|
15694
|
+
id,
|
|
15695
|
+
previousSecretTtlHours: ttl === undefined ? undefined : Number.parseInt(ttl, 10)
|
|
15696
|
+
});
|
|
15697
|
+
break;
|
|
15698
|
+
}
|
|
15699
|
+
case "send-webhook-test-event": {
|
|
15700
|
+
const id = positional[0];
|
|
15701
|
+
if (!id)
|
|
15702
|
+
throw new Error("send-webhook-test-event requires <id>");
|
|
15703
|
+
await sendWebhookTestEvent(id);
|
|
15704
|
+
break;
|
|
15705
|
+
}
|
|
15706
|
+
case "list-webhook-deliveries": {
|
|
15707
|
+
const status = getFlag(flags, "status");
|
|
15708
|
+
if (status && status !== "PENDING" && status !== "SUCCEEDED" && status !== "FAILED")
|
|
15709
|
+
throw new Error("--status must be PENDING, SUCCEEDED or FAILED");
|
|
15710
|
+
await listWebhookDeliveries({
|
|
15711
|
+
endpointId: getFlag(flags, "endpointId"),
|
|
15712
|
+
status,
|
|
15713
|
+
eventType: getFlag(flags, "eventType"),
|
|
15714
|
+
cursor: getFlag(flags, "cursor"),
|
|
15715
|
+
limit: parsePositiveIntFlag(getFlag(flags, "limit"), "--limit")
|
|
14156
15716
|
});
|
|
14157
15717
|
break;
|
|
14158
15718
|
}
|
|
15719
|
+
case "get-webhook-delivery": {
|
|
15720
|
+
const id = positional[0];
|
|
15721
|
+
if (!id)
|
|
15722
|
+
throw new Error("get-webhook-delivery requires <id>");
|
|
15723
|
+
await getWebhookDelivery(id);
|
|
15724
|
+
break;
|
|
15725
|
+
}
|
|
15726
|
+
case "replay-webhook-delivery": {
|
|
15727
|
+
const id = positional[0];
|
|
15728
|
+
if (!id)
|
|
15729
|
+
throw new Error("replay-webhook-delivery requires <id>");
|
|
15730
|
+
await replayWebhookDelivery(id);
|
|
15731
|
+
break;
|
|
15732
|
+
}
|
|
15733
|
+
case "reconcile-resource-operation": {
|
|
15734
|
+
const operationId = positional[0];
|
|
15735
|
+
if (!operationId) {
|
|
15736
|
+
throw new Error("reconcile-resource-operation requires <operationId>");
|
|
15737
|
+
}
|
|
15738
|
+
await reconcileResourceOperation(operationId);
|
|
15739
|
+
break;
|
|
15740
|
+
}
|
|
15741
|
+
case "list-inbound-sources":
|
|
15742
|
+
case "count-inbound-sources": {
|
|
15743
|
+
if (flags.page !== undefined || flags.perPage !== undefined)
|
|
15744
|
+
throw new Error("Inbound sources now use --limit/--cursor/--direction; --page/--perPage are no longer supported.");
|
|
15745
|
+
for (const key of ["search", "processingMode", "cursor", "direction"]) {
|
|
15746
|
+
if (flags[key] === true)
|
|
15747
|
+
throw new Error(`--${key} requires a value.`);
|
|
15748
|
+
}
|
|
15749
|
+
const enabled = flags.processingEnabled;
|
|
15750
|
+
if (enabled !== undefined && enabled !== "true" && enabled !== "false")
|
|
15751
|
+
throw new Error("--processingEnabled must be true or false.");
|
|
15752
|
+
const mode = getFlag(flags, "processingMode");
|
|
15753
|
+
const processingMode = Object.values(InboundProcessingMode).find((value) => value === mode);
|
|
15754
|
+
if (mode !== undefined && processingMode === undefined)
|
|
15755
|
+
throw new Error("Invalid --processingMode. Use ACTIVE, COLLECT_ONLY or SHADOW.");
|
|
15756
|
+
const filters = {
|
|
15757
|
+
search: getFlag(flags, "search"),
|
|
15758
|
+
processingEnabled: enabled === undefined ? undefined : enabled === "true",
|
|
15759
|
+
processingMode
|
|
15760
|
+
};
|
|
15761
|
+
if (cmd === "count-inbound-sources") {
|
|
15762
|
+
if (["limit", "cursor", "direction"].some((key) => flags[key] !== undefined))
|
|
15763
|
+
throw new Error("Source counts accept filters only, not pagination flags.");
|
|
15764
|
+
await countInboundSources(filters);
|
|
15765
|
+
} else {
|
|
15766
|
+
const direction = getFlag(flags, "direction") ?? "forward";
|
|
15767
|
+
if (direction !== "forward" && direction !== "backward")
|
|
15768
|
+
throw new Error("--direction must be forward or backward.");
|
|
15769
|
+
const cursor = getFlag(flags, "cursor");
|
|
15770
|
+
if (direction === "backward" && !cursor)
|
|
15771
|
+
throw new Error("Backward source pagination requires --cursor.");
|
|
15772
|
+
const rawLimit = flags.limit;
|
|
15773
|
+
const limit = rawLimit === undefined ? 25 : Number(rawLimit);
|
|
15774
|
+
if (rawLimit === true || !Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
15775
|
+
throw new Error("--limit must be an integer between 1 and 100.");
|
|
15776
|
+
await listInboundSources({
|
|
15777
|
+
...filters,
|
|
15778
|
+
cursor,
|
|
15779
|
+
direction,
|
|
15780
|
+
limit
|
|
15781
|
+
});
|
|
15782
|
+
}
|
|
15783
|
+
break;
|
|
15784
|
+
}
|
|
14159
15785
|
case "create-inbound-source": {
|
|
14160
15786
|
const name = getFlag(flags, "name");
|
|
14161
15787
|
const externalSourceId = getFlag(flags, "formId");
|
|
@@ -14182,13 +15808,20 @@ Waiting for approval\u2026
|
|
|
14182
15808
|
break;
|
|
14183
15809
|
}
|
|
14184
15810
|
case "list-inbound-submissions": {
|
|
15811
|
+
if (getFlag(flags, "page") !== undefined || getFlag(flags, "perPage") !== undefined) {
|
|
15812
|
+
throw new Error("Inbound submissions now use --limit and --cursor; --page/--perPage are no longer supported.");
|
|
15813
|
+
}
|
|
14185
15814
|
await listInboundSubmissions({
|
|
14186
|
-
|
|
14187
|
-
|
|
15815
|
+
cursor: getFlag(flags, "cursor"),
|
|
15816
|
+
limit: parsePositiveIntFlag(getFlag(flags, "limit"), "--limit") ?? 25,
|
|
14188
15817
|
sourceId: getFlag(flags, "sourceId")
|
|
14189
15818
|
});
|
|
14190
15819
|
break;
|
|
14191
15820
|
}
|
|
15821
|
+
case "count-inbound-submissions": {
|
|
15822
|
+
await countInboundSubmissions({ sourceId: getFlag(flags, "sourceId") });
|
|
15823
|
+
break;
|
|
15824
|
+
}
|
|
14192
15825
|
case "get-inbound-submission": {
|
|
14193
15826
|
const submissionId = positional[0];
|
|
14194
15827
|
if (!submissionId) {
|