@ted-galago/wave-cli 0.1.5 → 0.1.7
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 +166 -2
- package/dist/index.cjs +3290 -319
- package/dist/index.js +3288 -317
- package/package.json +2 -1
- package/scripts/benchmark-cli.mjs +626 -0
- package/scripts/verify-dev-api.mjs +417 -27
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
5
|
var import_commander2 = require("commander");
|
|
6
|
-
var
|
|
6
|
+
var import_zod16 = require("zod");
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
var import_commander = require("commander");
|
|
10
10
|
|
|
11
11
|
// src/commands/tasks.ts
|
|
12
|
-
var
|
|
12
|
+
var import_zod2 = require("zod");
|
|
13
13
|
|
|
14
14
|
// src/config.ts
|
|
15
15
|
var import_zod = require("zod");
|
|
@@ -188,6 +188,16 @@ function inferStatusFromGraphqlErrors(errors) {
|
|
|
188
188
|
if (!Array.isArray(errors) || errors.length === 0) {
|
|
189
189
|
return 400;
|
|
190
190
|
}
|
|
191
|
+
const codes = extractGraphqlErrorCodes(errors);
|
|
192
|
+
if (codes.includes("UNAUTHORIZED")) {
|
|
193
|
+
return 401;
|
|
194
|
+
}
|
|
195
|
+
if (codes.includes("NOT_FOUND")) {
|
|
196
|
+
return 404;
|
|
197
|
+
}
|
|
198
|
+
if (codes.includes("INVALID_SCOPE") || codes.includes("UNSUPPORTED_BRANCH")) {
|
|
199
|
+
return 400;
|
|
200
|
+
}
|
|
191
201
|
const text = JSON.stringify(errors).toLowerCase();
|
|
192
202
|
if (text.includes("unauthorized") || text.includes("not authenticated")) {
|
|
193
203
|
return 401;
|
|
@@ -203,13 +213,260 @@ function inferStatusFromGraphqlErrors(errors) {
|
|
|
203
213
|
}
|
|
204
214
|
return 400;
|
|
205
215
|
}
|
|
216
|
+
function extractGraphqlErrorCodes(errors) {
|
|
217
|
+
if (!Array.isArray(errors)) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const codes = errors.map((entry) => {
|
|
221
|
+
if (!entry || typeof entry !== "object") return "";
|
|
222
|
+
const extensions = entry.extensions;
|
|
223
|
+
if (!extensions || typeof extensions !== "object") return "";
|
|
224
|
+
return String(extensions.code ?? "").toUpperCase();
|
|
225
|
+
}).filter((code) => code.length > 0);
|
|
226
|
+
return Array.from(new Set(codes));
|
|
227
|
+
}
|
|
228
|
+
function errorCodeFromGraphqlErrors(errors, status) {
|
|
229
|
+
const codes = extractGraphqlErrorCodes(errors);
|
|
230
|
+
if (codes.includes("UNAUTHORIZED")) {
|
|
231
|
+
return "missing_auth";
|
|
232
|
+
}
|
|
233
|
+
if (codes.includes("NOT_FOUND")) {
|
|
234
|
+
return "not_found";
|
|
235
|
+
}
|
|
236
|
+
if (codes.includes("INVALID_SCOPE")) {
|
|
237
|
+
return "invalid_scope";
|
|
238
|
+
}
|
|
239
|
+
if (codes.includes("UNSUPPORTED_BRANCH")) {
|
|
240
|
+
return "unsupported_branch";
|
|
241
|
+
}
|
|
242
|
+
if (status === 401) {
|
|
243
|
+
return "missing_auth";
|
|
244
|
+
}
|
|
245
|
+
if (status === 403) {
|
|
246
|
+
return "forbidden";
|
|
247
|
+
}
|
|
248
|
+
return `http_${status}`;
|
|
249
|
+
}
|
|
206
250
|
function errorFromGraphqlErrors(errors, status) {
|
|
207
251
|
return {
|
|
208
|
-
code:
|
|
252
|
+
code: errorCodeFromGraphqlErrors(errors, status),
|
|
209
253
|
message: "GraphQL request failed.",
|
|
210
254
|
details: { errors }
|
|
211
255
|
};
|
|
212
256
|
}
|
|
257
|
+
function findParentContextFromVariables(variables) {
|
|
258
|
+
const directParent = Object.entries(variables).find(([key, value]) => {
|
|
259
|
+
if (key === "organization_id" || key === "organizationId") return false;
|
|
260
|
+
if (!key.endsWith("_id") && !key.endsWith("Id")) return false;
|
|
261
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
262
|
+
});
|
|
263
|
+
if (directParent) {
|
|
264
|
+
return { parentKey: directParent[0], parentId: String(directParent[1]) };
|
|
265
|
+
}
|
|
266
|
+
const params = variables.params && typeof variables.params === "object" && !Array.isArray(variables.params) ? variables.params : void 0;
|
|
267
|
+
if (!params) {
|
|
268
|
+
return {};
|
|
269
|
+
}
|
|
270
|
+
const rootObjectEntry = Object.entries(params).find(
|
|
271
|
+
([, value]) => value && typeof value === "object" && !Array.isArray(value)
|
|
272
|
+
);
|
|
273
|
+
if (!rootObjectEntry) {
|
|
274
|
+
return {};
|
|
275
|
+
}
|
|
276
|
+
const [, rootObject] = rootObjectEntry;
|
|
277
|
+
const parentEntry = Object.entries(rootObject).find(([key, value]) => {
|
|
278
|
+
if (!key.endsWith("_id") && !key.endsWith("Id")) return false;
|
|
279
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
280
|
+
});
|
|
281
|
+
if (!parentEntry) {
|
|
282
|
+
return {};
|
|
283
|
+
}
|
|
284
|
+
return { parentKey: parentEntry[0], parentId: String(parentEntry[1]) };
|
|
285
|
+
}
|
|
286
|
+
function shouldAddSparse422Diagnostic(status, mutationPayload) {
|
|
287
|
+
if (status !== 422) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
const rawErrors = mutationPayload.errors && typeof mutationPayload.errors === "object" ? mutationPayload.errors : void 0;
|
|
291
|
+
if (!rawErrors) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
const dataErrors = rawErrors.data;
|
|
295
|
+
return Array.isArray(dataErrors) && dataErrors.length === 0;
|
|
296
|
+
}
|
|
297
|
+
function buildSparse422Diagnostic(input) {
|
|
298
|
+
const parentContext = findParentContextFromVariables(input.variables);
|
|
299
|
+
return {
|
|
300
|
+
operation: input.command,
|
|
301
|
+
field: input.field,
|
|
302
|
+
context: parentContext.parentKey && parentContext.parentId ? {
|
|
303
|
+
parentKey: parentContext.parentKey,
|
|
304
|
+
parentId: parentContext.parentId
|
|
305
|
+
} : {
|
|
306
|
+
message: "No explicit parent id found in request variables."
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function isFeedbackCreateCommand(input) {
|
|
311
|
+
return input.operationType === "mutation" && input.command === "feedbacks.create";
|
|
312
|
+
}
|
|
313
|
+
function asRecord(value) {
|
|
314
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
return value;
|
|
318
|
+
}
|
|
319
|
+
function asNonEmptyString(value) {
|
|
320
|
+
if (typeof value !== "string") {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
const trimmed = value.trim();
|
|
324
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
325
|
+
}
|
|
326
|
+
function extractFeedbackIdentity(variables) {
|
|
327
|
+
const organizationId = asNonEmptyString(variables.organization_id) ?? asNonEmptyString(variables.organizationId);
|
|
328
|
+
const params = asRecord(variables.params);
|
|
329
|
+
const feedback = params ? asRecord(params.feedback) : null;
|
|
330
|
+
const name = feedback ? asNonEmptyString(feedback.name) : null;
|
|
331
|
+
const quarter = feedback ? asNonEmptyString(feedback.quarter) : null;
|
|
332
|
+
const year = feedback ? asNonEmptyString(feedback.year) : null;
|
|
333
|
+
if (!organizationId || !name || !quarter || !year) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
organizationId,
|
|
338
|
+
name,
|
|
339
|
+
quarter,
|
|
340
|
+
year
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function collectMessageStrings(value) {
|
|
344
|
+
if (typeof value === "string") {
|
|
345
|
+
return [value];
|
|
346
|
+
}
|
|
347
|
+
if (Array.isArray(value)) {
|
|
348
|
+
return value.flatMap((entry) => collectMessageStrings(entry));
|
|
349
|
+
}
|
|
350
|
+
if (!value || typeof value !== "object") {
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
return Object.values(value).flatMap(
|
|
354
|
+
(entry) => collectMessageStrings(entry)
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
function isDuplicateFeedbackMutationError(mutationPayload) {
|
|
358
|
+
const messages = collectMessageStrings(mutationPayload.errors);
|
|
359
|
+
return messages.some(
|
|
360
|
+
(message) => message.toLowerCase().includes("already been taken")
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
function extractFeedbackListNode(graph) {
|
|
364
|
+
const data = asRecord(graph.data);
|
|
365
|
+
const feedbacks = data ? asRecord(data.feedbacks) : null;
|
|
366
|
+
if (!feedbacks) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
const rows = Array.isArray(feedbacks.data) ? feedbacks.data : [];
|
|
370
|
+
const first = rows.find((entry) => asRecord(entry));
|
|
371
|
+
return first ? first : null;
|
|
372
|
+
}
|
|
373
|
+
function buildFeedbackReuseEnvelope(params) {
|
|
374
|
+
return {
|
|
375
|
+
envelope: buildEnvelope({
|
|
376
|
+
ok: true,
|
|
377
|
+
command: params.command,
|
|
378
|
+
status: params.status,
|
|
379
|
+
data: {
|
|
380
|
+
[params.field]: {
|
|
381
|
+
ok: true,
|
|
382
|
+
status: params.status,
|
|
383
|
+
errorCode: null,
|
|
384
|
+
data: {
|
|
385
|
+
data: params.feedbackNode
|
|
386
|
+
},
|
|
387
|
+
errors: null,
|
|
388
|
+
reusedExisting: true,
|
|
389
|
+
idempotency: {
|
|
390
|
+
reason: params.reason
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
error: null,
|
|
395
|
+
requestId: params.requestId
|
|
396
|
+
}),
|
|
397
|
+
exitCode: EXIT_CODES.success
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
function buildFeedbackFindRequestBody(command, identity) {
|
|
401
|
+
return buildGraphqlBody({
|
|
402
|
+
config: {
|
|
403
|
+
baseUrl: "http://localhost",
|
|
404
|
+
token: "placeholder",
|
|
405
|
+
timeoutMs: 1e3,
|
|
406
|
+
debug: false
|
|
407
|
+
},
|
|
408
|
+
command,
|
|
409
|
+
operationType: "query",
|
|
410
|
+
field: "feedbacks",
|
|
411
|
+
variables: {
|
|
412
|
+
organization_id: identity.organizationId,
|
|
413
|
+
name: identity.name,
|
|
414
|
+
quarter: identity.quarter,
|
|
415
|
+
year: identity.year,
|
|
416
|
+
page: 1,
|
|
417
|
+
per: 1
|
|
418
|
+
},
|
|
419
|
+
selectionSet: "{ data { id type attributes } count currentPage totalPages }"
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
async function requestGraphqlHttp(params) {
|
|
423
|
+
const response = await fetch(params.url, {
|
|
424
|
+
method: "POST",
|
|
425
|
+
headers: {
|
|
426
|
+
Authorization: `Bearer ${params.input.config.token}`,
|
|
427
|
+
Accept: "application/json",
|
|
428
|
+
"Content-Type": "application/json",
|
|
429
|
+
"X-Origin": "langgraph-cli",
|
|
430
|
+
"X-Request-Id": params.requestId,
|
|
431
|
+
...params.input.config.agentName ? { "X-Agent-Name": params.input.config.agentName } : {},
|
|
432
|
+
...params.input.config.agentRunId ? { "X-Agent-Run-Id": params.input.config.agentRunId } : {}
|
|
433
|
+
},
|
|
434
|
+
body: JSON.stringify(params.body),
|
|
435
|
+
signal: params.controller.signal
|
|
436
|
+
});
|
|
437
|
+
const responseRequestId = response.headers.get("x-request-id") ?? params.requestId;
|
|
438
|
+
const text = await response.text();
|
|
439
|
+
const payload = text ? parseJsonSafely(text) : null;
|
|
440
|
+
const graph = payload && typeof payload === "object" ? payload : {};
|
|
441
|
+
return {
|
|
442
|
+
status: response.status,
|
|
443
|
+
requestId: responseRequestId,
|
|
444
|
+
graph
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
async function findExistingFeedback(params) {
|
|
448
|
+
const command = `${params.input.command}.find-existing`;
|
|
449
|
+
const body = buildFeedbackFindRequestBody(command, params.identity);
|
|
450
|
+
const http = await requestGraphqlHttp({
|
|
451
|
+
input: params.input,
|
|
452
|
+
url: params.url,
|
|
453
|
+
requestId: params.requestId,
|
|
454
|
+
body,
|
|
455
|
+
controller: params.controller
|
|
456
|
+
});
|
|
457
|
+
const gqlErrors = http.graph.errors;
|
|
458
|
+
if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const feedbackNode = extractFeedbackListNode(http.graph);
|
|
462
|
+
if (!feedbackNode) {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
feedbackNode,
|
|
467
|
+
requestId: http.requestId
|
|
468
|
+
};
|
|
469
|
+
}
|
|
213
470
|
function graphqlTypeForValue(value) {
|
|
214
471
|
if (Array.isArray(value)) {
|
|
215
472
|
const firstNonNull = value.find((item) => item !== null && item !== void 0);
|
|
@@ -242,6 +499,22 @@ function graphqlTypeForVariable(name, value) {
|
|
|
242
499
|
function withNonNull(typeName) {
|
|
243
500
|
return typeName.endsWith("!") ? typeName : `${typeName}!`;
|
|
244
501
|
}
|
|
502
|
+
function splitSelectionAndFragments(selectionSet) {
|
|
503
|
+
const trimmed = selectionSet.trim();
|
|
504
|
+
if (trimmed.length === 0) {
|
|
505
|
+
return { fieldSelection: "{}", fragmentDefinitions: "" };
|
|
506
|
+
}
|
|
507
|
+
const fragmentMatch = /\bfragment\s+[A-Za-z0-9_]+\s+on\s+[A-Za-z0-9_]+\s*\{/.exec(trimmed);
|
|
508
|
+
if (!fragmentMatch || fragmentMatch.index <= 0) {
|
|
509
|
+
return { fieldSelection: trimmed, fragmentDefinitions: "" };
|
|
510
|
+
}
|
|
511
|
+
const fieldSelection = trimmed.slice(0, fragmentMatch.index).trim();
|
|
512
|
+
const fragmentDefinitions = trimmed.slice(fragmentMatch.index).trim();
|
|
513
|
+
return {
|
|
514
|
+
fieldSelection: fieldSelection.length > 0 ? fieldSelection : "{}",
|
|
515
|
+
fragmentDefinitions
|
|
516
|
+
};
|
|
517
|
+
}
|
|
245
518
|
function normalizeGraphqlVariables(variables) {
|
|
246
519
|
const normalized = {};
|
|
247
520
|
Object.entries(variables).forEach(([key, value]) => {
|
|
@@ -252,13 +525,20 @@ function normalizeGraphqlVariables(variables) {
|
|
|
252
525
|
function buildGraphqlBody(input) {
|
|
253
526
|
const graphqlField = toCamelCase(input.field);
|
|
254
527
|
const graphqlVariables = normalizeGraphqlVariables(input.variables);
|
|
528
|
+
const graphqlVariableTypes = normalizeGraphqlVariables(input.variableTypes ?? {});
|
|
255
529
|
const operationName = input.operationName ?? graphqlOperationName(input.command);
|
|
256
530
|
const variableEntries = Object.entries(graphqlVariables).filter(([, value]) => value !== void 0);
|
|
257
|
-
const variableDecl = variableEntries.map(([name, value]) =>
|
|
531
|
+
const variableDecl = variableEntries.map(([name, value]) => {
|
|
532
|
+
const overriddenType = graphqlVariableTypes[name];
|
|
533
|
+
const hasOverriddenType = typeof overriddenType === "string" && overriddenType.trim().length > 0;
|
|
534
|
+
const typeName = hasOverriddenType ? overriddenType.trim() : graphqlTypeForVariable(name, value);
|
|
535
|
+
return `$${name}: ${hasOverriddenType ? typeName : withNonNull(typeName)}`;
|
|
536
|
+
}).join(", ");
|
|
258
537
|
const fieldArgs = variableEntries.map(([name]) => `${name}: $${name}`).join(", ");
|
|
259
538
|
const signature = variableDecl.length > 0 ? `(${variableDecl})` : "";
|
|
260
539
|
const args = fieldArgs.length > 0 ? `(${fieldArgs})` : "";
|
|
261
|
-
const
|
|
540
|
+
const selection = splitSelectionAndFragments(input.selectionSet);
|
|
541
|
+
const query = `${input.operationType} ${operationName}${signature} { ${graphqlField}${args} ${selection.fieldSelection} }${selection.fragmentDefinitions.length > 0 ? ` ${selection.fragmentDefinitions}` : ""}`;
|
|
262
542
|
return {
|
|
263
543
|
operationName,
|
|
264
544
|
query,
|
|
@@ -279,24 +559,37 @@ async function graphqlRequest(input) {
|
|
|
279
559
|
const controller = new AbortController();
|
|
280
560
|
const timeoutId = setTimeout(() => controller.abort(), input.config.timeoutMs);
|
|
281
561
|
try {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
562
|
+
if (isFeedbackCreateCommand(input)) {
|
|
563
|
+
const feedbackIdentity = extractFeedbackIdentity(input.variables);
|
|
564
|
+
if (feedbackIdentity) {
|
|
565
|
+
const existing = await findExistingFeedback({
|
|
566
|
+
input,
|
|
567
|
+
url,
|
|
568
|
+
requestId,
|
|
569
|
+
controller,
|
|
570
|
+
identity: feedbackIdentity
|
|
571
|
+
});
|
|
572
|
+
if (existing) {
|
|
573
|
+
return buildFeedbackReuseEnvelope({
|
|
574
|
+
command: input.command,
|
|
575
|
+
field: input.field,
|
|
576
|
+
status: 200,
|
|
577
|
+
requestId: existing.requestId,
|
|
578
|
+
feedbackNode: existing.feedbackNode,
|
|
579
|
+
reason: "preexisting"
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
const http = await requestGraphqlHttp({
|
|
585
|
+
input,
|
|
586
|
+
url,
|
|
587
|
+
requestId,
|
|
588
|
+
body,
|
|
589
|
+
controller
|
|
295
590
|
});
|
|
296
|
-
const responseRequestId =
|
|
297
|
-
const
|
|
298
|
-
const payload = text ? parseJsonSafely(text) : null;
|
|
299
|
-
const graph = payload && typeof payload === "object" ? payload : {};
|
|
591
|
+
const responseRequestId = http.requestId;
|
|
592
|
+
const graph = http.graph;
|
|
300
593
|
const gqlErrors = graph.errors;
|
|
301
594
|
const gqlData = graph.data && typeof graph.data === "object" ? graph.data : {};
|
|
302
595
|
if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
|
|
@@ -319,6 +612,36 @@ async function graphqlRequest(input) {
|
|
|
319
612
|
const ok = Boolean(mutationPayload.ok);
|
|
320
613
|
const status = typeof mutationPayload.status === "number" ? mutationPayload.status : ok ? 200 : 400;
|
|
321
614
|
if (!ok) {
|
|
615
|
+
if (isFeedbackCreateCommand(input) && isDuplicateFeedbackMutationError(mutationPayload)) {
|
|
616
|
+
const feedbackIdentity = extractFeedbackIdentity(input.variables);
|
|
617
|
+
if (feedbackIdentity) {
|
|
618
|
+
const existing = await findExistingFeedback({
|
|
619
|
+
input,
|
|
620
|
+
url,
|
|
621
|
+
requestId: responseRequestId,
|
|
622
|
+
controller,
|
|
623
|
+
identity: feedbackIdentity
|
|
624
|
+
});
|
|
625
|
+
if (existing) {
|
|
626
|
+
return buildFeedbackReuseEnvelope({
|
|
627
|
+
command: input.command,
|
|
628
|
+
field: input.field,
|
|
629
|
+
status: 200,
|
|
630
|
+
requestId: existing.requestId,
|
|
631
|
+
feedbackNode: existing.feedbackNode,
|
|
632
|
+
reason: "duplicate_race"
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
const mutationErrors = mutationPayload.errors ?? null;
|
|
638
|
+
const details = {
|
|
639
|
+
errors: mutationErrors,
|
|
640
|
+
data: mutationPayload.data ?? null
|
|
641
|
+
};
|
|
642
|
+
if (shouldAddSparse422Diagnostic(status, mutationPayload)) {
|
|
643
|
+
details.fallbackDiagnostic = buildSparse422Diagnostic(input);
|
|
644
|
+
}
|
|
322
645
|
return {
|
|
323
646
|
envelope: buildEnvelope({
|
|
324
647
|
ok: false,
|
|
@@ -330,10 +653,7 @@ async function graphqlRequest(input) {
|
|
|
330
653
|
mutationPayload.errorCode ?? mutationPayload.error_code ?? `http_${status}`
|
|
331
654
|
),
|
|
332
655
|
message: "Mutation failed.",
|
|
333
|
-
details
|
|
334
|
-
errors: mutationPayload.errors ?? null,
|
|
335
|
-
data: mutationPayload.data ?? null
|
|
336
|
-
}
|
|
656
|
+
details
|
|
337
657
|
},
|
|
338
658
|
requestId: responseRequestId
|
|
339
659
|
}),
|
|
@@ -373,7 +693,7 @@ async function graphqlRequest(input) {
|
|
|
373
693
|
envelope: buildEnvelope({
|
|
374
694
|
ok: true,
|
|
375
695
|
command: input.command,
|
|
376
|
-
status:
|
|
696
|
+
status: http.status >= 200 && http.status < 300 ? http.status : 200,
|
|
377
697
|
data: { [input.field]: fieldPayload ?? null },
|
|
378
698
|
error: null,
|
|
379
699
|
requestId: responseRequestId
|
|
@@ -413,6 +733,494 @@ function printEnvelopeAndExit(params) {
|
|
|
413
733
|
}
|
|
414
734
|
|
|
415
735
|
// src/commandRunner.ts
|
|
736
|
+
var RESOURCE_QUERY_FIELDS = {
|
|
737
|
+
task: [
|
|
738
|
+
"summary",
|
|
739
|
+
"slug",
|
|
740
|
+
"description",
|
|
741
|
+
"notes",
|
|
742
|
+
"status",
|
|
743
|
+
"priority",
|
|
744
|
+
"rank",
|
|
745
|
+
"dueDate",
|
|
746
|
+
"createdAt",
|
|
747
|
+
"updatedAt",
|
|
748
|
+
"archivedAt",
|
|
749
|
+
"organizationId",
|
|
750
|
+
"memberId",
|
|
751
|
+
"creatorId",
|
|
752
|
+
"projectId",
|
|
753
|
+
"projectSlug",
|
|
754
|
+
"taskId",
|
|
755
|
+
"labelIds",
|
|
756
|
+
"estimateIds",
|
|
757
|
+
"subtasksCount",
|
|
758
|
+
"completedSubtasksCount"
|
|
759
|
+
],
|
|
760
|
+
issue: [
|
|
761
|
+
"name",
|
|
762
|
+
"slug",
|
|
763
|
+
"description",
|
|
764
|
+
"notes",
|
|
765
|
+
"status",
|
|
766
|
+
"priority",
|
|
767
|
+
"rank",
|
|
768
|
+
"dueBy",
|
|
769
|
+
"createdAt",
|
|
770
|
+
"updatedAt",
|
|
771
|
+
"archivedAt",
|
|
772
|
+
"organizationId",
|
|
773
|
+
"memberId",
|
|
774
|
+
"creatorId",
|
|
775
|
+
"issueGroupId",
|
|
776
|
+
"issueGroupSlug",
|
|
777
|
+
"issueType",
|
|
778
|
+
"labelIds",
|
|
779
|
+
"subIssuesCount",
|
|
780
|
+
"completedSubIssuesCount"
|
|
781
|
+
],
|
|
782
|
+
team: [
|
|
783
|
+
"name",
|
|
784
|
+
"slug",
|
|
785
|
+
"createdAt",
|
|
786
|
+
"updatedAt",
|
|
787
|
+
"memberIds",
|
|
788
|
+
"leadMemberId",
|
|
789
|
+
"organizationId",
|
|
790
|
+
"responsibilities",
|
|
791
|
+
"keyMetric"
|
|
792
|
+
],
|
|
793
|
+
member: [
|
|
794
|
+
"slug",
|
|
795
|
+
"email",
|
|
796
|
+
"role",
|
|
797
|
+
"status",
|
|
798
|
+
"title",
|
|
799
|
+
"firstName",
|
|
800
|
+
"lastName",
|
|
801
|
+
"createdAt",
|
|
802
|
+
"updatedAt",
|
|
803
|
+
"lastActiveAt",
|
|
804
|
+
"deactivatedAt",
|
|
805
|
+
"organizationId",
|
|
806
|
+
"organizationSlug",
|
|
807
|
+
"userId",
|
|
808
|
+
"coachId",
|
|
809
|
+
"timezone",
|
|
810
|
+
"province",
|
|
811
|
+
"birthdate",
|
|
812
|
+
"workAnniversary",
|
|
813
|
+
"phone",
|
|
814
|
+
"pinned",
|
|
815
|
+
"rocksCount",
|
|
816
|
+
"measurablesCount",
|
|
817
|
+
"smartKpisCount"
|
|
818
|
+
],
|
|
819
|
+
rock: [
|
|
820
|
+
"name",
|
|
821
|
+
"slug",
|
|
822
|
+
"description",
|
|
823
|
+
"notes",
|
|
824
|
+
"status",
|
|
825
|
+
"priority",
|
|
826
|
+
"rank",
|
|
827
|
+
"dueBy",
|
|
828
|
+
"createdAt",
|
|
829
|
+
"updatedAt",
|
|
830
|
+
"archivedAt",
|
|
831
|
+
"organizationId",
|
|
832
|
+
"memberId",
|
|
833
|
+
"creatorId",
|
|
834
|
+
"rockCollectionId",
|
|
835
|
+
"rockCollectionSlug",
|
|
836
|
+
"quarterlyObjectiveId",
|
|
837
|
+
"rockType",
|
|
838
|
+
"labelIds",
|
|
839
|
+
"milestonesCount",
|
|
840
|
+
"completedMilestonesCount"
|
|
841
|
+
],
|
|
842
|
+
meeting: [
|
|
843
|
+
"createdAt",
|
|
844
|
+
"updatedAt",
|
|
845
|
+
"name",
|
|
846
|
+
"slug",
|
|
847
|
+
"status",
|
|
848
|
+
"description",
|
|
849
|
+
"notes",
|
|
850
|
+
"useAiTranscript",
|
|
851
|
+
"aiTranscript",
|
|
852
|
+
"aiTranscriptStatus",
|
|
853
|
+
"aiTranscriptError",
|
|
854
|
+
"aiTranscriptUpdatedAt",
|
|
855
|
+
"aiSummary",
|
|
856
|
+
"aiSummaryStatus",
|
|
857
|
+
"aiSummaryError",
|
|
858
|
+
"aiSummaryUpdatedAt",
|
|
859
|
+
"repeats",
|
|
860
|
+
"color",
|
|
861
|
+
"talkingPointsCount",
|
|
862
|
+
"completedTalkingPointsCount",
|
|
863
|
+
"date",
|
|
864
|
+
"startTime",
|
|
865
|
+
"endTime",
|
|
866
|
+
"meetingStartTime",
|
|
867
|
+
"meetingEndTime",
|
|
868
|
+
"currentAgendaItemId",
|
|
869
|
+
"memberId",
|
|
870
|
+
"memberIds",
|
|
871
|
+
"teamIds",
|
|
872
|
+
"organizationId",
|
|
873
|
+
"agendaId",
|
|
874
|
+
"parentMeetingId",
|
|
875
|
+
"childMeetingIds",
|
|
876
|
+
"agendaName",
|
|
877
|
+
"occurrenceDate"
|
|
878
|
+
],
|
|
879
|
+
list: [
|
|
880
|
+
"name",
|
|
881
|
+
"slug",
|
|
882
|
+
"description",
|
|
883
|
+
"status",
|
|
884
|
+
"priority",
|
|
885
|
+
"createdAt",
|
|
886
|
+
"updatedAt",
|
|
887
|
+
"startDate",
|
|
888
|
+
"targetDate",
|
|
889
|
+
"archivedAt",
|
|
890
|
+
"memberId",
|
|
891
|
+
"organizationId",
|
|
892
|
+
"teamIds"
|
|
893
|
+
],
|
|
894
|
+
list_item: [
|
|
895
|
+
"summary",
|
|
896
|
+
"slug",
|
|
897
|
+
"description",
|
|
898
|
+
"notes",
|
|
899
|
+
"status",
|
|
900
|
+
"priority",
|
|
901
|
+
"rank",
|
|
902
|
+
"dueDate",
|
|
903
|
+
"createdAt",
|
|
904
|
+
"updatedAt",
|
|
905
|
+
"archivedAt",
|
|
906
|
+
"organizationId",
|
|
907
|
+
"memberId",
|
|
908
|
+
"creatorId",
|
|
909
|
+
"listId",
|
|
910
|
+
"listSlug",
|
|
911
|
+
"labelIds",
|
|
912
|
+
"estimateIds",
|
|
913
|
+
"subitemsCount",
|
|
914
|
+
"completedSubitemsCount"
|
|
915
|
+
],
|
|
916
|
+
issue_group: [
|
|
917
|
+
"name",
|
|
918
|
+
"slug",
|
|
919
|
+
"description",
|
|
920
|
+
"status",
|
|
921
|
+
"priority",
|
|
922
|
+
"startDate",
|
|
923
|
+
"targetDate",
|
|
924
|
+
"createdAt",
|
|
925
|
+
"updatedAt",
|
|
926
|
+
"memberId",
|
|
927
|
+
"organizationId",
|
|
928
|
+
"teamIds"
|
|
929
|
+
],
|
|
930
|
+
todo_group: [
|
|
931
|
+
"name",
|
|
932
|
+
"slug",
|
|
933
|
+
"description",
|
|
934
|
+
"status",
|
|
935
|
+
"priority",
|
|
936
|
+
"startDate",
|
|
937
|
+
"targetDate",
|
|
938
|
+
"createdAt",
|
|
939
|
+
"updatedAt",
|
|
940
|
+
"memberId",
|
|
941
|
+
"organizationId",
|
|
942
|
+
"teamIds"
|
|
943
|
+
],
|
|
944
|
+
todo: [
|
|
945
|
+
"name",
|
|
946
|
+
"slug",
|
|
947
|
+
"description",
|
|
948
|
+
"status",
|
|
949
|
+
"priority",
|
|
950
|
+
"rank",
|
|
951
|
+
"dueBy",
|
|
952
|
+
"createdAt",
|
|
953
|
+
"updatedAt",
|
|
954
|
+
"archivedAt",
|
|
955
|
+
"organizationId",
|
|
956
|
+
"meetingId",
|
|
957
|
+
"memberId",
|
|
958
|
+
"creatorId",
|
|
959
|
+
"todoGroupId",
|
|
960
|
+
"todoGroupSlug",
|
|
961
|
+
"labelIds",
|
|
962
|
+
"subTodosCount",
|
|
963
|
+
"completedSubTodosCount"
|
|
964
|
+
],
|
|
965
|
+
rock_collection: [
|
|
966
|
+
"name",
|
|
967
|
+
"slug",
|
|
968
|
+
"description",
|
|
969
|
+
"status",
|
|
970
|
+
"priority",
|
|
971
|
+
"rockType",
|
|
972
|
+
"createdAt",
|
|
973
|
+
"updatedAt",
|
|
974
|
+
"startDate",
|
|
975
|
+
"targetDate",
|
|
976
|
+
"archivedAt",
|
|
977
|
+
"memberId",
|
|
978
|
+
"organizationId",
|
|
979
|
+
"teamIds"
|
|
980
|
+
],
|
|
981
|
+
content: [
|
|
982
|
+
"name",
|
|
983
|
+
"slug",
|
|
984
|
+
"firstChildSlug",
|
|
985
|
+
"rootParentSlug",
|
|
986
|
+
"status",
|
|
987
|
+
"contentType",
|
|
988
|
+
"lastEdited",
|
|
989
|
+
"organizationId",
|
|
990
|
+
"memberId",
|
|
991
|
+
"focusMemberId",
|
|
992
|
+
"focusTeamId",
|
|
993
|
+
"teamId",
|
|
994
|
+
"creatorId",
|
|
995
|
+
"createdAt",
|
|
996
|
+
"updatedAt",
|
|
997
|
+
"childCount",
|
|
998
|
+
"assignmentType",
|
|
999
|
+
"contentableId",
|
|
1000
|
+
"contentableSlug",
|
|
1001
|
+
"contentableType",
|
|
1002
|
+
"votesTotal",
|
|
1003
|
+
"labelIds",
|
|
1004
|
+
"rootContentId",
|
|
1005
|
+
"parentContentId"
|
|
1006
|
+
],
|
|
1007
|
+
stand_up: [
|
|
1008
|
+
"completedDate",
|
|
1009
|
+
"blockers",
|
|
1010
|
+
"plannedWork",
|
|
1011
|
+
"slug",
|
|
1012
|
+
"memberId",
|
|
1013
|
+
"organizationId"
|
|
1014
|
+
],
|
|
1015
|
+
headline: [
|
|
1016
|
+
"slug",
|
|
1017
|
+
"summary",
|
|
1018
|
+
"description",
|
|
1019
|
+
"memberId",
|
|
1020
|
+
"status",
|
|
1021
|
+
"rank",
|
|
1022
|
+
"createdAt",
|
|
1023
|
+
"updatedAt",
|
|
1024
|
+
"headlineType",
|
|
1025
|
+
"teamIds",
|
|
1026
|
+
"meetingId",
|
|
1027
|
+
"labelIds"
|
|
1028
|
+
],
|
|
1029
|
+
question: [
|
|
1030
|
+
"name",
|
|
1031
|
+
"description",
|
|
1032
|
+
"status",
|
|
1033
|
+
"votesTotal",
|
|
1034
|
+
"slug",
|
|
1035
|
+
"createdAt",
|
|
1036
|
+
"updatedAt",
|
|
1037
|
+
"memberId",
|
|
1038
|
+
"creatorId",
|
|
1039
|
+
"organizationId",
|
|
1040
|
+
"acceptedAnswerIds",
|
|
1041
|
+
"labelIds"
|
|
1042
|
+
],
|
|
1043
|
+
feedback: [
|
|
1044
|
+
"name",
|
|
1045
|
+
"slug",
|
|
1046
|
+
"year",
|
|
1047
|
+
"quarter",
|
|
1048
|
+
"organizationId",
|
|
1049
|
+
"memberIds"
|
|
1050
|
+
],
|
|
1051
|
+
survey: [
|
|
1052
|
+
"name",
|
|
1053
|
+
"slug",
|
|
1054
|
+
"createdAt",
|
|
1055
|
+
"dueDate",
|
|
1056
|
+
"updatedAt",
|
|
1057
|
+
"recipientType",
|
|
1058
|
+
"organizationId",
|
|
1059
|
+
"memberIds"
|
|
1060
|
+
],
|
|
1061
|
+
responsibility: ["name", "description", "rank", "slug", "memberId", "organizationId"],
|
|
1062
|
+
smart_kpi_view: [
|
|
1063
|
+
"name",
|
|
1064
|
+
"slug",
|
|
1065
|
+
"description",
|
|
1066
|
+
"status",
|
|
1067
|
+
"priority",
|
|
1068
|
+
"createdAt",
|
|
1069
|
+
"updatedAt",
|
|
1070
|
+
"archivedAt",
|
|
1071
|
+
"memberId",
|
|
1072
|
+
"organizationId",
|
|
1073
|
+
"teamIds"
|
|
1074
|
+
],
|
|
1075
|
+
smart_kpi: [
|
|
1076
|
+
"name",
|
|
1077
|
+
"slug",
|
|
1078
|
+
"notes",
|
|
1079
|
+
"interval",
|
|
1080
|
+
"trend",
|
|
1081
|
+
"smartKpiType",
|
|
1082
|
+
"condition",
|
|
1083
|
+
"status",
|
|
1084
|
+
"progressStatus",
|
|
1085
|
+
"autoIncrease",
|
|
1086
|
+
"createdAt",
|
|
1087
|
+
"updatedAt",
|
|
1088
|
+
"archivedAt",
|
|
1089
|
+
"organizationId",
|
|
1090
|
+
"smartKpiViewId",
|
|
1091
|
+
"smartKpiViewSlug",
|
|
1092
|
+
"memberId",
|
|
1093
|
+
"integrationId",
|
|
1094
|
+
"quarterlyObjectiveId"
|
|
1095
|
+
],
|
|
1096
|
+
measurable_group: [
|
|
1097
|
+
"name",
|
|
1098
|
+
"slug",
|
|
1099
|
+
"description",
|
|
1100
|
+
"status",
|
|
1101
|
+
"priority",
|
|
1102
|
+
"createdAt",
|
|
1103
|
+
"updatedAt",
|
|
1104
|
+
"memberId",
|
|
1105
|
+
"organizationId",
|
|
1106
|
+
"teamIds"
|
|
1107
|
+
],
|
|
1108
|
+
measurable: [
|
|
1109
|
+
"name",
|
|
1110
|
+
"slug",
|
|
1111
|
+
"description",
|
|
1112
|
+
"notes",
|
|
1113
|
+
"interval",
|
|
1114
|
+
"trend",
|
|
1115
|
+
"measurableType",
|
|
1116
|
+
"condition",
|
|
1117
|
+
"status",
|
|
1118
|
+
"rank",
|
|
1119
|
+
"createdAt",
|
|
1120
|
+
"updatedAt",
|
|
1121
|
+
"archivedAt",
|
|
1122
|
+
"organizationId",
|
|
1123
|
+
"measurableGroupId",
|
|
1124
|
+
"measurableGroupSlug",
|
|
1125
|
+
"memberId",
|
|
1126
|
+
"creatorId",
|
|
1127
|
+
"quarterlyObjectiveId",
|
|
1128
|
+
"labelIds"
|
|
1129
|
+
],
|
|
1130
|
+
customer: [
|
|
1131
|
+
"name",
|
|
1132
|
+
"slug",
|
|
1133
|
+
"createdAt",
|
|
1134
|
+
"updatedAt",
|
|
1135
|
+
"memberId",
|
|
1136
|
+
"organizationId",
|
|
1137
|
+
"status",
|
|
1138
|
+
"rank",
|
|
1139
|
+
"revenue",
|
|
1140
|
+
"companySize",
|
|
1141
|
+
"domain",
|
|
1142
|
+
"primaryEmail",
|
|
1143
|
+
"primaryPhone",
|
|
1144
|
+
"primaryLocation"
|
|
1145
|
+
],
|
|
1146
|
+
contact: [
|
|
1147
|
+
"name",
|
|
1148
|
+
"slug",
|
|
1149
|
+
"createdAt",
|
|
1150
|
+
"updatedAt",
|
|
1151
|
+
"memberId",
|
|
1152
|
+
"organizationId",
|
|
1153
|
+
"customerId",
|
|
1154
|
+
"status",
|
|
1155
|
+
"rank",
|
|
1156
|
+
"jobTitle",
|
|
1157
|
+
"email",
|
|
1158
|
+
"phone",
|
|
1159
|
+
"location"
|
|
1160
|
+
],
|
|
1161
|
+
annual_objective: [
|
|
1162
|
+
"name",
|
|
1163
|
+
"description",
|
|
1164
|
+
"status",
|
|
1165
|
+
"createdAt",
|
|
1166
|
+
"updatedAt",
|
|
1167
|
+
"organizationId",
|
|
1168
|
+
"strategicObjectiveId",
|
|
1169
|
+
"ownerId",
|
|
1170
|
+
"creatorId"
|
|
1171
|
+
],
|
|
1172
|
+
quarterly_objective: [
|
|
1173
|
+
"name",
|
|
1174
|
+
"description",
|
|
1175
|
+
"status",
|
|
1176
|
+
"alignmentScore",
|
|
1177
|
+
"alignmentLabel",
|
|
1178
|
+
"rocksCount",
|
|
1179
|
+
"measurablesCount",
|
|
1180
|
+
"smartKpisCount",
|
|
1181
|
+
"createdAt",
|
|
1182
|
+
"updatedAt",
|
|
1183
|
+
"organizationId",
|
|
1184
|
+
"strategicObjectiveId",
|
|
1185
|
+
"annualObjectiveId",
|
|
1186
|
+
"departmentId",
|
|
1187
|
+
"ownerId",
|
|
1188
|
+
"creatorId"
|
|
1189
|
+
],
|
|
1190
|
+
organization_meta_profile: ["summary", "profile"],
|
|
1191
|
+
key_metric_meta_profile: ["summary", "profile"],
|
|
1192
|
+
strategic_plan: [],
|
|
1193
|
+
strategic_objective: []
|
|
1194
|
+
};
|
|
1195
|
+
var RESOURCE_FIELD_ALIASES = {
|
|
1196
|
+
tasks: "task",
|
|
1197
|
+
issues: "issue",
|
|
1198
|
+
teams: "team",
|
|
1199
|
+
members: "member",
|
|
1200
|
+
rocks: "rock",
|
|
1201
|
+
meetings: "meeting",
|
|
1202
|
+
lists: "list",
|
|
1203
|
+
list_items: "list_item",
|
|
1204
|
+
issue_groups: "issue_group",
|
|
1205
|
+
todo_groups: "todo_group",
|
|
1206
|
+
todos: "todo",
|
|
1207
|
+
rock_collections: "rock_collection",
|
|
1208
|
+
contents: "content",
|
|
1209
|
+
stand_ups: "stand_up",
|
|
1210
|
+
headlines: "headline",
|
|
1211
|
+
questions: "question",
|
|
1212
|
+
feedbacks: "feedback",
|
|
1213
|
+
surveys: "survey",
|
|
1214
|
+
responsibilities: "responsibility",
|
|
1215
|
+
smart_kpi_views: "smart_kpi_view",
|
|
1216
|
+
smart_kpis: "smart_kpi",
|
|
1217
|
+
measurable_groups: "measurable_group",
|
|
1218
|
+
measurables: "measurable",
|
|
1219
|
+
customers: "customer",
|
|
1220
|
+
contacts: "contact",
|
|
1221
|
+
annual_objectives: "annual_objective",
|
|
1222
|
+
quarterly_objectives: "quarterly_objective"
|
|
1223
|
+
};
|
|
416
1224
|
function buildCliErrorEnvelope(params) {
|
|
417
1225
|
return {
|
|
418
1226
|
ok: false,
|
|
@@ -433,11 +1241,47 @@ function defaultQuerySelectionSet(field, isList) {
|
|
|
433
1241
|
if (field === "organization") {
|
|
434
1242
|
return "{ id slug membersCount organizationDetail { title name description timezone workspaceName } }";
|
|
435
1243
|
}
|
|
1244
|
+
const canonicalField = RESOURCE_FIELD_ALIASES[field] ?? field;
|
|
1245
|
+
const explicitFields = RESOURCE_QUERY_FIELDS[canonicalField];
|
|
1246
|
+
if (explicitFields) {
|
|
1247
|
+
const fields = Array.from(/* @__PURE__ */ new Set(["id", "type", ...explicitFields, "attributes"])).join(" ");
|
|
1248
|
+
return isList ? `{ data { ${fields} } count currentPage totalPages }` : `{ ${fields} }`;
|
|
1249
|
+
}
|
|
436
1250
|
if (isList) {
|
|
437
1251
|
return "{ data { id type attributes } count currentPage totalPages }";
|
|
438
1252
|
}
|
|
439
1253
|
return "{ id type attributes }";
|
|
440
1254
|
}
|
|
1255
|
+
function isRecord(value) {
|
|
1256
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1257
|
+
}
|
|
1258
|
+
function normalizeDisplayFieldsInRow(row) {
|
|
1259
|
+
if (!isRecord(row)) return row;
|
|
1260
|
+
const attributes = isRecord(row.attributes) ? row.attributes : null;
|
|
1261
|
+
if (!attributes) return row;
|
|
1262
|
+
const normalized = { ...row };
|
|
1263
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1264
|
+
if (!Object.prototype.hasOwnProperty.call(normalized, key)) {
|
|
1265
|
+
normalized[key] = value;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
return normalized;
|
|
1269
|
+
}
|
|
1270
|
+
function normalizeQueryFieldPayloadForDisplay(fieldPayload) {
|
|
1271
|
+
if (Array.isArray(fieldPayload)) {
|
|
1272
|
+
return fieldPayload.map((row) => normalizeDisplayFieldsInRow(row));
|
|
1273
|
+
}
|
|
1274
|
+
if (!isRecord(fieldPayload)) {
|
|
1275
|
+
return fieldPayload;
|
|
1276
|
+
}
|
|
1277
|
+
if (Array.isArray(fieldPayload.data)) {
|
|
1278
|
+
return {
|
|
1279
|
+
...fieldPayload,
|
|
1280
|
+
data: fieldPayload.data.map((row) => normalizeDisplayFieldsInRow(row))
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
return normalizeDisplayFieldsInRow(fieldPayload);
|
|
1284
|
+
}
|
|
441
1285
|
function parseBooleanMaybe(value) {
|
|
442
1286
|
const lowered = value.toLowerCase();
|
|
443
1287
|
if (lowered === "true") {
|
|
@@ -494,9 +1338,15 @@ async function runGraphqlQueryCommand(input) {
|
|
|
494
1338
|
operationType: "query",
|
|
495
1339
|
field: input.field,
|
|
496
1340
|
variables: input.variables ?? {},
|
|
1341
|
+
variableTypes: input.variableTypes,
|
|
497
1342
|
selectionSet: input.selectionSet ?? defaultQuerySelectionSet(input.field, Boolean(input.isList)),
|
|
498
1343
|
isShow: input.isShow
|
|
499
1344
|
});
|
|
1345
|
+
const envelopeData = result.envelope.data;
|
|
1346
|
+
if (result.envelope.ok && envelopeData && Object.prototype.hasOwnProperty.call(envelopeData, input.field)) {
|
|
1347
|
+
envelopeData[input.field] = normalizeQueryFieldPayloadForDisplay(envelopeData[input.field]);
|
|
1348
|
+
result.envelope.data = envelopeData;
|
|
1349
|
+
}
|
|
500
1350
|
if (result.envelope.ok && input.transformData && result.envelope.data) {
|
|
501
1351
|
const dataRecord = result.envelope.data;
|
|
502
1352
|
const transformed = input.transformData(dataRecord[input.field]);
|
|
@@ -504,6 +1354,17 @@ async function runGraphqlQueryCommand(input) {
|
|
|
504
1354
|
...dataRecord,
|
|
505
1355
|
[input.field]: transformed
|
|
506
1356
|
};
|
|
1357
|
+
if (input.isShow && (transformed === null || transformed === void 0)) {
|
|
1358
|
+
result.envelope.ok = false;
|
|
1359
|
+
result.envelope.status = 404;
|
|
1360
|
+
result.envelope.data = null;
|
|
1361
|
+
result.envelope.error = {
|
|
1362
|
+
code: "not_found",
|
|
1363
|
+
message: "Record not found.",
|
|
1364
|
+
details: {}
|
|
1365
|
+
};
|
|
1366
|
+
result.exitCode = EXIT_CODES.notFound;
|
|
1367
|
+
}
|
|
507
1368
|
}
|
|
508
1369
|
printEnvelopeAndExit(result);
|
|
509
1370
|
} catch (error) {
|
|
@@ -541,6 +1402,7 @@ async function runGraphqlMutationCommand(input) {
|
|
|
541
1402
|
operationType: "mutation",
|
|
542
1403
|
field: input.field,
|
|
543
1404
|
variables: input.variables ?? {},
|
|
1405
|
+
variableTypes: input.variableTypes,
|
|
544
1406
|
selectionSet: input.selectionSet ?? "{ ok status errorCode data errors }"
|
|
545
1407
|
});
|
|
546
1408
|
printEnvelopeAndExit(result);
|
|
@@ -780,8 +1642,114 @@ function resolveOrganizationId(raw) {
|
|
|
780
1642
|
return organizationId;
|
|
781
1643
|
}
|
|
782
1644
|
|
|
1645
|
+
// src/commands/tasks.ts
|
|
1646
|
+
var projectIdSchema = import_zod2.z.string().min(1);
|
|
1647
|
+
var idSchema = import_zod2.z.string().min(1);
|
|
1648
|
+
var summarySchema = import_zod2.z.string().min(1);
|
|
1649
|
+
function registerTaskCommands(program) {
|
|
1650
|
+
const tasks = program.command("tasks").description("Task operations");
|
|
1651
|
+
tasks.command("list").option("--project-id <projectId>").option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--team-ids <teamIds>").option("--member-id <memberId>").option("--meeting-id <meetingId>").option("--field-name <fieldName>").option("--field-value <fieldValue>").option("--field-blank <fieldBlank>").option("--open <open>").option("--rank-direction <rankDirection>").option("--include-archived <includeArchived>").action(async (opts, cmd) => {
|
|
1652
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1653
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1654
|
+
const projectId = opts.projectId ? projectIdSchema.parse(opts.projectId) : void 0;
|
|
1655
|
+
await runGraphqlQueryCommand({
|
|
1656
|
+
command: "tasks.list",
|
|
1657
|
+
runtimeOptions: context.runtimeOptions,
|
|
1658
|
+
field: "tasks",
|
|
1659
|
+
variables: normalizeGraphqlVariables2({
|
|
1660
|
+
organization_id: organizationId,
|
|
1661
|
+
page: opts.page,
|
|
1662
|
+
per: opts.per,
|
|
1663
|
+
project_id: projectId,
|
|
1664
|
+
team_id: opts.teamId,
|
|
1665
|
+
team_ids: opts.teamIds,
|
|
1666
|
+
member_id: opts.memberId,
|
|
1667
|
+
meeting_id: opts.meetingId,
|
|
1668
|
+
field_name: opts.fieldName,
|
|
1669
|
+
field_value: opts.fieldValue,
|
|
1670
|
+
field_blank: opts.fieldBlank,
|
|
1671
|
+
open: opts.open,
|
|
1672
|
+
rank_direction: opts.rankDirection,
|
|
1673
|
+
include_archived: opts.includeArchived
|
|
1674
|
+
}),
|
|
1675
|
+
isList: true
|
|
1676
|
+
});
|
|
1677
|
+
});
|
|
1678
|
+
tasks.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
|
|
1679
|
+
const parsed = idSchema.parse(opts.id);
|
|
1680
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1681
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1682
|
+
await runGraphqlQueryCommand({
|
|
1683
|
+
command: "tasks.show",
|
|
1684
|
+
runtimeOptions: context.runtimeOptions,
|
|
1685
|
+
field: "task",
|
|
1686
|
+
variables: {
|
|
1687
|
+
organization_id: organizationId,
|
|
1688
|
+
id: parsed
|
|
1689
|
+
},
|
|
1690
|
+
isShow: true
|
|
1691
|
+
});
|
|
1692
|
+
});
|
|
1693
|
+
tasks.command("create").requiredOption("--project-id <projectId>").option("--title <title>", "Legacy alias for --summary").option("--summary <summary>").action(async (opts, cmd) => {
|
|
1694
|
+
const projectId = projectIdSchema.parse(opts.projectId);
|
|
1695
|
+
const summary = summarySchema.parse(opts.summary ?? opts.title);
|
|
1696
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1697
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1698
|
+
await runGraphqlMutationCommand({
|
|
1699
|
+
command: "tasks.create",
|
|
1700
|
+
runtimeOptions: context.runtimeOptions,
|
|
1701
|
+
field: "create_task",
|
|
1702
|
+
variables: {
|
|
1703
|
+
organization_id: organizationId,
|
|
1704
|
+
params: {
|
|
1705
|
+
task: {
|
|
1706
|
+
project_id: projectId,
|
|
1707
|
+
summary
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
});
|
|
1712
|
+
});
|
|
1713
|
+
tasks.command("update").requiredOption("--id <id>").option("--summary <summary>").option("--description <description>").option("--status <status>").option("--priority <priority>").option("--due-date <dueDate>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
1714
|
+
const id = idSchema.parse(opts.id);
|
|
1715
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1716
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1717
|
+
const taskPayload = {
|
|
1718
|
+
...opts.summary ? { summary: String(opts.summary) } : {},
|
|
1719
|
+
...opts.description ? { description: String(opts.description) } : {},
|
|
1720
|
+
...opts.status ? { status: String(opts.status) } : {},
|
|
1721
|
+
...opts.priority ? { priority: String(opts.priority) } : {},
|
|
1722
|
+
...opts.dueDate ? { due_date: String(opts.dueDate) } : {},
|
|
1723
|
+
...opts.memberId ? { member_id: String(opts.memberId) } : {}
|
|
1724
|
+
};
|
|
1725
|
+
if (Object.keys(taskPayload).length === 0) {
|
|
1726
|
+
throw new CliError({
|
|
1727
|
+
message: "tasks update requires at least one patch field (summary, description, status, priority, due-date, member-id).",
|
|
1728
|
+
kind: "invalid_args",
|
|
1729
|
+
status: 400,
|
|
1730
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
await runGraphqlMutationCommand({
|
|
1734
|
+
command: "tasks.update",
|
|
1735
|
+
runtimeOptions: context.runtimeOptions,
|
|
1736
|
+
field: "update_task",
|
|
1737
|
+
variables: {
|
|
1738
|
+
organization_id: organizationId,
|
|
1739
|
+
task_id: id,
|
|
1740
|
+
params: {
|
|
1741
|
+
task: taskPayload
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
// src/commands/projects.ts
|
|
1749
|
+
var import_zod4 = require("zod");
|
|
1750
|
+
|
|
783
1751
|
// src/commands/entityCrud.ts
|
|
784
|
-
var
|
|
1752
|
+
var import_zod3 = require("zod");
|
|
785
1753
|
|
|
786
1754
|
// src/commands/dtoHelpCatalog.ts
|
|
787
1755
|
var dtoHelpCatalog = {
|
|
@@ -850,7 +1818,7 @@ var dtoHelpCatalog = {
|
|
|
850
1818
|
create: [
|
|
851
1819
|
["member_id", "string"],
|
|
852
1820
|
["name", "string"],
|
|
853
|
-
["type", "
|
|
1821
|
+
["type", "enum(TeamMeeting|OneOnOneMeeting)"],
|
|
854
1822
|
["date", "string"],
|
|
855
1823
|
["status", "enum(upcoming|active|completed)"],
|
|
856
1824
|
["start_time", "number"],
|
|
@@ -1362,7 +2330,7 @@ function buildDataJsonHelp(rootKey, mode) {
|
|
|
1362
2330
|
}
|
|
1363
2331
|
|
|
1364
2332
|
// src/commands/entityCrud.ts
|
|
1365
|
-
var
|
|
2333
|
+
var idSchema2 = import_zod3.z.string().min(1);
|
|
1366
2334
|
function toSingularResourceName(resourcePath) {
|
|
1367
2335
|
if (resourcePath === "organization_meta_profiles") {
|
|
1368
2336
|
return "organization_meta_profile";
|
|
@@ -1442,14 +2410,19 @@ function registerEntityCrudCommands(program, config) {
|
|
|
1442
2410
|
const updateHelp5 = buildDataJsonHelp(config.rootKey, "update") ?? "JSON object, optionally wrapped with root key";
|
|
1443
2411
|
const list = entityCommand.command("list").option("--page <page>").option("--per <per>");
|
|
1444
2412
|
const listParams = config.listParams ?? [];
|
|
2413
|
+
const showParams = config.showParams ?? [];
|
|
2414
|
+
const allowQueryJson = config.allowQueryJson !== false;
|
|
1445
2415
|
listParams.forEach((param) => {
|
|
1446
2416
|
const cliParam = param.replace(/_/g, "-");
|
|
1447
2417
|
list.option(`--${cliParam} <${cliParam}>`);
|
|
1448
2418
|
});
|
|
1449
|
-
|
|
2419
|
+
if (allowQueryJson) {
|
|
2420
|
+
list.option("--query-json <queryJson>", "Additional query params as JSON object");
|
|
2421
|
+
}
|
|
2422
|
+
list.action(async (opts, cmd) => {
|
|
1450
2423
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1451
2424
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1452
|
-
const extraQuery = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
2425
|
+
const extraQuery = allowQueryJson ? parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0) : {};
|
|
1453
2426
|
const mappedKnownParams = Object.fromEntries(
|
|
1454
2427
|
listParams.map((param) => {
|
|
1455
2428
|
const optionKey = param.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
|
@@ -1466,46 +2439,93 @@ function registerEntityCrudCommands(program, config) {
|
|
|
1466
2439
|
await runGraphqlQueryCommand({
|
|
1467
2440
|
command: `${config.command}.list`,
|
|
1468
2441
|
runtimeOptions: context.runtimeOptions,
|
|
1469
|
-
field: config.resourcePath === "feedback" ? "feedbacks" : config.resourcePath,
|
|
2442
|
+
field: config.listField ?? (config.resourcePath === "feedback" ? "feedbacks" : config.resourcePath),
|
|
1470
2443
|
variables,
|
|
2444
|
+
variableTypes: config.listVariableTypes,
|
|
2445
|
+
selectionSet: config.listSelectionSet,
|
|
1471
2446
|
isList: true
|
|
1472
2447
|
});
|
|
1473
2448
|
});
|
|
1474
|
-
entityCommand.command("show").requiredOption("--id <id>")
|
|
1475
|
-
|
|
2449
|
+
const show = entityCommand.command("show").requiredOption("--id <id>");
|
|
2450
|
+
showParams.forEach((param) => {
|
|
2451
|
+
const cliParam = param.replace(/_/g, "-");
|
|
2452
|
+
show.option(`--${cliParam} <${cliParam}>`);
|
|
2453
|
+
});
|
|
2454
|
+
show.action(async (opts, cmd) => {
|
|
2455
|
+
const id = idSchema2.parse(opts.id);
|
|
1476
2456
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1477
2457
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2458
|
+
const defaultCommand = `${config.command}.show`;
|
|
2459
|
+
const defaultField = config.showField ?? (config.resourcePath === "feedback" ? "feedback" : toSingularResourceName(config.resourcePath));
|
|
2460
|
+
const mappedShowParams = Object.fromEntries(
|
|
2461
|
+
showParams.map((param) => {
|
|
2462
|
+
const optionKey = param.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
|
2463
|
+
return [param, opts[optionKey]];
|
|
2464
|
+
})
|
|
2465
|
+
);
|
|
2466
|
+
const defaultVariables = normalizeGraphqlVariables2({
|
|
2467
|
+
organization_id: organizationId,
|
|
2468
|
+
id,
|
|
2469
|
+
...mappedShowParams
|
|
2470
|
+
});
|
|
2471
|
+
const showQuery = config.showQueryFactory ? config.showQueryFactory({
|
|
2472
|
+
command: defaultCommand,
|
|
2473
|
+
field: defaultField,
|
|
2474
|
+
variables: defaultVariables,
|
|
2475
|
+
id,
|
|
2476
|
+
organizationId
|
|
2477
|
+
}) : void 0;
|
|
1478
2478
|
await runGraphqlQueryCommand({
|
|
1479
|
-
command:
|
|
2479
|
+
command: showQuery?.command ?? defaultCommand,
|
|
1480
2480
|
runtimeOptions: context.runtimeOptions,
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
isShow: true
|
|
2481
|
+
operationName: showQuery?.operationName,
|
|
2482
|
+
field: showQuery?.field ?? defaultField,
|
|
2483
|
+
variables: showQuery?.variables ?? defaultVariables,
|
|
2484
|
+
variableTypes: showQuery?.variableTypes ?? config.showVariableTypes,
|
|
2485
|
+
selectionSet: showQuery?.selectionSet ?? config.showSelectionSet,
|
|
2486
|
+
isShow: true,
|
|
2487
|
+
transformData: showQuery?.transformData
|
|
1487
2488
|
});
|
|
1488
2489
|
});
|
|
1489
2490
|
entityCommand.command("create").requiredOption("--data-json <dataJson>", createHelp4).action(async (opts, cmd) => {
|
|
1490
2491
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1491
2492
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1492
|
-
|
|
2493
|
+
let body = normalizeBody(String(opts.dataJson), config.rootKey);
|
|
2494
|
+
if (config.normalizeCreateBody) {
|
|
2495
|
+
body = config.normalizeCreateBody(body);
|
|
2496
|
+
}
|
|
1493
2497
|
assertRequiredCreateFields(body, config.rootKey, config.requiredCreateFields);
|
|
2498
|
+
const defaultCommand = `${config.command}.create`;
|
|
2499
|
+
const defaultField = `create_${toSingularResourceName(config.resourcePath)}`;
|
|
2500
|
+
const defaultVariables = {
|
|
2501
|
+
organization_id: organizationId,
|
|
2502
|
+
params: body
|
|
2503
|
+
};
|
|
2504
|
+
const createMutation = config.createMutationFactory ? config.createMutationFactory({
|
|
2505
|
+
command: defaultCommand,
|
|
2506
|
+
field: defaultField,
|
|
2507
|
+
variables: defaultVariables,
|
|
2508
|
+
body,
|
|
2509
|
+
organizationId
|
|
2510
|
+
}) : void 0;
|
|
1494
2511
|
await runGraphqlMutationCommand({
|
|
1495
|
-
command:
|
|
2512
|
+
command: createMutation?.command ?? defaultCommand,
|
|
1496
2513
|
runtimeOptions: context.runtimeOptions,
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
2514
|
+
operationName: createMutation?.operationName,
|
|
2515
|
+
field: createMutation?.field ?? defaultField,
|
|
2516
|
+
variables: createMutation?.variables ?? defaultVariables,
|
|
2517
|
+
variableTypes: createMutation?.variableTypes,
|
|
2518
|
+
selectionSet: createMutation?.selectionSet
|
|
1502
2519
|
});
|
|
1503
2520
|
});
|
|
1504
2521
|
entityCommand.command("update").requiredOption("--id <id>").requiredOption("--data-json <dataJson>", updateHelp5).action(async (opts, cmd) => {
|
|
1505
|
-
const id =
|
|
2522
|
+
const id = idSchema2.parse(opts.id);
|
|
1506
2523
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1507
2524
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1508
|
-
|
|
2525
|
+
let body = normalizeBody(String(opts.dataJson), config.rootKey);
|
|
2526
|
+
if (config.normalizeUpdateBody) {
|
|
2527
|
+
body = config.normalizeUpdateBody(body);
|
|
2528
|
+
}
|
|
1509
2529
|
const singular = toSingularResourceName(config.resourcePath);
|
|
1510
2530
|
await runGraphqlMutationCommand({
|
|
1511
2531
|
command: `${config.command}.update`,
|
|
@@ -1527,137 +2547,69 @@ var __testables = {
|
|
|
1527
2547
|
parseQueryJson
|
|
1528
2548
|
};
|
|
1529
2549
|
|
|
1530
|
-
// src/commands/tasks.ts
|
|
1531
|
-
var projectIdSchema = import_zod3.z.string().min(1);
|
|
1532
|
-
var idSchema2 = import_zod3.z.string().min(1);
|
|
1533
|
-
var summarySchema = import_zod3.z.string().min(1);
|
|
1534
|
-
function registerTaskCommands(program) {
|
|
1535
|
-
const tasks = program.command("tasks").description("Task operations");
|
|
1536
|
-
tasks.command("list").option("--project-id <projectId>").option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--team-ids <teamIds>").option("--member-id <memberId>").option("--meeting-id <meetingId>").option("--field-name <fieldName>").option("--field-value <fieldValue>").option("--field-blank <fieldBlank>").option("--rank-direction <rankDirection>").option("--include-archived <includeArchived>").option("--query-json <queryJson>").action(async (opts, cmd) => {
|
|
1537
|
-
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1538
|
-
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1539
|
-
const projectId = opts.projectId ? projectIdSchema.parse(opts.projectId) : void 0;
|
|
1540
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1541
|
-
await runGraphqlQueryCommand({
|
|
1542
|
-
command: "tasks.list",
|
|
1543
|
-
runtimeOptions: context.runtimeOptions,
|
|
1544
|
-
field: "tasks",
|
|
1545
|
-
variables: normalizeGraphqlVariables2({
|
|
1546
|
-
organization_id: organizationId,
|
|
1547
|
-
page: opts.page,
|
|
1548
|
-
per: opts.per,
|
|
1549
|
-
project_id: projectId,
|
|
1550
|
-
team_id: opts.teamId,
|
|
1551
|
-
team_ids: opts.teamIds,
|
|
1552
|
-
member_id: opts.memberId,
|
|
1553
|
-
meeting_id: opts.meetingId,
|
|
1554
|
-
field_name: opts.fieldName,
|
|
1555
|
-
field_value: opts.fieldValue,
|
|
1556
|
-
field_blank: opts.fieldBlank,
|
|
1557
|
-
rank_direction: opts.rankDirection,
|
|
1558
|
-
include_archived: opts.includeArchived,
|
|
1559
|
-
...extra
|
|
1560
|
-
}),
|
|
1561
|
-
isList: true
|
|
1562
|
-
});
|
|
1563
|
-
});
|
|
1564
|
-
tasks.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
|
|
1565
|
-
const parsed = idSchema2.parse(opts.id);
|
|
1566
|
-
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1567
|
-
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1568
|
-
await runGraphqlQueryCommand({
|
|
1569
|
-
command: "tasks.show",
|
|
1570
|
-
runtimeOptions: context.runtimeOptions,
|
|
1571
|
-
field: "task",
|
|
1572
|
-
variables: {
|
|
1573
|
-
organization_id: organizationId,
|
|
1574
|
-
id: parsed
|
|
1575
|
-
},
|
|
1576
|
-
isShow: true
|
|
1577
|
-
});
|
|
1578
|
-
});
|
|
1579
|
-
tasks.command("create").requiredOption("--project-id <projectId>").option("--title <title>", "Legacy alias for --summary").option("--summary <summary>").action(async (opts, cmd) => {
|
|
1580
|
-
const projectId = projectIdSchema.parse(opts.projectId);
|
|
1581
|
-
const summary = summarySchema.parse(opts.summary ?? opts.title);
|
|
1582
|
-
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1583
|
-
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1584
|
-
await runGraphqlMutationCommand({
|
|
1585
|
-
command: "tasks.create",
|
|
1586
|
-
runtimeOptions: context.runtimeOptions,
|
|
1587
|
-
field: "create_task",
|
|
1588
|
-
variables: {
|
|
1589
|
-
organization_id: organizationId,
|
|
1590
|
-
params: {
|
|
1591
|
-
task: {
|
|
1592
|
-
project_id: projectId,
|
|
1593
|
-
summary
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
});
|
|
1598
|
-
});
|
|
1599
|
-
tasks.command("update").requiredOption("--id <id>").option("--summary <summary>").option("--description <description>").option("--status <status>").option("--priority <priority>").option("--due-date <dueDate>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
1600
|
-
const id = idSchema2.parse(opts.id);
|
|
1601
|
-
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1602
|
-
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1603
|
-
const taskPayload = {
|
|
1604
|
-
...opts.summary ? { summary: String(opts.summary) } : {},
|
|
1605
|
-
...opts.description ? { description: String(opts.description) } : {},
|
|
1606
|
-
...opts.status ? { status: String(opts.status) } : {},
|
|
1607
|
-
...opts.priority ? { priority: String(opts.priority) } : {},
|
|
1608
|
-
...opts.dueDate ? { due_date: String(opts.dueDate) } : {},
|
|
1609
|
-
...opts.memberId ? { member_id: String(opts.memberId) } : {}
|
|
1610
|
-
};
|
|
1611
|
-
if (Object.keys(taskPayload).length === 0) {
|
|
1612
|
-
throw new CliError({
|
|
1613
|
-
message: "tasks update requires at least one patch field (summary, description, status, priority, due-date, member-id).",
|
|
1614
|
-
kind: "invalid_args",
|
|
1615
|
-
status: 400,
|
|
1616
|
-
exitCode: EXIT_CODES.invalidArgs
|
|
1617
|
-
});
|
|
1618
|
-
}
|
|
1619
|
-
await runGraphqlMutationCommand({
|
|
1620
|
-
command: "tasks.update",
|
|
1621
|
-
runtimeOptions: context.runtimeOptions,
|
|
1622
|
-
field: "update_task",
|
|
1623
|
-
variables: {
|
|
1624
|
-
organization_id: organizationId,
|
|
1625
|
-
task_id: id,
|
|
1626
|
-
params: {
|
|
1627
|
-
task: taskPayload
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
});
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
2550
|
// src/commands/projects.ts
|
|
1635
|
-
var import_zod4 = require("zod");
|
|
1636
2551
|
var idSchema3 = import_zod4.z.string().min(1);
|
|
1637
2552
|
var projectCreateDataJsonHelp = buildDataJsonHelp("project", "create") ?? 'JSON object for project or {"project": {...}}';
|
|
1638
2553
|
var projectUpdateDataJsonHelp = buildDataJsonHelp("project", "update") ?? 'JSON object for project or {"project": {...}}';
|
|
2554
|
+
var projectsIndexFullSelectionSet = "{ count currentPage totalPages data { id type attributes { name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds favorites { id memberId } resources { ...ResourceSummaryFull } } name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type attributes viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type attributes filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { id type attributes value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type attributes value memberId createdAt updatedAt commentType commentableId commentableType parentCommentId emojis { id name memberId } resources { ...ResourceSummaryFull } replies { id type } } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }";
|
|
2555
|
+
function asRecord2(value) {
|
|
2556
|
+
return value && typeof value === "object" ? value : null;
|
|
2557
|
+
}
|
|
2558
|
+
function toNonEmptyString(value) {
|
|
2559
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
2560
|
+
}
|
|
2561
|
+
function normalizeProjectRowForDisplay(row) {
|
|
2562
|
+
const record = asRecord2(row);
|
|
2563
|
+
if (!record) return row;
|
|
2564
|
+
const attributes = asRecord2(record.attributes);
|
|
2565
|
+
const topLevelName = toNonEmptyString(record.name);
|
|
2566
|
+
const topLevelTitle = toNonEmptyString(record.title);
|
|
2567
|
+
const attributeName = toNonEmptyString(attributes?.name);
|
|
2568
|
+
const attributeTitle = toNonEmptyString(attributes?.title);
|
|
2569
|
+
if (!topLevelName && !topLevelTitle && !attributeName && !attributeTitle) {
|
|
2570
|
+
return record;
|
|
2571
|
+
}
|
|
2572
|
+
return {
|
|
2573
|
+
...record,
|
|
2574
|
+
...topLevelName ? {} : attributeName ? { name: attributeName } : {},
|
|
2575
|
+
...topLevelTitle ? {} : attributeTitle ? { title: attributeTitle } : {}
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
function normalizeProjectsListForDisplay(payload) {
|
|
2579
|
+
const record = asRecord2(payload);
|
|
2580
|
+
if (!record || !Array.isArray(record.data)) return payload;
|
|
2581
|
+
return {
|
|
2582
|
+
...record,
|
|
2583
|
+
data: record.data.map((row) => normalizeProjectRowForDisplay(row))
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
1639
2586
|
function registerProjectCommands(program) {
|
|
1640
2587
|
const projects = program.command("projects").description("Project operations");
|
|
1641
|
-
projects.command("list").option("--page <page>").option("--per <per>").option("--
|
|
2588
|
+
projects.command("list").option("--page <page>").option("--per <per>").option("--team-ids <teamIds>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
1642
2589
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1643
2590
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1644
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1645
2591
|
await runGraphqlQueryCommand({
|
|
1646
2592
|
command: "projects.list",
|
|
2593
|
+
operationName: "ProjectsIndexFull",
|
|
1647
2594
|
runtimeOptions: context.runtimeOptions,
|
|
1648
2595
|
field: "projects",
|
|
1649
2596
|
variables: normalizeGraphqlVariables2({
|
|
1650
2597
|
organization_id: organizationId,
|
|
1651
2598
|
page: opts.page,
|
|
1652
2599
|
per: opts.per,
|
|
1653
|
-
include_archived: opts.includeArchived,
|
|
1654
|
-
status: opts.status,
|
|
1655
|
-
term: opts.term,
|
|
1656
2600
|
team_ids: opts.teamIds,
|
|
1657
|
-
member_id: opts.memberId
|
|
1658
|
-
...extra
|
|
2601
|
+
member_id: opts.memberId
|
|
1659
2602
|
}),
|
|
1660
|
-
|
|
2603
|
+
variableTypes: {
|
|
2604
|
+
organization_id: "ID!",
|
|
2605
|
+
page: "Int",
|
|
2606
|
+
per: "Int",
|
|
2607
|
+
team_ids: "[ID!]",
|
|
2608
|
+
member_id: "ID"
|
|
2609
|
+
},
|
|
2610
|
+
isList: true,
|
|
2611
|
+
selectionSet: projectsIndexFullSelectionSet,
|
|
2612
|
+
transformData: normalizeProjectsListForDisplay
|
|
1661
2613
|
});
|
|
1662
2614
|
});
|
|
1663
2615
|
projects.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
|
|
@@ -1672,7 +2624,9 @@ function registerProjectCommands(program) {
|
|
|
1672
2624
|
organization_id: organizationId,
|
|
1673
2625
|
id
|
|
1674
2626
|
},
|
|
1675
|
-
isShow: true
|
|
2627
|
+
isShow: true,
|
|
2628
|
+
selectionSet: "{ id type name }",
|
|
2629
|
+
transformData: normalizeProjectRowForDisplay
|
|
1676
2630
|
});
|
|
1677
2631
|
});
|
|
1678
2632
|
projects.command("create").requiredOption("--data-json <dataJson>", projectCreateDataJsonHelp).action(async (opts, cmd) => {
|
|
@@ -1702,6 +2656,11 @@ function registerProjectCommands(program) {
|
|
|
1702
2656
|
organization_id: organizationId,
|
|
1703
2657
|
project_id: id,
|
|
1704
2658
|
params: body
|
|
2659
|
+
},
|
|
2660
|
+
variableTypes: {
|
|
2661
|
+
organization_id: "ID!",
|
|
2662
|
+
project_id: "ID!",
|
|
2663
|
+
params: "UpdateProjectParamsInput!"
|
|
1705
2664
|
}
|
|
1706
2665
|
});
|
|
1707
2666
|
});
|
|
@@ -1716,11 +2675,10 @@ var createHelp = buildDataJsonHelp("rock", "create") ?? 'JSON object for rock or
|
|
|
1716
2675
|
var updateHelp = buildDataJsonHelp("rock", "update") ?? 'JSON object for rock or {"rock": {...}}';
|
|
1717
2676
|
function registerRockCommands(program) {
|
|
1718
2677
|
const rocks = program.command("rocks").description("Rock operations");
|
|
1719
|
-
rocks.command("list").option("--page <page>").option("--per <per>").option("--rock-collection-id <rockCollectionId>").option("--
|
|
2678
|
+
rocks.command("list").option("--page <page>").option("--per <per>").option("--rock-collection-id <rockCollectionId>").option("--start-date <startDate>").option("--rock-type <rockType>").option("--team-id <teamId>").option("--member-id <memberId>").option("--meeting-id <meetingId>").option("--annual-objective-id <annualObjectiveId>").option("--quarterly-objective-id <quarterlyObjectiveId>").action(async (opts, cmd) => {
|
|
1720
2679
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1721
2680
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1722
2681
|
const rockCollectionId = opts.rockCollectionId ? rockCollectionIdSchema.parse(opts.rockCollectionId) : void 0;
|
|
1723
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1724
2682
|
await runGraphqlQueryCommand({
|
|
1725
2683
|
command: "rocks.list",
|
|
1726
2684
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -1730,18 +2688,13 @@ function registerRockCommands(program) {
|
|
|
1730
2688
|
page: opts.page,
|
|
1731
2689
|
per: opts.per,
|
|
1732
2690
|
rock_collection_id: rockCollectionId,
|
|
2691
|
+
start_date: opts.startDate,
|
|
2692
|
+
rock_type: opts.rockType,
|
|
1733
2693
|
team_id: opts.teamId,
|
|
1734
|
-
team_ids: opts.teamIds,
|
|
1735
2694
|
member_id: opts.memberId,
|
|
1736
2695
|
meeting_id: opts.meetingId,
|
|
1737
2696
|
annual_objective_id: opts.annualObjectiveId,
|
|
1738
|
-
quarterly_objective_id: opts.quarterlyObjectiveId
|
|
1739
|
-
field_name: opts.fieldName,
|
|
1740
|
-
field_value: opts.fieldValue,
|
|
1741
|
-
field_blank: opts.fieldBlank,
|
|
1742
|
-
rank_direction: opts.rankDirection,
|
|
1743
|
-
include_archived: opts.includeArchived,
|
|
1744
|
-
...extra
|
|
2697
|
+
quarterly_objective_id: opts.quarterlyObjectiveId
|
|
1745
2698
|
}),
|
|
1746
2699
|
isList: true
|
|
1747
2700
|
});
|
|
@@ -1814,28 +2767,161 @@ function registerRockCommands(program) {
|
|
|
1814
2767
|
var import_zod6 = require("zod");
|
|
1815
2768
|
var idSchema5 = import_zod6.z.string().min(1);
|
|
1816
2769
|
var notesSchema = import_zod6.z.string().min(1);
|
|
2770
|
+
var MEETING_TYPES = /* @__PURE__ */ new Set(["TeamMeeting", "OneOnOneMeeting"]);
|
|
2771
|
+
var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed"]);
|
|
2772
|
+
var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
|
|
1817
2773
|
var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
|
|
1818
2774
|
var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
|
|
2775
|
+
function asNonEmptyString2(value) {
|
|
2776
|
+
if (typeof value !== "string") {
|
|
2777
|
+
return void 0;
|
|
2778
|
+
}
|
|
2779
|
+
const trimmed = value.trim();
|
|
2780
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2781
|
+
}
|
|
2782
|
+
function toFiniteNumber(value, field) {
|
|
2783
|
+
if (value === void 0 || value === null) {
|
|
2784
|
+
return void 0;
|
|
2785
|
+
}
|
|
2786
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2787
|
+
return value;
|
|
2788
|
+
}
|
|
2789
|
+
if (typeof value === "string") {
|
|
2790
|
+
const trimmed = value.trim();
|
|
2791
|
+
if (trimmed.length === 0) {
|
|
2792
|
+
return void 0;
|
|
2793
|
+
}
|
|
2794
|
+
const parsed = Number(trimmed);
|
|
2795
|
+
if (Number.isFinite(parsed)) {
|
|
2796
|
+
return parsed;
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
throw new CliError({
|
|
2800
|
+
message: `Invalid ${field}. Expected a numeric value.`,
|
|
2801
|
+
kind: "invalid_args",
|
|
2802
|
+
status: 400,
|
|
2803
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2804
|
+
});
|
|
2805
|
+
}
|
|
2806
|
+
function toStringArray(value, field) {
|
|
2807
|
+
if (value === void 0 || value === null) {
|
|
2808
|
+
return void 0;
|
|
2809
|
+
}
|
|
2810
|
+
const items = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : null;
|
|
2811
|
+
if (!items) {
|
|
2812
|
+
throw new CliError({
|
|
2813
|
+
message: `Invalid ${field}. Expected an array or comma-separated string.`,
|
|
2814
|
+
kind: "invalid_args",
|
|
2815
|
+
status: 400,
|
|
2816
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2817
|
+
});
|
|
2818
|
+
}
|
|
2819
|
+
const normalized = items.map((item) => String(item).trim()).filter((item) => item.length > 0);
|
|
2820
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
2821
|
+
}
|
|
2822
|
+
function normalizeMeetingCreateBody(body) {
|
|
2823
|
+
const entity = body.meeting;
|
|
2824
|
+
if (!entity || typeof entity !== "object" || Array.isArray(entity)) {
|
|
2825
|
+
throw new CliError({
|
|
2826
|
+
message: 'Invalid payload. Expected object at "meeting".',
|
|
2827
|
+
kind: "invalid_args",
|
|
2828
|
+
status: 400,
|
|
2829
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
2830
|
+
});
|
|
2831
|
+
}
|
|
2832
|
+
const meeting = { ...entity };
|
|
2833
|
+
const type = asNonEmptyString2(meeting.type);
|
|
2834
|
+
if (!type || !MEETING_TYPES.has(type)) {
|
|
2835
|
+
throw new CliError({
|
|
2836
|
+
message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
|
|
2837
|
+
kind: "invalid_args",
|
|
2838
|
+
status: 400,
|
|
2839
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2840
|
+
details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
|
|
2841
|
+
});
|
|
2842
|
+
}
|
|
2843
|
+
const memberId = asNonEmptyString2(meeting.member_id);
|
|
2844
|
+
const date = asNonEmptyString2(meeting.date);
|
|
2845
|
+
const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
|
|
2846
|
+
const missingRequired = [];
|
|
2847
|
+
if (!memberId) missingRequired.push("member_id");
|
|
2848
|
+
if (!date) missingRequired.push("date");
|
|
2849
|
+
if (startTime === void 0) missingRequired.push("start_time");
|
|
2850
|
+
if (missingRequired.length > 0) {
|
|
2851
|
+
throw new CliError({
|
|
2852
|
+
message: `Missing required create fields for meeting: ${missingRequired.join(", ")}.`,
|
|
2853
|
+
kind: "invalid_args",
|
|
2854
|
+
status: 400,
|
|
2855
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2856
|
+
details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
|
|
2857
|
+
});
|
|
2858
|
+
}
|
|
2859
|
+
const status = asNonEmptyString2(meeting.status);
|
|
2860
|
+
if (status && !MEETING_STATUSES.has(status)) {
|
|
2861
|
+
throw new CliError({
|
|
2862
|
+
message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
|
|
2863
|
+
kind: "invalid_args",
|
|
2864
|
+
status: 400,
|
|
2865
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2866
|
+
details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
|
|
2867
|
+
});
|
|
2868
|
+
}
|
|
2869
|
+
const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
|
|
2870
|
+
if (!MEETING_REPEATS.has(repeats)) {
|
|
2871
|
+
throw new CliError({
|
|
2872
|
+
message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
|
|
2873
|
+
kind: "invalid_args",
|
|
2874
|
+
status: 400,
|
|
2875
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2876
|
+
details: { field: "meeting.repeats", allowed: Array.from(MEETING_REPEATS) }
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
const teamsIds = toStringArray(meeting.teams_ids, "meeting.teams_ids");
|
|
2880
|
+
if (type === "TeamMeeting" && (!teamsIds || teamsIds.length === 0)) {
|
|
2881
|
+
throw new CliError({
|
|
2882
|
+
message: "Missing required create fields for meeting: teams_ids.",
|
|
2883
|
+
kind: "invalid_args",
|
|
2884
|
+
status: 400,
|
|
2885
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
2886
|
+
details: { requiredFields: ["teams_ids"], rootKey: "meeting" }
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
const endTime = toFiniteNumber(meeting.end_time, "meeting.end_time");
|
|
2890
|
+
meeting.type = type;
|
|
2891
|
+
meeting.member_id = memberId;
|
|
2892
|
+
meeting.date = date;
|
|
2893
|
+
meeting.start_time = startTime;
|
|
2894
|
+
meeting.repeats = repeats;
|
|
2895
|
+
if (status) {
|
|
2896
|
+
meeting.status = status;
|
|
2897
|
+
}
|
|
2898
|
+
if (endTime !== void 0) {
|
|
2899
|
+
meeting.end_time = endTime;
|
|
2900
|
+
}
|
|
2901
|
+
if (teamsIds) {
|
|
2902
|
+
meeting.teams_ids = teamsIds;
|
|
2903
|
+
}
|
|
2904
|
+
return { ...body, meeting };
|
|
2905
|
+
}
|
|
1819
2906
|
function registerMeetingCommands(program) {
|
|
1820
2907
|
const meetings = program.command("meetings").description("Meeting operations");
|
|
1821
|
-
meetings.command("list").option("--per <per>").option("--date <date>").option("--occurrence-date <occurrenceDate>").option("--past <past>").option("--start-time <startTime>").option("--today-and-active <todayAndActive>").option("--
|
|
2908
|
+
meetings.command("list").option("--page <page>").option("--per <per>").option("--date <date>").option("--occurrence-date <occurrenceDate>").option("--past <past>").option("--start-time <startTime>").option("--today-and-active <todayAndActive>").option("--type <type>").action(async (opts, cmd) => {
|
|
1822
2909
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1823
2910
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1824
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1825
2911
|
await runGraphqlQueryCommand({
|
|
1826
2912
|
command: "meetings.list",
|
|
1827
2913
|
runtimeOptions: context.runtimeOptions,
|
|
1828
2914
|
field: "meetings",
|
|
1829
2915
|
variables: normalizeGraphqlVariables2({
|
|
1830
2916
|
organization_id: organizationId,
|
|
2917
|
+
page: opts.page,
|
|
1831
2918
|
per: opts.per,
|
|
1832
2919
|
date: opts.date,
|
|
1833
2920
|
occurrence_date: opts.occurrenceDate,
|
|
1834
2921
|
past: opts.past,
|
|
1835
2922
|
start_time: opts.startTime,
|
|
1836
2923
|
today_and_active: opts.todayAndActive,
|
|
1837
|
-
|
|
1838
|
-
...extra
|
|
2924
|
+
type: opts.type
|
|
1839
2925
|
}),
|
|
1840
2926
|
isList: true
|
|
1841
2927
|
});
|
|
@@ -1878,7 +2964,8 @@ function registerMeetingCommands(program) {
|
|
|
1878
2964
|
meetings.command("create").requiredOption("--data-json <dataJson>", createHelp2).action(async (opts, cmd) => {
|
|
1879
2965
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1880
2966
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1881
|
-
const
|
|
2967
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "meeting");
|
|
2968
|
+
const body = normalizeMeetingCreateBody(rawBody);
|
|
1882
2969
|
await runGraphqlMutationCommand({
|
|
1883
2970
|
command: "meetings.create",
|
|
1884
2971
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -1914,10 +3001,9 @@ var createHelp3 = buildDataJsonHelp("member", "create") ?? 'JSON object for memb
|
|
|
1914
3001
|
var updateHelp3 = buildDataJsonHelp("member", "update") ?? 'JSON object for member or {"member": {...}}';
|
|
1915
3002
|
function registerMemberCommands(program) {
|
|
1916
3003
|
const members = program.command("members").description("Member operations");
|
|
1917
|
-
members.command("list").option("--page <page>").option("--per <per>").
|
|
3004
|
+
members.command("list").option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
|
|
1918
3005
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1919
3006
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1920
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1921
3007
|
await runGraphqlQueryCommand({
|
|
1922
3008
|
command: "members.list",
|
|
1923
3009
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -1925,8 +3011,7 @@ function registerMemberCommands(program) {
|
|
|
1925
3011
|
variables: normalizeGraphqlVariables2({
|
|
1926
3012
|
organization_id: organizationId,
|
|
1927
3013
|
page: opts.page,
|
|
1928
|
-
per: opts.per
|
|
1929
|
-
...extra
|
|
3014
|
+
per: opts.per
|
|
1930
3015
|
}),
|
|
1931
3016
|
isList: true
|
|
1932
3017
|
});
|
|
@@ -1983,14 +3068,15 @@ var import_zod8 = require("zod");
|
|
|
1983
3068
|
var issueGroupIdSchema = import_zod8.z.string().min(1);
|
|
1984
3069
|
var idSchema7 = import_zod8.z.string().min(1);
|
|
1985
3070
|
var nameSchema = import_zod8.z.string().min(1);
|
|
1986
|
-
var issueTypeSchema = import_zod8.z.string().min(1)
|
|
3071
|
+
var issueTypeSchema = import_zod8.z.string().min(1).refine((value) => value === "short_term" || value === "long_term", {
|
|
3072
|
+
message: "Invalid issue type. Use one of: short_term, long_term."
|
|
3073
|
+
});
|
|
1987
3074
|
var updateHelp4 = buildDataJsonHelp("issue", "update") ?? 'JSON object for issue or {"issue": {...}}';
|
|
1988
3075
|
function registerIssueCommands(program) {
|
|
1989
3076
|
const issues = program.command("issues").description("Issue operations");
|
|
1990
|
-
issues.command("list").option("--page <page>").option("--per <per>").option("--issue-group-id <issueGroupId>").option("--
|
|
3077
|
+
issues.command("list").option("--page <page>").option("--per <per>").option("--issue-group-id <issueGroupId>").option("--start-date <startDate>").option("--issue-type <issueType>").option("--team-id <teamId>").option("--member-id <memberId>").option("--meeting-id <meetingId>").action(async (opts, cmd) => {
|
|
1991
3078
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
1992
3079
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
1993
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
1994
3080
|
await runGraphqlQueryCommand({
|
|
1995
3081
|
command: "issues.list",
|
|
1996
3082
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2000,13 +3086,11 @@ function registerIssueCommands(program) {
|
|
|
2000
3086
|
page: opts.page,
|
|
2001
3087
|
per: opts.per,
|
|
2002
3088
|
issue_group_id: opts.issueGroupId,
|
|
3089
|
+
start_date: opts.startDate,
|
|
3090
|
+
issue_type: opts.issueType,
|
|
2003
3091
|
team_id: opts.teamId,
|
|
2004
|
-
team_ids: opts.teamIds,
|
|
2005
3092
|
member_id: opts.memberId,
|
|
2006
|
-
meeting_id: opts.meetingId
|
|
2007
|
-
rank_direction: opts.rankDirection,
|
|
2008
|
-
include_archived: opts.includeArchived,
|
|
2009
|
-
...extra
|
|
3093
|
+
meeting_id: opts.meetingId
|
|
2010
3094
|
}),
|
|
2011
3095
|
isList: true
|
|
2012
3096
|
});
|
|
@@ -2026,7 +3110,7 @@ function registerIssueCommands(program) {
|
|
|
2026
3110
|
isShow: true
|
|
2027
3111
|
});
|
|
2028
3112
|
});
|
|
2029
|
-
issues.command("create").requiredOption("--issue-group-id <issueGroupId>").requiredOption("--name <name>").requiredOption("--issue-type <issueType>").option("--status <status>").option("--priority <priority>").option("--description <description>").option("--due-by <dueBy>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
3113
|
+
issues.command("create").requiredOption("--issue-group-id <issueGroupId>").requiredOption("--name <name>").requiredOption("--issue-type <issueType>", "Issue type: short_term | long_term").option("--status <status>").option("--priority <priority>").option("--description <description>").option("--due-by <dueBy>").option("--member-id <memberId>").action(async (opts, cmd) => {
|
|
2030
3114
|
const issueGroupId = issueGroupIdSchema.parse(opts.issueGroupId);
|
|
2031
3115
|
const name = nameSchema.parse(opts.name);
|
|
2032
3116
|
const issueType = issueTypeSchema.parse(opts.issueType);
|
|
@@ -2071,86 +3155,733 @@ function registerIssueCommands(program) {
|
|
|
2071
3155
|
});
|
|
2072
3156
|
}
|
|
2073
3157
|
|
|
3158
|
+
// src/commands/smartKpiNames.ts
|
|
3159
|
+
var SMART_KPI_NAMES = [
|
|
3160
|
+
"total_active_users",
|
|
3161
|
+
"total_new_users",
|
|
3162
|
+
"total_return_users",
|
|
3163
|
+
"total_engaged_sessions",
|
|
3164
|
+
"total_sessions",
|
|
3165
|
+
"engagement_rate",
|
|
3166
|
+
"bounce_rate",
|
|
3167
|
+
"page_call_phone_clicks_logged_in_unique",
|
|
3168
|
+
"page_cta_clicks_logged_in_unique",
|
|
3169
|
+
"page_engaged_users",
|
|
3170
|
+
"page_fan_adds_unique",
|
|
3171
|
+
"page_fan_adds",
|
|
3172
|
+
"page_fan_removes",
|
|
3173
|
+
"page_fans",
|
|
3174
|
+
"page_get_directions_clicks_logged_in_unique",
|
|
3175
|
+
"page_impressions_unique",
|
|
3176
|
+
"page_impressions",
|
|
3177
|
+
"page_negative_feedback",
|
|
3178
|
+
"page_positive_feedback_comment",
|
|
3179
|
+
"page_positive_feedback_like",
|
|
3180
|
+
"page_positive_feedback_other",
|
|
3181
|
+
"page_positive_feedback_share",
|
|
3182
|
+
"page_post_engagements",
|
|
3183
|
+
"page_total_actions",
|
|
3184
|
+
"page_views_logged_in_unique",
|
|
3185
|
+
"page_views_total",
|
|
3186
|
+
"page_website_clicks_logged_in_unique",
|
|
3187
|
+
"post_clicks_by_type_unique",
|
|
3188
|
+
"post_engaged_users",
|
|
3189
|
+
"post_impressions_fan_paid",
|
|
3190
|
+
"post_impressions_fan",
|
|
3191
|
+
"post_impressions_organic",
|
|
3192
|
+
"post_impressions_unique",
|
|
3193
|
+
"post_impressions",
|
|
3194
|
+
"post_reactions_like_total",
|
|
3195
|
+
"get_directions_clicks",
|
|
3196
|
+
"phone_call_clicks",
|
|
3197
|
+
"profile_views",
|
|
3198
|
+
"reach",
|
|
3199
|
+
"text_message_clicks",
|
|
3200
|
+
"website_clicks",
|
|
3201
|
+
"online_followers",
|
|
3202
|
+
"total_interactions",
|
|
3203
|
+
"accounts_engaged",
|
|
3204
|
+
"likes",
|
|
3205
|
+
"comments",
|
|
3206
|
+
"saves",
|
|
3207
|
+
"shares",
|
|
3208
|
+
"replies",
|
|
3209
|
+
"impressions",
|
|
3210
|
+
"email_contacts",
|
|
3211
|
+
"follower_count",
|
|
3212
|
+
"total_new_conversations",
|
|
3213
|
+
"total_unassigned_conversations",
|
|
3214
|
+
"total_closed_conversations",
|
|
3215
|
+
"total_new_contacts",
|
|
3216
|
+
"total_contacts",
|
|
3217
|
+
"total_revenue",
|
|
3218
|
+
"total_expenses",
|
|
3219
|
+
"cash_flow",
|
|
3220
|
+
"paid_invoices",
|
|
3221
|
+
"unpaid_invoices",
|
|
3222
|
+
"total_new_payments",
|
|
3223
|
+
"total_new_invoices",
|
|
3224
|
+
"total_paid_invoices",
|
|
3225
|
+
"total_refunds",
|
|
3226
|
+
"total_disputes",
|
|
3227
|
+
"calls",
|
|
3228
|
+
"sms",
|
|
3229
|
+
"mms",
|
|
3230
|
+
"verify_push",
|
|
3231
|
+
"verify_totp",
|
|
3232
|
+
"recordings",
|
|
3233
|
+
"transcriptions",
|
|
3234
|
+
"programmable_voice",
|
|
3235
|
+
"authy_phone_verifications",
|
|
3236
|
+
"authy_authentications",
|
|
3237
|
+
"twilio_errors",
|
|
3238
|
+
"twilio_warnings",
|
|
3239
|
+
"twilio_notices",
|
|
3240
|
+
"total_subscribers",
|
|
3241
|
+
"total_subscribers_gained",
|
|
3242
|
+
"total_subscribers_lost",
|
|
3243
|
+
"total_engagement",
|
|
3244
|
+
"total_views",
|
|
3245
|
+
"total_comments",
|
|
3246
|
+
"total_likes",
|
|
3247
|
+
"total_dislikes",
|
|
3248
|
+
"total_shares",
|
|
3249
|
+
"total_card_impressions",
|
|
3250
|
+
"total_card_clicks",
|
|
3251
|
+
"total_card_click_rate",
|
|
3252
|
+
"rock_total_new_rock_groups",
|
|
3253
|
+
"rock_total_rock_groups",
|
|
3254
|
+
"rock_total_new_rocks",
|
|
3255
|
+
"rock_total_new_milestones",
|
|
3256
|
+
"rock_total_completed_milestones",
|
|
3257
|
+
"rock_total_incomplete_milestones",
|
|
3258
|
+
"project_total_projects",
|
|
3259
|
+
"project_total_new_projects",
|
|
3260
|
+
"project_total_new_tasks",
|
|
3261
|
+
"project_total_completed_tasks",
|
|
3262
|
+
"project_total_incomplete_tasks",
|
|
3263
|
+
"project_total_new_sub_tasks",
|
|
3264
|
+
"project_total_completed_sub_tasks",
|
|
3265
|
+
"project_total_incomplete_sub_tasks",
|
|
3266
|
+
"list_total_list",
|
|
3267
|
+
"list_total_new_list",
|
|
3268
|
+
"list_total_new_list_items",
|
|
3269
|
+
"list_total_completed_list_items",
|
|
3270
|
+
"list_total_incomplete_list_items",
|
|
3271
|
+
"list_total_new_sub_items",
|
|
3272
|
+
"list_total_completed_sub_items",
|
|
3273
|
+
"list_total_incomplete_sub_items",
|
|
3274
|
+
"issue_total_issue_groups",
|
|
3275
|
+
"issue_total_new_issue_groups",
|
|
3276
|
+
"issue_total_new_issues",
|
|
3277
|
+
"issue_total_completed_issues",
|
|
3278
|
+
"issue_total_incomplete_issues",
|
|
3279
|
+
"issue_total_new_sub_issues",
|
|
3280
|
+
"issue_total_completed_sub_issues",
|
|
3281
|
+
"issue_total_incomplete_sub_issues",
|
|
3282
|
+
"todo_total_todo_groups",
|
|
3283
|
+
"todo_total_new_todo_groups",
|
|
3284
|
+
"todo_total_new_todos",
|
|
3285
|
+
"todo_total_completed_todos",
|
|
3286
|
+
"todo_total_incomplete_todos",
|
|
3287
|
+
"todo_total_new_sub_todos",
|
|
3288
|
+
"todo_total_completed_sub_todos",
|
|
3289
|
+
"todo_total_incomplete_sub_todos",
|
|
3290
|
+
"measurable_total_scorecards",
|
|
3291
|
+
"measurable_total_new_scorecards",
|
|
3292
|
+
"measurable_total_new_measurables",
|
|
3293
|
+
"stand_up_daily_stand_up_completion_rate",
|
|
3294
|
+
"stand_up_total_stand_ups_complete",
|
|
3295
|
+
"stand_up_daily_stand_up_block_rate",
|
|
3296
|
+
"stand_up_total_blocked_stand_ups",
|
|
3297
|
+
"headline_total_new_headlines",
|
|
3298
|
+
"content_total_content",
|
|
3299
|
+
"content_total_new_content",
|
|
3300
|
+
"question_total_questions",
|
|
3301
|
+
"question_total_new_questions",
|
|
3302
|
+
"question_total_questions_answered",
|
|
3303
|
+
"survey_new_surveys_sent",
|
|
3304
|
+
"member_total_new_members",
|
|
3305
|
+
"member_total_members",
|
|
3306
|
+
"responsibility_total_new_responsibilities_added",
|
|
3307
|
+
"responsibility_total_responsibilities",
|
|
3308
|
+
"customer_total_customers",
|
|
3309
|
+
"customer_total_new_customers",
|
|
3310
|
+
"customer_total_new_customer_logs",
|
|
3311
|
+
"contact_total_contacts",
|
|
3312
|
+
"contact_total_new_contacts",
|
|
3313
|
+
"contact_total_new_contact_logs"
|
|
3314
|
+
];
|
|
3315
|
+
var SMART_KPI_NAME_SET = new Set(SMART_KPI_NAMES);
|
|
3316
|
+
|
|
2074
3317
|
// src/commands/systemTools.ts
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
3318
|
+
var TODO_STATUSES = /* @__PURE__ */ new Set(["open", "completed"]);
|
|
3319
|
+
var KNOWLEDGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["company", "policy", "process"]);
|
|
3320
|
+
var KNOWLEDGE_STATUSES = /* @__PURE__ */ new Set(["draft", "published"]);
|
|
3321
|
+
var NEWS_STATUSES = /* @__PURE__ */ new Set(["active", "completed"]);
|
|
3322
|
+
var NEWS_HEADLINE_TYPES = /* @__PURE__ */ new Set(["team", "org_wide"]);
|
|
3323
|
+
var QUESTION_STATUSES = /* @__PURE__ */ new Set(["asked", "answered"]);
|
|
3324
|
+
var PULSE_STATUSES = /* @__PURE__ */ new Set(["on_track", "at_risk", "off_track"]);
|
|
3325
|
+
var SURVEY_RECIPIENT_TYPES = /* @__PURE__ */ new Set(["member", "team", "org_wide"]);
|
|
3326
|
+
var SURVEY_NAMES = /* @__PURE__ */ new Set([
|
|
3327
|
+
"employee_net_promoter_score",
|
|
3328
|
+
"continuous_performance_review",
|
|
3329
|
+
"core_value_alignment",
|
|
3330
|
+
"engagement",
|
|
3331
|
+
"wellness_and_mental_health",
|
|
3332
|
+
"workspace_culture",
|
|
3333
|
+
"peer_review",
|
|
3334
|
+
"manager_review",
|
|
3335
|
+
"onboarding"
|
|
3336
|
+
]);
|
|
3337
|
+
var FEEDBACK_QUARTERS = /* @__PURE__ */ new Set(["q1", "q2", "q3", "q4"]);
|
|
3338
|
+
var FEEDBACK_NAMES = /* @__PURE__ */ new Set([
|
|
3339
|
+
"productivity_and_focus",
|
|
3340
|
+
"company_collaboration",
|
|
3341
|
+
"project_management",
|
|
3342
|
+
"employee_engagement",
|
|
3343
|
+
"training_and_development",
|
|
3344
|
+
"innovation_and_creativity",
|
|
3345
|
+
"customer_insights",
|
|
3346
|
+
"process_improvement",
|
|
3347
|
+
"leadership_and_management",
|
|
3348
|
+
"company_culture",
|
|
3349
|
+
"roadmap_and_strategy",
|
|
3350
|
+
"customer_testing_and_feedback"
|
|
3351
|
+
]);
|
|
3352
|
+
var SCORECARD_INTERVALS = /* @__PURE__ */ new Set([
|
|
3353
|
+
"daily",
|
|
3354
|
+
"weekly",
|
|
3355
|
+
"monthly",
|
|
3356
|
+
"quarterly",
|
|
3357
|
+
"yearly"
|
|
3358
|
+
]);
|
|
3359
|
+
var SCORECARD_TRENDS = /* @__PURE__ */ new Set(["average", "total"]);
|
|
3360
|
+
function isRecord2(value) {
|
|
3361
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3362
|
+
}
|
|
3363
|
+
function ensureEntityObject(body, rootKey) {
|
|
3364
|
+
const entity = body[rootKey];
|
|
3365
|
+
if (!isRecord2(entity)) {
|
|
3366
|
+
throw new CliError({
|
|
3367
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
3368
|
+
kind: "invalid_args",
|
|
3369
|
+
status: 400,
|
|
3370
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
3371
|
+
});
|
|
3372
|
+
}
|
|
3373
|
+
return { ...entity };
|
|
3374
|
+
}
|
|
3375
|
+
function throwMissingRequiredCreateFields(rootKey, fields) {
|
|
3376
|
+
throw new CliError({
|
|
3377
|
+
message: `Missing required create fields for ${rootKey}: ${fields.join(", ")}.`,
|
|
3378
|
+
kind: "invalid_args",
|
|
3379
|
+
status: 400,
|
|
3380
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3381
|
+
details: { requiredFields: fields, rootKey }
|
|
2115
3382
|
});
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
"
|
|
2127
|
-
"
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
3383
|
+
}
|
|
3384
|
+
function normalizeTodosCreateBody(body) {
|
|
3385
|
+
const todo = ensureEntityObject(body, "todo");
|
|
3386
|
+
const rawStatus = todo.status;
|
|
3387
|
+
if (rawStatus === void 0 || rawStatus === null || String(rawStatus).trim().length === 0) {
|
|
3388
|
+
todo.status = "open";
|
|
3389
|
+
return { ...body, todo };
|
|
3390
|
+
}
|
|
3391
|
+
if (typeof rawStatus !== "string" || !TODO_STATUSES.has(rawStatus)) {
|
|
3392
|
+
throw new CliError({
|
|
3393
|
+
message: "Invalid todo status. Use one of: open, completed.",
|
|
3394
|
+
kind: "invalid_args",
|
|
3395
|
+
status: 400,
|
|
3396
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3397
|
+
details: { allowed: Array.from(TODO_STATUSES) }
|
|
3398
|
+
});
|
|
3399
|
+
}
|
|
3400
|
+
return { ...body, todo };
|
|
3401
|
+
}
|
|
3402
|
+
function asNonEmptyString3(value) {
|
|
3403
|
+
if (typeof value !== "string") {
|
|
3404
|
+
return void 0;
|
|
3405
|
+
}
|
|
3406
|
+
const trimmed = value.trim();
|
|
3407
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3408
|
+
}
|
|
3409
|
+
function validateEnumField(params) {
|
|
3410
|
+
const value = asNonEmptyString3(params.rawValue);
|
|
3411
|
+
if (!value) {
|
|
3412
|
+
return void 0;
|
|
3413
|
+
}
|
|
3414
|
+
if (!params.allowed.has(value)) {
|
|
3415
|
+
throw new CliError({
|
|
3416
|
+
message: params.message,
|
|
3417
|
+
kind: "invalid_args",
|
|
3418
|
+
status: 400,
|
|
3419
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3420
|
+
details: { field: params.field, allowed: Array.from(params.allowed) }
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3423
|
+
return value;
|
|
3424
|
+
}
|
|
3425
|
+
function normalizeKnowledgeCreateBody(body) {
|
|
3426
|
+
const content = ensureEntityObject(body, "content");
|
|
3427
|
+
const contentType = validateEnumField({
|
|
3428
|
+
rawValue: content.content_type,
|
|
3429
|
+
field: "content.content_type",
|
|
3430
|
+
allowed: KNOWLEDGE_CONTENT_TYPES,
|
|
3431
|
+
message: "Invalid content.content_type. Use one of: company, policy, process."
|
|
3432
|
+
});
|
|
3433
|
+
if (!contentType) {
|
|
3434
|
+
throwMissingRequiredCreateFields("content", ["content_type"]);
|
|
3435
|
+
}
|
|
3436
|
+
content.content_type = contentType;
|
|
3437
|
+
const status = validateEnumField({
|
|
3438
|
+
rawValue: content.status,
|
|
3439
|
+
field: "content.status",
|
|
3440
|
+
allowed: KNOWLEDGE_STATUSES,
|
|
3441
|
+
message: "Invalid content.status. Use one of: draft, published."
|
|
3442
|
+
});
|
|
3443
|
+
content.status = status ?? "draft";
|
|
3444
|
+
const memberId = asNonEmptyString3(content.member_id);
|
|
3445
|
+
if (!memberId) {
|
|
3446
|
+
throwMissingRequiredCreateFields("content", ["member_id"]);
|
|
3447
|
+
}
|
|
3448
|
+
content.member_id = memberId;
|
|
3449
|
+
return { ...body, content };
|
|
3450
|
+
}
|
|
3451
|
+
function normalizeNewsCreateBody(body) {
|
|
3452
|
+
const headline = ensureEntityObject(body, "headline");
|
|
3453
|
+
const memberId = asNonEmptyString3(headline.member_id);
|
|
3454
|
+
if (!memberId) {
|
|
3455
|
+
throwMissingRequiredCreateFields("headline", ["member_id"]);
|
|
3456
|
+
}
|
|
3457
|
+
headline.member_id = memberId;
|
|
3458
|
+
const status = validateEnumField({
|
|
3459
|
+
rawValue: headline.status,
|
|
3460
|
+
field: "headline.status",
|
|
3461
|
+
allowed: NEWS_STATUSES,
|
|
3462
|
+
message: "Invalid headline.status. Use one of: active, completed."
|
|
3463
|
+
});
|
|
3464
|
+
if (!status) {
|
|
3465
|
+
throwMissingRequiredCreateFields("headline", ["status"]);
|
|
3466
|
+
}
|
|
3467
|
+
headline.status = status;
|
|
3468
|
+
const headlineType = validateEnumField({
|
|
3469
|
+
rawValue: headline.headline_type,
|
|
3470
|
+
field: "headline.headline_type",
|
|
3471
|
+
allowed: NEWS_HEADLINE_TYPES,
|
|
3472
|
+
message: "Invalid headline.headline_type. Use one of: team, org_wide."
|
|
3473
|
+
});
|
|
3474
|
+
if (!headlineType) {
|
|
3475
|
+
throwMissingRequiredCreateFields("headline", ["headline_type"]);
|
|
3476
|
+
}
|
|
3477
|
+
headline.headline_type = headlineType;
|
|
3478
|
+
return { ...body, headline };
|
|
3479
|
+
}
|
|
3480
|
+
function normalizeQuestionsCreateBody(body) {
|
|
3481
|
+
const question = ensureEntityObject(body, "question");
|
|
3482
|
+
const summary = asNonEmptyString3(question.summary);
|
|
3483
|
+
const currentName = asNonEmptyString3(question.name);
|
|
3484
|
+
if (!currentName && summary) {
|
|
3485
|
+
question.name = summary;
|
|
3486
|
+
}
|
|
3487
|
+
delete question.summary;
|
|
3488
|
+
const name = asNonEmptyString3(question.name);
|
|
3489
|
+
const memberId = asNonEmptyString3(question.member_id);
|
|
3490
|
+
const missing = [];
|
|
3491
|
+
if (!name) missing.push("name");
|
|
3492
|
+
if (!memberId) missing.push("member_id");
|
|
3493
|
+
if (missing.length > 0) {
|
|
3494
|
+
throwMissingRequiredCreateFields("question", missing);
|
|
3495
|
+
}
|
|
3496
|
+
question.name = name;
|
|
3497
|
+
question.member_id = memberId;
|
|
3498
|
+
const status = validateEnumField({
|
|
3499
|
+
rawValue: question.status,
|
|
3500
|
+
field: "question.status",
|
|
3501
|
+
allowed: QUESTION_STATUSES,
|
|
3502
|
+
message: "Invalid question.status. Use one of: asked, answered."
|
|
3503
|
+
});
|
|
3504
|
+
if (status) {
|
|
3505
|
+
question.status = status;
|
|
3506
|
+
}
|
|
3507
|
+
return { ...body, question };
|
|
3508
|
+
}
|
|
3509
|
+
function normalizeQuestionsUpdateBody(body) {
|
|
3510
|
+
const question = ensureEntityObject(body, "question");
|
|
3511
|
+
const summary = asNonEmptyString3(question.summary);
|
|
3512
|
+
const currentName = asNonEmptyString3(question.name);
|
|
3513
|
+
if (!currentName && summary) {
|
|
3514
|
+
question.name = summary;
|
|
3515
|
+
}
|
|
3516
|
+
delete question.summary;
|
|
3517
|
+
const name = asNonEmptyString3(question.name);
|
|
3518
|
+
if (name) {
|
|
3519
|
+
question.name = name;
|
|
3520
|
+
}
|
|
3521
|
+
const status = validateEnumField({
|
|
3522
|
+
rawValue: question.status,
|
|
3523
|
+
field: "question.status",
|
|
3524
|
+
allowed: QUESTION_STATUSES,
|
|
3525
|
+
message: "Invalid question.status. Use one of: asked, answered."
|
|
3526
|
+
});
|
|
3527
|
+
if (status) {
|
|
3528
|
+
question.status = status;
|
|
3529
|
+
}
|
|
3530
|
+
return { ...body, question };
|
|
3531
|
+
}
|
|
3532
|
+
function normalizePulseCreateBody(body) {
|
|
3533
|
+
const healthUpdate = ensureEntityObject(body, "health_update");
|
|
3534
|
+
const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
|
|
3535
|
+
const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
|
|
3536
|
+
const memberId = asNonEmptyString3(healthUpdate.member_id);
|
|
3537
|
+
const status = validateEnumField({
|
|
3538
|
+
rawValue: healthUpdate.status,
|
|
3539
|
+
field: "health_update.status",
|
|
3540
|
+
allowed: PULSE_STATUSES,
|
|
3541
|
+
message: "Invalid health_update.status. Use one of: on_track, at_risk, off_track."
|
|
3542
|
+
});
|
|
3543
|
+
const missing = [];
|
|
3544
|
+
if (!healthUpdatableId) missing.push("health_updatable_id");
|
|
3545
|
+
if (!healthUpdatableType) missing.push("health_updatable_type");
|
|
3546
|
+
if (!memberId) missing.push("member_id");
|
|
3547
|
+
if (!status) missing.push("status");
|
|
3548
|
+
if (missing.length > 0) {
|
|
3549
|
+
throwMissingRequiredCreateFields("health_update", missing);
|
|
3550
|
+
}
|
|
3551
|
+
healthUpdate.health_updatable_id = healthUpdatableId;
|
|
3552
|
+
healthUpdate.health_updatable_type = healthUpdatableType;
|
|
3553
|
+
healthUpdate.member_id = memberId;
|
|
3554
|
+
healthUpdate.status = status;
|
|
3555
|
+
delete healthUpdate.updatable_id;
|
|
3556
|
+
delete healthUpdate.updatable_type;
|
|
3557
|
+
return { ...body, health_update: healthUpdate };
|
|
3558
|
+
}
|
|
3559
|
+
function normalizeSurveysCreateBody(body) {
|
|
3560
|
+
const survey = ensureEntityObject(body, "survey");
|
|
3561
|
+
const title = asNonEmptyString3(survey.title);
|
|
3562
|
+
const currentName = asNonEmptyString3(survey.name);
|
|
3563
|
+
if (!currentName && title) {
|
|
3564
|
+
survey.name = title;
|
|
3565
|
+
}
|
|
3566
|
+
delete survey.title;
|
|
3567
|
+
const name = validateEnumField({
|
|
3568
|
+
rawValue: survey.name,
|
|
3569
|
+
field: "survey.name",
|
|
3570
|
+
allowed: SURVEY_NAMES,
|
|
3571
|
+
message: "Invalid survey.name. Use one of: employee_net_promoter_score, continuous_performance_review, core_value_alignment, engagement, wellness_and_mental_health, workspace_culture, peer_review, manager_review, onboarding."
|
|
3572
|
+
});
|
|
3573
|
+
const recipientType = validateEnumField({
|
|
3574
|
+
rawValue: survey.recipient_type,
|
|
3575
|
+
field: "survey.recipient_type",
|
|
3576
|
+
allowed: SURVEY_RECIPIENT_TYPES,
|
|
3577
|
+
message: "Invalid survey.recipient_type. Use one of: member, team, org_wide."
|
|
3578
|
+
});
|
|
3579
|
+
const missing = [];
|
|
3580
|
+
if (!name) missing.push("name");
|
|
3581
|
+
if (!recipientType) missing.push("recipient_type");
|
|
3582
|
+
if (missing.length > 0) {
|
|
3583
|
+
throwMissingRequiredCreateFields("survey", missing);
|
|
3584
|
+
}
|
|
3585
|
+
survey.name = name;
|
|
3586
|
+
survey.recipient_type = recipientType;
|
|
3587
|
+
return { ...body, survey };
|
|
3588
|
+
}
|
|
3589
|
+
function normalizeSurveysUpdateBody(body) {
|
|
3590
|
+
const survey = ensureEntityObject(body, "survey");
|
|
3591
|
+
const title = asNonEmptyString3(survey.title);
|
|
3592
|
+
const currentName = asNonEmptyString3(survey.name);
|
|
3593
|
+
if (!currentName && title) {
|
|
3594
|
+
survey.name = title;
|
|
3595
|
+
}
|
|
3596
|
+
delete survey.title;
|
|
3597
|
+
const name = validateEnumField({
|
|
3598
|
+
rawValue: survey.name,
|
|
3599
|
+
field: "survey.name",
|
|
3600
|
+
allowed: SURVEY_NAMES,
|
|
3601
|
+
message: "Invalid survey.name. Use one of: employee_net_promoter_score, continuous_performance_review, core_value_alignment, engagement, wellness_and_mental_health, workspace_culture, peer_review, manager_review, onboarding."
|
|
3602
|
+
});
|
|
3603
|
+
if (name) {
|
|
3604
|
+
survey.name = name;
|
|
3605
|
+
}
|
|
3606
|
+
const recipientType = validateEnumField({
|
|
3607
|
+
rawValue: survey.recipient_type,
|
|
3608
|
+
field: "survey.recipient_type",
|
|
3609
|
+
allowed: SURVEY_RECIPIENT_TYPES,
|
|
3610
|
+
message: "Invalid survey.recipient_type. Use one of: member, team, org_wide."
|
|
3611
|
+
});
|
|
3612
|
+
if (recipientType) {
|
|
3613
|
+
survey.recipient_type = recipientType;
|
|
3614
|
+
}
|
|
3615
|
+
return { ...body, survey };
|
|
3616
|
+
}
|
|
3617
|
+
function normalizeFeedbacksCreateBody(body) {
|
|
3618
|
+
const feedback = ensureEntityObject(body, "feedback");
|
|
3619
|
+
const title = asNonEmptyString3(feedback.title);
|
|
3620
|
+
const currentName = asNonEmptyString3(feedback.name);
|
|
3621
|
+
if (!currentName && title) {
|
|
3622
|
+
feedback.name = title;
|
|
3623
|
+
}
|
|
3624
|
+
delete feedback.title;
|
|
3625
|
+
const name = validateEnumField({
|
|
3626
|
+
rawValue: feedback.name,
|
|
3627
|
+
field: "feedback.name",
|
|
3628
|
+
allowed: FEEDBACK_NAMES,
|
|
3629
|
+
message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
|
|
3630
|
+
});
|
|
3631
|
+
const quarter = validateEnumField({
|
|
3632
|
+
rawValue: feedback.quarter,
|
|
3633
|
+
field: "feedback.quarter",
|
|
3634
|
+
allowed: FEEDBACK_QUARTERS,
|
|
3635
|
+
message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
|
|
3636
|
+
});
|
|
3637
|
+
const year = asNonEmptyString3(feedback.year);
|
|
3638
|
+
const missing = [];
|
|
3639
|
+
if (!name) missing.push("name");
|
|
3640
|
+
if (!quarter) missing.push("quarter");
|
|
3641
|
+
if (!year) missing.push("year");
|
|
3642
|
+
if (missing.length > 0) {
|
|
3643
|
+
throwMissingRequiredCreateFields("feedback", missing);
|
|
3644
|
+
}
|
|
3645
|
+
feedback.name = name;
|
|
3646
|
+
feedback.quarter = quarter;
|
|
3647
|
+
feedback.year = year;
|
|
3648
|
+
return { ...body, feedback };
|
|
3649
|
+
}
|
|
3650
|
+
function normalizeFeedbacksUpdateBody(body) {
|
|
3651
|
+
const feedback = ensureEntityObject(body, "feedback");
|
|
3652
|
+
const title = asNonEmptyString3(feedback.title);
|
|
3653
|
+
const currentName = asNonEmptyString3(feedback.name);
|
|
3654
|
+
if (!currentName && title) {
|
|
3655
|
+
feedback.name = title;
|
|
3656
|
+
}
|
|
3657
|
+
delete feedback.title;
|
|
3658
|
+
const name = validateEnumField({
|
|
3659
|
+
rawValue: feedback.name,
|
|
3660
|
+
field: "feedback.name",
|
|
3661
|
+
allowed: FEEDBACK_NAMES,
|
|
3662
|
+
message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
|
|
3663
|
+
});
|
|
3664
|
+
if (name) {
|
|
3665
|
+
feedback.name = name;
|
|
3666
|
+
}
|
|
3667
|
+
const quarter = validateEnumField({
|
|
3668
|
+
rawValue: feedback.quarter,
|
|
3669
|
+
field: "feedback.quarter",
|
|
3670
|
+
allowed: FEEDBACK_QUARTERS,
|
|
3671
|
+
message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
|
|
3672
|
+
});
|
|
3673
|
+
if (quarter) {
|
|
3674
|
+
feedback.quarter = quarter;
|
|
3675
|
+
}
|
|
3676
|
+
return { ...body, feedback };
|
|
3677
|
+
}
|
|
3678
|
+
function normalizeAccountabilityCreateBody(body) {
|
|
3679
|
+
const responsibility = ensureEntityObject(body, "responsibility");
|
|
3680
|
+
const summary = asNonEmptyString3(responsibility.summary);
|
|
3681
|
+
const currentName = asNonEmptyString3(responsibility.name);
|
|
3682
|
+
if (!currentName && summary) {
|
|
3683
|
+
responsibility.name = summary;
|
|
3684
|
+
}
|
|
3685
|
+
delete responsibility.summary;
|
|
3686
|
+
const name = asNonEmptyString3(responsibility.name);
|
|
3687
|
+
const memberId = asNonEmptyString3(responsibility.member_id);
|
|
3688
|
+
const missing = [];
|
|
3689
|
+
if (!name) missing.push("name");
|
|
3690
|
+
if (!memberId) missing.push("member_id");
|
|
3691
|
+
if (missing.length > 0) {
|
|
3692
|
+
throwMissingRequiredCreateFields("responsibility", missing);
|
|
3693
|
+
}
|
|
3694
|
+
responsibility.name = name;
|
|
3695
|
+
responsibility.member_id = memberId;
|
|
3696
|
+
return { ...body, responsibility };
|
|
3697
|
+
}
|
|
3698
|
+
function normalizeAccountabilityUpdateBody(body) {
|
|
3699
|
+
const responsibility = ensureEntityObject(body, "responsibility");
|
|
3700
|
+
const summary = asNonEmptyString3(responsibility.summary);
|
|
3701
|
+
const currentName = asNonEmptyString3(responsibility.name);
|
|
3702
|
+
if (!currentName && summary) {
|
|
3703
|
+
responsibility.name = summary;
|
|
3704
|
+
}
|
|
3705
|
+
delete responsibility.summary;
|
|
3706
|
+
return { ...body, responsibility };
|
|
3707
|
+
}
|
|
3708
|
+
function normalizeScorecardsCreateBody(body) {
|
|
3709
|
+
const measurable = ensureEntityObject(body, "measurable");
|
|
3710
|
+
const interval = validateEnumField({
|
|
3711
|
+
rawValue: measurable.interval,
|
|
3712
|
+
field: "measurable.interval",
|
|
3713
|
+
allowed: SCORECARD_INTERVALS,
|
|
3714
|
+
message: "Invalid measurable.interval. Use one of: daily, weekly, monthly, quarterly, yearly."
|
|
3715
|
+
});
|
|
3716
|
+
measurable.interval = interval ?? "weekly";
|
|
3717
|
+
const trend = validateEnumField({
|
|
3718
|
+
rawValue: measurable.trend,
|
|
3719
|
+
field: "measurable.trend",
|
|
3720
|
+
allowed: SCORECARD_TRENDS,
|
|
3721
|
+
message: "Invalid measurable.trend. Use one of: average, total."
|
|
3722
|
+
});
|
|
3723
|
+
measurable.trend = trend ?? "average";
|
|
3724
|
+
return { ...body, measurable };
|
|
3725
|
+
}
|
|
3726
|
+
function buildKpisCreateMutation(params) {
|
|
3727
|
+
const entity = params.body.smart_kpi;
|
|
3728
|
+
if (!entity || typeof entity !== "object" || Array.isArray(entity)) {
|
|
3729
|
+
throw new CliError({
|
|
3730
|
+
message: 'Invalid payload. Expected object at "smart_kpi".',
|
|
3731
|
+
kind: "invalid_args",
|
|
3732
|
+
status: 400,
|
|
3733
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
3734
|
+
});
|
|
3735
|
+
}
|
|
3736
|
+
const smartKpi = { ...entity };
|
|
3737
|
+
const name = asNonEmptyString3(smartKpi.name);
|
|
3738
|
+
const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
|
|
3739
|
+
const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
|
|
3740
|
+
const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
|
|
3741
|
+
if (!name) {
|
|
3742
|
+
throw new CliError({
|
|
3743
|
+
message: "Missing required create fields for smart_kpi: name.",
|
|
3744
|
+
kind: "invalid_args",
|
|
3745
|
+
status: 400,
|
|
3746
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3747
|
+
details: { requiredFields: ["name"], rootKey: "smart_kpi" }
|
|
3748
|
+
});
|
|
3749
|
+
}
|
|
3750
|
+
if (measurableGroupId && !hasAllowedName) {
|
|
3751
|
+
const measurable = {
|
|
3752
|
+
measurable_group_id: measurableGroupId,
|
|
3753
|
+
name,
|
|
3754
|
+
interval: "daily",
|
|
3755
|
+
trend: "average",
|
|
3756
|
+
measurable_type: "number",
|
|
3757
|
+
condition: "greater_than_or_equal_to"
|
|
3758
|
+
};
|
|
3759
|
+
const notes = asNonEmptyString3(smartKpi.notes);
|
|
3760
|
+
if (notes) {
|
|
3761
|
+
measurable.notes = notes;
|
|
3762
|
+
}
|
|
3763
|
+
return {
|
|
3764
|
+
command: "measurables.create",
|
|
3765
|
+
field: "create_measurable",
|
|
3766
|
+
variables: {
|
|
3767
|
+
organization_id: params.organizationId,
|
|
3768
|
+
params: { measurable }
|
|
3769
|
+
}
|
|
3770
|
+
};
|
|
3771
|
+
}
|
|
3772
|
+
if (!smartKpiViewId) {
|
|
3773
|
+
throw new CliError({
|
|
3774
|
+
message: "Missing required create fields for smart_kpi: smart_kpi_view_id.",
|
|
3775
|
+
kind: "invalid_args",
|
|
3776
|
+
status: 400,
|
|
3777
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3778
|
+
details: { requiredFields: ["smart_kpi_view_id"], rootKey: "smart_kpi" }
|
|
3779
|
+
});
|
|
3780
|
+
}
|
|
3781
|
+
if (!hasAllowedName) {
|
|
3782
|
+
throw new CliError({
|
|
3783
|
+
message: "Invalid smart_kpi.name for kpis.create. Use an allowed enum value or route free-text KPI names to measurable create.",
|
|
3784
|
+
kind: "invalid_args",
|
|
3785
|
+
status: 400,
|
|
3786
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
3787
|
+
details: {
|
|
3788
|
+
field: "smart_kpi.name",
|
|
3789
|
+
allowedValues: SMART_KPI_NAMES
|
|
3790
|
+
}
|
|
3791
|
+
});
|
|
3792
|
+
}
|
|
3793
|
+
delete smartKpi.measurable_group_id;
|
|
3794
|
+
smartKpi.name = name;
|
|
3795
|
+
smartKpi.smart_kpi_view_id = smartKpiViewId;
|
|
3796
|
+
return {
|
|
3797
|
+
command: "kpis.create",
|
|
3798
|
+
field: "create_smart_kpi",
|
|
3799
|
+
variables: {
|
|
3800
|
+
organization_id: params.organizationId,
|
|
3801
|
+
params: { smart_kpi: smartKpi }
|
|
3802
|
+
}
|
|
3803
|
+
};
|
|
3804
|
+
}
|
|
3805
|
+
function registerSystemToolCommands(program) {
|
|
3806
|
+
registerEntityCrudCommands(program, {
|
|
3807
|
+
command: "lists",
|
|
3808
|
+
description: "List operations",
|
|
3809
|
+
resourcePath: "lists",
|
|
3810
|
+
rootKey: "list",
|
|
3811
|
+
listParams: ["member_id", "team_ids"],
|
|
3812
|
+
showParams: ["current_member_id"],
|
|
3813
|
+
allowQueryJson: false
|
|
3814
|
+
});
|
|
3815
|
+
registerEntityCrudCommands(program, {
|
|
3816
|
+
command: "list-items",
|
|
3817
|
+
description: "List item operations",
|
|
3818
|
+
resourcePath: "list_items",
|
|
3819
|
+
rootKey: "list_item",
|
|
3820
|
+
requiredCreateFields: ["list_id"],
|
|
3821
|
+
listParams: ["list_id", "meeting_id", "open", "team_id", "member_id", "include_archived"],
|
|
3822
|
+
allowQueryJson: false
|
|
3823
|
+
});
|
|
3824
|
+
registerEntityCrudCommands(program, {
|
|
3825
|
+
command: "issue-groups",
|
|
3826
|
+
description: "Issue group operations",
|
|
3827
|
+
resourcePath: "issue_groups",
|
|
3828
|
+
rootKey: "issue_group",
|
|
3829
|
+
listParams: ["member_id", "team_ids"],
|
|
3830
|
+
showParams: ["current_member_id"],
|
|
3831
|
+
allowQueryJson: false
|
|
3832
|
+
});
|
|
3833
|
+
registerEntityCrudCommands(program, {
|
|
3834
|
+
command: "todo-groups",
|
|
3835
|
+
description: "To-do group operations",
|
|
3836
|
+
resourcePath: "todo_groups",
|
|
3837
|
+
rootKey: "todo_group",
|
|
3838
|
+
listParams: ["member_id", "team_ids"],
|
|
3839
|
+
showParams: ["current_member_id"],
|
|
3840
|
+
allowQueryJson: false
|
|
3841
|
+
});
|
|
3842
|
+
registerEntityCrudCommands(program, {
|
|
3843
|
+
command: "todos",
|
|
3844
|
+
description: "To-do operations",
|
|
3845
|
+
resourcePath: "todos",
|
|
3846
|
+
rootKey: "todo",
|
|
3847
|
+
requiredCreateFields: ["todo_group_id"],
|
|
3848
|
+
normalizeCreateBody: normalizeTodosCreateBody,
|
|
3849
|
+
listParams: ["todo_group_id", "start_date", "team_id", "member_id"],
|
|
3850
|
+
allowQueryJson: false
|
|
2131
3851
|
});
|
|
2132
3852
|
registerEntityCrudCommands(program, {
|
|
2133
3853
|
command: "rock-collections",
|
|
2134
3854
|
description: "Rock collection operations",
|
|
2135
3855
|
resourcePath: "rock_collections",
|
|
2136
3856
|
rootKey: "rock_collection",
|
|
2137
|
-
listParams: ["
|
|
3857
|
+
listParams: ["member_id", "team_ids"],
|
|
3858
|
+
showParams: ["current_member_id"],
|
|
3859
|
+
allowQueryJson: false
|
|
2138
3860
|
});
|
|
2139
3861
|
registerEntityCrudCommands(program, {
|
|
2140
3862
|
command: "knowledge",
|
|
2141
3863
|
description: "Knowledge content operations",
|
|
2142
3864
|
resourcePath: "contents",
|
|
2143
3865
|
rootKey: "content",
|
|
3866
|
+
normalizeCreateBody: normalizeKnowledgeCreateBody,
|
|
2144
3867
|
listParams: [
|
|
2145
3868
|
"assigned",
|
|
2146
3869
|
"contentable_id",
|
|
3870
|
+
"contentable_ids",
|
|
3871
|
+
"content_type",
|
|
2147
3872
|
"contentable_type",
|
|
2148
|
-
"
|
|
2149
|
-
"
|
|
3873
|
+
"focus_member_id",
|
|
3874
|
+
"focus_team_id",
|
|
2150
3875
|
"member_id",
|
|
2151
3876
|
"parent_content_id",
|
|
2152
|
-
"
|
|
2153
|
-
|
|
3877
|
+
"sort",
|
|
3878
|
+
"status",
|
|
3879
|
+
"team_id",
|
|
3880
|
+
"term",
|
|
3881
|
+
"type"
|
|
3882
|
+
],
|
|
3883
|
+
showParams: ["include_all_rollups"],
|
|
3884
|
+
allowQueryJson: false
|
|
2154
3885
|
});
|
|
2155
3886
|
registerEntityCrudCommands(program, {
|
|
2156
3887
|
command: "stand-ups",
|
|
@@ -2163,74 +3894,118 @@ function registerSystemToolCommands(program) {
|
|
|
2163
3894
|
"date",
|
|
2164
3895
|
"end_date",
|
|
2165
3896
|
"start_date",
|
|
3897
|
+
"team_id",
|
|
2166
3898
|
"use_week_range"
|
|
2167
|
-
]
|
|
3899
|
+
],
|
|
3900
|
+
allowQueryJson: false
|
|
2168
3901
|
});
|
|
2169
3902
|
registerEntityCrudCommands(program, {
|
|
2170
3903
|
command: "news",
|
|
2171
3904
|
description: "News operations",
|
|
2172
3905
|
resourcePath: "headlines",
|
|
2173
3906
|
rootKey: "headline",
|
|
2174
|
-
|
|
3907
|
+
requiredCreateFields: ["member_id", "status", "headline_type"],
|
|
3908
|
+
normalizeCreateBody: normalizeNewsCreateBody,
|
|
3909
|
+
listParams: ["meeting_id", "team_id", "unread"],
|
|
3910
|
+
allowQueryJson: false,
|
|
3911
|
+
showQueryFactory: ({ id, organizationId }) => ({
|
|
3912
|
+
field: "headlines",
|
|
3913
|
+
variables: {
|
|
3914
|
+
organization_id: organizationId,
|
|
3915
|
+
page: 1,
|
|
3916
|
+
per: 200
|
|
3917
|
+
},
|
|
3918
|
+
selectionSet: "{ data { id type slug summary description memberId status rank createdAt updatedAt headlineType teamIds meetingId labelIds attributes } count currentPage totalPages }",
|
|
3919
|
+
transformData: (value) => {
|
|
3920
|
+
if (!value || typeof value !== "object") {
|
|
3921
|
+
return null;
|
|
3922
|
+
}
|
|
3923
|
+
const payload = value;
|
|
3924
|
+
const rows = Array.isArray(payload.data) ? payload.data : [];
|
|
3925
|
+
return rows.find((row) => {
|
|
3926
|
+
if (!row || typeof row !== "object") {
|
|
3927
|
+
return false;
|
|
3928
|
+
}
|
|
3929
|
+
return String(row.id ?? "") === id;
|
|
3930
|
+
}) ?? null;
|
|
3931
|
+
}
|
|
3932
|
+
})
|
|
2175
3933
|
});
|
|
2176
3934
|
registerEntityCrudCommands(program, {
|
|
2177
3935
|
command: "questions",
|
|
2178
3936
|
description: "Q&A forum operations",
|
|
2179
3937
|
resourcePath: "questions",
|
|
2180
3938
|
rootKey: "question",
|
|
2181
|
-
|
|
3939
|
+
requiredCreateFields: ["member_id", "name"],
|
|
3940
|
+
normalizeCreateBody: normalizeQuestionsCreateBody,
|
|
3941
|
+
normalizeUpdateBody: normalizeQuestionsUpdateBody,
|
|
3942
|
+
listParams: ["answered", "asked"],
|
|
3943
|
+
allowQueryJson: false
|
|
2182
3944
|
});
|
|
2183
3945
|
registerEntityCrudCommands(program, {
|
|
2184
3946
|
command: "pulse",
|
|
2185
3947
|
description: "Pulse operations",
|
|
2186
3948
|
resourcePath: "health_updates",
|
|
2187
3949
|
rootKey: "health_update",
|
|
2188
|
-
|
|
3950
|
+
listField: "feedbacks",
|
|
3951
|
+
showField: "feedback",
|
|
3952
|
+
requiredCreateFields: ["health_updatable_id", "health_updatable_type", "member_id", "status"],
|
|
3953
|
+
normalizeCreateBody: normalizePulseCreateBody,
|
|
3954
|
+
listParams: ["last", "latest", "start_date", "name", "quarter", "year"],
|
|
3955
|
+
allowQueryJson: false
|
|
2189
3956
|
});
|
|
2190
3957
|
registerEntityCrudCommands(program, {
|
|
2191
3958
|
command: "surveys",
|
|
2192
3959
|
description: "Survey operations",
|
|
2193
3960
|
resourcePath: "surveys",
|
|
2194
3961
|
rootKey: "survey",
|
|
2195
|
-
|
|
3962
|
+
requiredCreateFields: ["name", "recipient_type"],
|
|
3963
|
+
normalizeCreateBody: normalizeSurveysCreateBody,
|
|
3964
|
+
normalizeUpdateBody: normalizeSurveysUpdateBody,
|
|
3965
|
+
listParams: ["completed", "current_member", "due", "exclude_completed", "sent"],
|
|
3966
|
+
allowQueryJson: false
|
|
2196
3967
|
});
|
|
2197
3968
|
registerEntityCrudCommands(program, {
|
|
2198
3969
|
command: "feedbacks",
|
|
2199
3970
|
description: "Feedback operations",
|
|
2200
3971
|
resourcePath: "feedback",
|
|
2201
3972
|
rootKey: "feedback",
|
|
2202
|
-
|
|
3973
|
+
requiredCreateFields: ["name", "quarter", "year"],
|
|
3974
|
+
normalizeCreateBody: normalizeFeedbacksCreateBody,
|
|
3975
|
+
normalizeUpdateBody: normalizeFeedbacksUpdateBody,
|
|
3976
|
+
listParams: ["last", "latest", "start_date"],
|
|
3977
|
+
allowQueryJson: false
|
|
2203
3978
|
});
|
|
2204
3979
|
registerEntityCrudCommands(program, {
|
|
2205
3980
|
command: "accountability",
|
|
2206
3981
|
description: "Accountability operations",
|
|
2207
3982
|
resourcePath: "responsibilities",
|
|
2208
3983
|
rootKey: "responsibility",
|
|
2209
|
-
|
|
3984
|
+
requiredCreateFields: ["name", "member_id"],
|
|
3985
|
+
normalizeCreateBody: normalizeAccountabilityCreateBody,
|
|
3986
|
+
normalizeUpdateBody: normalizeAccountabilityUpdateBody,
|
|
3987
|
+
listParams: [],
|
|
3988
|
+
allowQueryJson: false
|
|
2210
3989
|
});
|
|
2211
3990
|
registerEntityCrudCommands(program, {
|
|
2212
3991
|
command: "kpis",
|
|
2213
3992
|
description: "KPI operations",
|
|
2214
3993
|
resourcePath: "smart_kpis",
|
|
2215
3994
|
rootKey: "smart_kpi",
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
"quarterly_objective_id",
|
|
2223
|
-
"smart_kpi_view_id",
|
|
2224
|
-
"team_id",
|
|
2225
|
-
"team_ids"
|
|
2226
|
-
]
|
|
3995
|
+
createMutationFactory: ({ body, organizationId }) => buildKpisCreateMutation({
|
|
3996
|
+
body,
|
|
3997
|
+
organizationId
|
|
3998
|
+
}),
|
|
3999
|
+
listParams: ["team_id", "member_id", "smart_kpi_view_id", "quarterly_objective_id"],
|
|
4000
|
+
allowQueryJson: false
|
|
2227
4001
|
});
|
|
2228
4002
|
registerEntityCrudCommands(program, {
|
|
2229
4003
|
command: "scorecard-groups",
|
|
2230
4004
|
description: "Scorecard group operations",
|
|
2231
4005
|
resourcePath: "measurable_groups",
|
|
2232
4006
|
rootKey: "measurable_group",
|
|
2233
|
-
listParams: ["include_archived", "member_id", "name", "sort", "team_ids", "term"]
|
|
4007
|
+
listParams: ["include_archived", "member_id", "name", "sort", "team_ids", "term"],
|
|
4008
|
+
allowQueryJson: false
|
|
2234
4009
|
});
|
|
2235
4010
|
registerEntityCrudCommands(program, {
|
|
2236
4011
|
command: "scorecards",
|
|
@@ -2238,6 +4013,7 @@ function registerSystemToolCommands(program) {
|
|
|
2238
4013
|
resourcePath: "measurables",
|
|
2239
4014
|
rootKey: "measurable",
|
|
2240
4015
|
requiredCreateFields: ["measurable_group_id"],
|
|
4016
|
+
normalizeCreateBody: normalizeScorecardsCreateBody,
|
|
2241
4017
|
listParams: [
|
|
2242
4018
|
"annual_objective_id",
|
|
2243
4019
|
"include_archived",
|
|
@@ -2249,21 +4025,24 @@ function registerSystemToolCommands(program) {
|
|
|
2249
4025
|
"sort",
|
|
2250
4026
|
"team_id",
|
|
2251
4027
|
"team_ids"
|
|
2252
|
-
]
|
|
4028
|
+
],
|
|
4029
|
+
allowQueryJson: false
|
|
2253
4030
|
});
|
|
2254
4031
|
registerEntityCrudCommands(program, {
|
|
2255
4032
|
command: "customers",
|
|
2256
4033
|
description: "CRM customer operations",
|
|
2257
4034
|
resourcePath: "customers",
|
|
2258
4035
|
rootKey: "customer",
|
|
2259
|
-
listParams: ["
|
|
4036
|
+
listParams: ["project_id", "meeting_id", "open", "team_id", "member_id"],
|
|
4037
|
+
allowQueryJson: false
|
|
2260
4038
|
});
|
|
2261
4039
|
registerEntityCrudCommands(program, {
|
|
2262
4040
|
command: "contacts",
|
|
2263
4041
|
description: "CRM contact operations",
|
|
2264
4042
|
resourcePath: "contacts",
|
|
2265
4043
|
rootKey: "contact",
|
|
2266
|
-
listParams: ["customer_id", "member_id",
|
|
4044
|
+
listParams: ["customer_id", "member_id"],
|
|
4045
|
+
allowQueryJson: false
|
|
2267
4046
|
});
|
|
2268
4047
|
}
|
|
2269
4048
|
|
|
@@ -2272,10 +4051,9 @@ var import_zod9 = require("zod");
|
|
|
2272
4051
|
var idSchema8 = import_zod9.z.string().min(1);
|
|
2273
4052
|
function registerTeamCommands(program) {
|
|
2274
4053
|
const teams = program.command("teams").description("Team operations");
|
|
2275
|
-
teams.command("list").option("--page <page>").option("--per <per>").
|
|
4054
|
+
teams.command("list").option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
|
|
2276
4055
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2277
4056
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2278
|
-
const extra = parseQueryJson(opts.queryJson ? String(opts.queryJson) : void 0);
|
|
2279
4057
|
await runGraphqlQueryCommand({
|
|
2280
4058
|
command: "teams.list",
|
|
2281
4059
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2283,8 +4061,7 @@ function registerTeamCommands(program) {
|
|
|
2283
4061
|
variables: normalizeGraphqlVariables2({
|
|
2284
4062
|
organization_id: organizationId,
|
|
2285
4063
|
page: opts.page,
|
|
2286
|
-
per: opts.per
|
|
2287
|
-
...extra
|
|
4064
|
+
per: opts.per
|
|
2288
4065
|
}),
|
|
2289
4066
|
isList: true
|
|
2290
4067
|
});
|
|
@@ -2339,6 +4116,103 @@ function registerTeamCommands(program) {
|
|
|
2339
4116
|
// src/commands/organizations.ts
|
|
2340
4117
|
var import_zod10 = require("zod");
|
|
2341
4118
|
var idSchema9 = import_zod10.z.string().min(1);
|
|
4119
|
+
function isRecord3(value) {
|
|
4120
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4121
|
+
}
|
|
4122
|
+
function ensureRootObject(body, rootKey) {
|
|
4123
|
+
const root = body[rootKey];
|
|
4124
|
+
if (!isRecord3(root)) {
|
|
4125
|
+
throw new CliError({
|
|
4126
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
4127
|
+
kind: "invalid_args",
|
|
4128
|
+
status: 400,
|
|
4129
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
4130
|
+
});
|
|
4131
|
+
}
|
|
4132
|
+
return { ...root };
|
|
4133
|
+
}
|
|
4134
|
+
function asNonEmptyString4(value) {
|
|
4135
|
+
if (typeof value !== "string") {
|
|
4136
|
+
return void 0;
|
|
4137
|
+
}
|
|
4138
|
+
const trimmed = value.trim();
|
|
4139
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
4140
|
+
}
|
|
4141
|
+
function normalizeOrganizationUpdateBody(body) {
|
|
4142
|
+
const organization = ensureRootObject(body, "organization");
|
|
4143
|
+
const detail = isRecord3(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
|
|
4144
|
+
const workspaceName = asNonEmptyString4(organization.workspace_name);
|
|
4145
|
+
if (workspaceName) {
|
|
4146
|
+
detail.workspace_name = workspaceName;
|
|
4147
|
+
}
|
|
4148
|
+
delete organization.workspace_name;
|
|
4149
|
+
if (Object.keys(detail).length > 0) {
|
|
4150
|
+
organization.organization_detail_attributes = detail;
|
|
4151
|
+
}
|
|
4152
|
+
return { organization };
|
|
4153
|
+
}
|
|
4154
|
+
function normalizeOrganizationMetaProfileUpdateBody(body) {
|
|
4155
|
+
const root = ensureRootObject(body, "organization_meta_profile");
|
|
4156
|
+
const profile = isRecord3(root.profile) ? { ...root.profile } : {};
|
|
4157
|
+
const title = asNonEmptyString4(root.title);
|
|
4158
|
+
if (title) {
|
|
4159
|
+
const companyIdentity = isRecord3(profile.company_identity) ? { ...profile.company_identity } : {};
|
|
4160
|
+
companyIdentity.one_sentence_summary = title;
|
|
4161
|
+
profile.company_identity = companyIdentity;
|
|
4162
|
+
}
|
|
4163
|
+
const unsupported = Object.keys(root).filter((key) => key !== "profile" && key !== "title");
|
|
4164
|
+
if (unsupported.length > 0) {
|
|
4165
|
+
throw new CliError({
|
|
4166
|
+
message: "Invalid organization_meta_profile update payload. Use organization_meta_profile.profile.<section>.<field>.",
|
|
4167
|
+
kind: "invalid_args",
|
|
4168
|
+
status: 400,
|
|
4169
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4170
|
+
details: { unsupportedKeys: unsupported, expectedRootKey: "profile" }
|
|
4171
|
+
});
|
|
4172
|
+
}
|
|
4173
|
+
if (Object.keys(profile).length === 0) {
|
|
4174
|
+
throw new CliError({
|
|
4175
|
+
message: "Missing required update fields for organization_meta_profile: profile.",
|
|
4176
|
+
kind: "invalid_args",
|
|
4177
|
+
status: 400,
|
|
4178
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4179
|
+
details: { requiredFields: ["profile"], rootKey: "organization_meta_profile" }
|
|
4180
|
+
});
|
|
4181
|
+
}
|
|
4182
|
+
return { organization_meta_profile: { profile } };
|
|
4183
|
+
}
|
|
4184
|
+
function normalizeKeyMetricMetaProfileUpdateBody(body) {
|
|
4185
|
+
const root = ensureRootObject(body, "key_metric_meta_profile");
|
|
4186
|
+
const profile = isRecord3(root.profile) ? { ...root.profile } : {};
|
|
4187
|
+
const annualRevenue = asNonEmptyString4(root.annual_revenue);
|
|
4188
|
+
if (annualRevenue) {
|
|
4189
|
+
const financial = isRecord3(profile.financial) ? { ...profile.financial } : {};
|
|
4190
|
+
financial.revenue = annualRevenue;
|
|
4191
|
+
profile.financial = financial;
|
|
4192
|
+
}
|
|
4193
|
+
const unsupported = Object.keys(root).filter(
|
|
4194
|
+
(key) => key !== "profile" && key !== "annual_revenue"
|
|
4195
|
+
);
|
|
4196
|
+
if (unsupported.length > 0) {
|
|
4197
|
+
throw new CliError({
|
|
4198
|
+
message: "Invalid key_metric_meta_profile update payload. Use key_metric_meta_profile.profile.<section>.<field>.",
|
|
4199
|
+
kind: "invalid_args",
|
|
4200
|
+
status: 400,
|
|
4201
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4202
|
+
details: { unsupportedKeys: unsupported, expectedRootKey: "profile" }
|
|
4203
|
+
});
|
|
4204
|
+
}
|
|
4205
|
+
if (Object.keys(profile).length === 0) {
|
|
4206
|
+
throw new CliError({
|
|
4207
|
+
message: "Missing required update fields for key_metric_meta_profile: profile.",
|
|
4208
|
+
kind: "invalid_args",
|
|
4209
|
+
status: 400,
|
|
4210
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4211
|
+
details: { requiredFields: ["profile"], rootKey: "key_metric_meta_profile" }
|
|
4212
|
+
});
|
|
4213
|
+
}
|
|
4214
|
+
return { key_metric_meta_profile: { profile } };
|
|
4215
|
+
}
|
|
2342
4216
|
function registerOrganizationCommands(program) {
|
|
2343
4217
|
const organizations = program.command("organizations").description("Organization operations");
|
|
2344
4218
|
organizations.command("show").option("--id <id>", "Organization ID (defaults to resolved organization context)").action(async (opts, cmd) => {
|
|
@@ -2360,7 +4234,8 @@ function registerOrganizationCommands(program) {
|
|
|
2360
4234
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2361
4235
|
const fallbackId = resolveOrganizationId(context.organizationId);
|
|
2362
4236
|
const id = idSchema9.parse(opts.id ?? fallbackId);
|
|
2363
|
-
const
|
|
4237
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "organization");
|
|
4238
|
+
const body = normalizeOrganizationUpdateBody(rawBody);
|
|
2364
4239
|
await runGraphqlMutationCommand({
|
|
2365
4240
|
command: "organizations.update",
|
|
2366
4241
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2394,10 +4269,11 @@ function registerOrganizationCommands(program) {
|
|
|
2394
4269
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2395
4270
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2396
4271
|
const id = idSchema9.parse(opts.id ?? organizationId);
|
|
2397
|
-
const
|
|
4272
|
+
const rawBody = __testables.normalizeBody(
|
|
2398
4273
|
String(opts.dataJson),
|
|
2399
4274
|
"organization_meta_profile"
|
|
2400
4275
|
);
|
|
4276
|
+
const body = normalizeOrganizationMetaProfileUpdateBody(rawBody);
|
|
2401
4277
|
await runGraphqlMutationCommand({
|
|
2402
4278
|
command: "organizations.meta-profile.update",
|
|
2403
4279
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2432,10 +4308,11 @@ function registerOrganizationCommands(program) {
|
|
|
2432
4308
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2433
4309
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2434
4310
|
const id = idSchema9.parse(opts.id ?? organizationId);
|
|
2435
|
-
const
|
|
4311
|
+
const rawBody = __testables.normalizeBody(
|
|
2436
4312
|
String(opts.dataJson),
|
|
2437
4313
|
"key_metric_meta_profile"
|
|
2438
4314
|
);
|
|
4315
|
+
const body = normalizeKeyMetricMetaProfileUpdateBody(rawBody);
|
|
2439
4316
|
await runGraphqlMutationCommand({
|
|
2440
4317
|
command: "organizations.key-metric-meta-profile.update",
|
|
2441
4318
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2452,36 +4329,131 @@ function registerOrganizationCommands(program) {
|
|
|
2452
4329
|
// src/commands/foundation.ts
|
|
2453
4330
|
var import_zod11 = require("zod");
|
|
2454
4331
|
var idSchema10 = import_zod11.z.string().min(1);
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
}
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
4332
|
+
var STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS = /* @__PURE__ */ new Set([
|
|
4333
|
+
"published_at",
|
|
4334
|
+
"profile",
|
|
4335
|
+
"strategic_plan_reads_attributes"
|
|
4336
|
+
]);
|
|
4337
|
+
var STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS = /* @__PURE__ */ new Set([
|
|
4338
|
+
"summary",
|
|
4339
|
+
"alignment_score",
|
|
4340
|
+
"published_at",
|
|
4341
|
+
"strategic_objective_reads_attributes"
|
|
4342
|
+
]);
|
|
4343
|
+
function isRecord4(value) {
|
|
4344
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4345
|
+
}
|
|
4346
|
+
function ensureRootObject2(body, rootKey) {
|
|
4347
|
+
const root = body[rootKey];
|
|
4348
|
+
if (!isRecord4(root)) {
|
|
4349
|
+
throw new CliError({
|
|
4350
|
+
message: `Invalid payload. Expected object at "${rootKey}".`,
|
|
4351
|
+
kind: "invalid_args",
|
|
4352
|
+
status: 400,
|
|
4353
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
4354
|
+
});
|
|
4355
|
+
}
|
|
4356
|
+
return { ...root };
|
|
4357
|
+
}
|
|
4358
|
+
function asNonEmptyString5(value) {
|
|
4359
|
+
if (typeof value !== "string") {
|
|
4360
|
+
return void 0;
|
|
4361
|
+
}
|
|
4362
|
+
const trimmed = value.trim();
|
|
4363
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
4364
|
+
}
|
|
4365
|
+
function normalizeStrategicPlanUpdateBody(body) {
|
|
4366
|
+
const strategicPlan = ensureRootObject2(body, "strategic_plan");
|
|
4367
|
+
const unsupported = Object.keys(strategicPlan).filter(
|
|
4368
|
+
(key) => !STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS.has(key)
|
|
4369
|
+
);
|
|
4370
|
+
if (unsupported.length > 0) {
|
|
4371
|
+
throw new CliError({
|
|
4372
|
+
message: "Invalid strategic_plan update payload. Allowed keys: published_at, profile, strategic_plan_reads_attributes.",
|
|
4373
|
+
kind: "invalid_args",
|
|
4374
|
+
status: 400,
|
|
4375
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4376
|
+
details: {
|
|
4377
|
+
unsupportedKeys: unsupported,
|
|
4378
|
+
allowedKeys: Array.from(STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS)
|
|
4379
|
+
}
|
|
4380
|
+
});
|
|
4381
|
+
}
|
|
4382
|
+
return { strategic_plan: strategicPlan };
|
|
4383
|
+
}
|
|
4384
|
+
function normalizeStrategicObjectiveUpdateBody(body) {
|
|
4385
|
+
const strategicObjective = ensureRootObject2(body, "strategic_objective");
|
|
4386
|
+
const title = asNonEmptyString5(strategicObjective.title);
|
|
4387
|
+
if (!asNonEmptyString5(strategicObjective.summary) && title) {
|
|
4388
|
+
strategicObjective.summary = title;
|
|
4389
|
+
}
|
|
4390
|
+
delete strategicObjective.title;
|
|
4391
|
+
const unsupported = Object.keys(strategicObjective).filter(
|
|
4392
|
+
(key) => !STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS.has(key)
|
|
4393
|
+
);
|
|
4394
|
+
if (unsupported.length > 0) {
|
|
4395
|
+
throw new CliError({
|
|
4396
|
+
message: "Invalid strategic_objective update payload. Allowed keys: summary, alignment_score, published_at, strategic_objective_reads_attributes.",
|
|
4397
|
+
kind: "invalid_args",
|
|
4398
|
+
status: 400,
|
|
4399
|
+
exitCode: EXIT_CODES.invalidArgs,
|
|
4400
|
+
details: {
|
|
4401
|
+
unsupportedKeys: unsupported,
|
|
4402
|
+
allowedKeys: Array.from(STRATEGIC_OBJECTIVE_ALLOWED_UPDATE_KEYS)
|
|
4403
|
+
}
|
|
4404
|
+
});
|
|
4405
|
+
}
|
|
4406
|
+
return { strategic_objective: strategicObjective };
|
|
4407
|
+
}
|
|
4408
|
+
function normalizeAnnualObjectiveCreateBody(body) {
|
|
4409
|
+
const annualObjective = ensureRootObject2(body, "annual_objective");
|
|
4410
|
+
const title = asNonEmptyString5(annualObjective.title);
|
|
4411
|
+
if (!asNonEmptyString5(annualObjective.name) && title) {
|
|
4412
|
+
annualObjective.name = title;
|
|
4413
|
+
}
|
|
4414
|
+
delete annualObjective.title;
|
|
4415
|
+
return { annual_objective: annualObjective };
|
|
4416
|
+
}
|
|
4417
|
+
function normalizeQuarterlyObjectiveCreateBody(body) {
|
|
4418
|
+
const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
|
|
4419
|
+
const title = asNonEmptyString5(quarterlyObjective.title);
|
|
4420
|
+
if (!asNonEmptyString5(quarterlyObjective.name) && title) {
|
|
4421
|
+
quarterlyObjective.name = title;
|
|
4422
|
+
}
|
|
4423
|
+
delete quarterlyObjective.title;
|
|
4424
|
+
return { quarterly_objective: quarterlyObjective };
|
|
4425
|
+
}
|
|
4426
|
+
function registerFoundationCommands(program) {
|
|
4427
|
+
const foundation = program.command("foundation").description("Foundation operations");
|
|
4428
|
+
const strategicPlans = foundation.command("strategic-plans").description("Strategic plan operations");
|
|
4429
|
+
const strategicObjectives = foundation.command("strategic-objectives").description("Strategic objective operations");
|
|
4430
|
+
strategicPlans.command("show").option("--id <id>", "Strategic plan ID (defaults to organization context)").option("--progress-scope <progressScope>").option("--all-progress <allProgress>").option("--all <all>").action(async (opts, cmd) => {
|
|
4431
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
4432
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
4433
|
+
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
4434
|
+
await runGraphqlQueryCommand({
|
|
4435
|
+
command: "foundation.strategic-plans.show",
|
|
4436
|
+
runtimeOptions: context.runtimeOptions,
|
|
4437
|
+
field: "strategic_plan",
|
|
4438
|
+
variables: normalizeGraphqlVariables2({
|
|
4439
|
+
organization_id: organizationId,
|
|
4440
|
+
id,
|
|
4441
|
+
progress_scope: opts.progressScope,
|
|
4442
|
+
all_progress: opts.allProgress,
|
|
4443
|
+
all: opts.all
|
|
4444
|
+
}),
|
|
4445
|
+
isShow: true
|
|
4446
|
+
});
|
|
4447
|
+
});
|
|
4448
|
+
strategicPlans.command("update").option("--id <id>", "Strategic plan ID (defaults to organization context)").requiredOption(
|
|
4449
|
+
"--data-json <dataJson>",
|
|
2479
4450
|
'JSON object for strategic_plan or {"strategic_plan": {...}}'
|
|
2480
4451
|
).action(async (opts, cmd) => {
|
|
2481
4452
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2482
4453
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2483
4454
|
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
2484
|
-
const
|
|
4455
|
+
const rawBody = __testables.normalizeBody(String(opts.dataJson), "strategic_plan");
|
|
4456
|
+
const body = normalizeStrategicPlanUpdateBody(rawBody);
|
|
2485
4457
|
await runGraphqlMutationCommand({
|
|
2486
4458
|
command: "foundation.strategic-plans.update",
|
|
2487
4459
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2518,10 +4490,11 @@ function registerFoundationCommands(program) {
|
|
|
2518
4490
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2519
4491
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2520
4492
|
const id = idSchema10.parse(opts.id ?? organizationId);
|
|
2521
|
-
const
|
|
4493
|
+
const rawBody = __testables.normalizeBody(
|
|
2522
4494
|
String(opts.dataJson),
|
|
2523
4495
|
"strategic_objective"
|
|
2524
4496
|
);
|
|
4497
|
+
const body = normalizeStrategicObjectiveUpdateBody(rawBody);
|
|
2525
4498
|
await runGraphqlMutationCommand({
|
|
2526
4499
|
command: "foundation.strategic-objectives.update",
|
|
2527
4500
|
runtimeOptions: context.runtimeOptions,
|
|
@@ -2538,16 +4511,20 @@ function registerFoundationCommands(program) {
|
|
|
2538
4511
|
description: "Foundation annual objective operations",
|
|
2539
4512
|
resourcePath: "annual_objectives",
|
|
2540
4513
|
rootKey: "annual_objective",
|
|
2541
|
-
requiredCreateFields: ["strategic_objective_id"],
|
|
2542
|
-
|
|
4514
|
+
requiredCreateFields: ["strategic_objective_id", "name"],
|
|
4515
|
+
normalizeCreateBody: normalizeAnnualObjectiveCreateBody,
|
|
4516
|
+
listParams: [],
|
|
4517
|
+
allowQueryJson: false
|
|
2543
4518
|
});
|
|
2544
4519
|
registerEntityCrudCommands(foundation, {
|
|
2545
4520
|
command: "quarterly-objectives",
|
|
2546
4521
|
description: "Foundation quarterly objective operations",
|
|
2547
4522
|
resourcePath: "quarterly_objectives",
|
|
2548
4523
|
rootKey: "quarterly_objective",
|
|
2549
|
-
requiredCreateFields: ["strategic_objective_id", "annual_objective_id"],
|
|
2550
|
-
|
|
4524
|
+
requiredCreateFields: ["strategic_objective_id", "annual_objective_id", "name"],
|
|
4525
|
+
normalizeCreateBody: normalizeQuarterlyObjectiveCreateBody,
|
|
4526
|
+
listParams: [],
|
|
4527
|
+
allowQueryJson: false
|
|
2551
4528
|
});
|
|
2552
4529
|
}
|
|
2553
4530
|
|
|
@@ -2650,6 +4627,20 @@ function normalizeListPayload(payload, parentKind, parentIdFallback, parentTyped
|
|
|
2650
4627
|
totalPages: record.totalPages ?? 1
|
|
2651
4628
|
};
|
|
2652
4629
|
}
|
|
4630
|
+
function normalizeSubtaskCreateBody(body) {
|
|
4631
|
+
const subtask = body.subtask;
|
|
4632
|
+
if (!subtask || typeof subtask !== "object" || Array.isArray(subtask)) {
|
|
4633
|
+
return body;
|
|
4634
|
+
}
|
|
4635
|
+
const subtaskRecord = subtask;
|
|
4636
|
+
const summary = typeof subtaskRecord.summary === "string" ? subtaskRecord.summary.trim() : void 0;
|
|
4637
|
+
const hasName = typeof subtaskRecord.name === "string" && subtaskRecord.name.trim().length > 0;
|
|
4638
|
+
if (!hasName && summary && summary.length > 0) {
|
|
4639
|
+
subtaskRecord.name = summary;
|
|
4640
|
+
}
|
|
4641
|
+
delete subtaskRecord.summary;
|
|
4642
|
+
return body;
|
|
4643
|
+
}
|
|
2653
4644
|
function registerChildCommands(program, config) {
|
|
2654
4645
|
const command = program.command(config.command).description(config.description);
|
|
2655
4646
|
command.command("list").requiredOption(`--${config.parentFlag} <${config.parentFlag}>`).option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
|
|
@@ -2680,7 +4671,10 @@ function registerChildCommands(program, config) {
|
|
|
2680
4671
|
command.command("create").requiredOption("--data-json <dataJson>").action(async (opts, cmd) => {
|
|
2681
4672
|
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
2682
4673
|
const organizationId = resolveOrganizationId(context.organizationId);
|
|
2683
|
-
|
|
4674
|
+
let body = normalizeBody2(String(opts.dataJson), config.rootKey);
|
|
4675
|
+
if (config.normalizeCreateBody) {
|
|
4676
|
+
body = config.normalizeCreateBody(body);
|
|
4677
|
+
}
|
|
2684
4678
|
assertRequiredParent(body, config.rootKey, config.parentFlag.replace(/-/g, "_"));
|
|
2685
4679
|
await runGraphqlMutationCommand({
|
|
2686
4680
|
command: `${config.command}.create`,
|
|
@@ -2743,7 +4737,8 @@ function registerChildEntityCommands(program) {
|
|
|
2743
4737
|
updateOperationName: "UpdateSubtask",
|
|
2744
4738
|
destroyOperationName: "DestroySubtask",
|
|
2745
4739
|
listSelectionSet: "{ data { id type name status taskId attributes } count currentPage totalPages }",
|
|
2746
|
-
listParentTypedField: "taskId"
|
|
4740
|
+
listParentTypedField: "taskId",
|
|
4741
|
+
normalizeCreateBody: normalizeSubtaskCreateBody
|
|
2747
4742
|
});
|
|
2748
4743
|
registerChildCommands(program, {
|
|
2749
4744
|
command: "milestones",
|
|
@@ -2887,7 +4882,7 @@ function registerNoteCommands(program) {
|
|
|
2887
4882
|
per: opts.per
|
|
2888
4883
|
}),
|
|
2889
4884
|
isList: true,
|
|
2890
|
-
selectionSet: "{ count currentPage totalPages data { id type name
|
|
4885
|
+
selectionSet: "{ count currentPage totalPages data { id type name slug firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId attributes } }"
|
|
2891
4886
|
});
|
|
2892
4887
|
});
|
|
2893
4888
|
notes.command("show").requiredOption("--id <id>").action(async (opts, cmd) => {
|
|
@@ -2904,7 +4899,7 @@ function registerNoteCommands(program) {
|
|
|
2904
4899
|
id
|
|
2905
4900
|
}),
|
|
2906
4901
|
isShow: true,
|
|
2907
|
-
selectionSet: "{ id type name
|
|
4902
|
+
selectionSet: "{ id type name slug firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId attributes }"
|
|
2908
4903
|
});
|
|
2909
4904
|
});
|
|
2910
4905
|
notes.command("update").requiredOption("--id <id>").option("--name <name>").option("--body <body>").option("--status <status>").action(async (opts, cmd) => {
|
|
@@ -3025,8 +5020,980 @@ function registerNoteCommands(program) {
|
|
|
3025
5020
|
});
|
|
3026
5021
|
}
|
|
3027
5022
|
|
|
5023
|
+
// src/commands/markdownTree.ts
|
|
5024
|
+
var import_zod14 = require("zod");
|
|
5025
|
+
var nonEmptyString2 = import_zod14.z.string().min(1);
|
|
5026
|
+
var nonNegativeInt = import_zod14.z.coerce.number().int().min(0);
|
|
5027
|
+
function addScopeOptions(command) {
|
|
5028
|
+
return command.requiredOption("--tool-key <toolKey>").requiredOption("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").option("--tree-view");
|
|
5029
|
+
}
|
|
5030
|
+
function parseScopeOptions(raw) {
|
|
5031
|
+
const parsed = {
|
|
5032
|
+
toolKey: nonEmptyString2.parse(raw.toolKey),
|
|
5033
|
+
nodeKey: nonEmptyString2.parse(raw.nodeKey)
|
|
5034
|
+
};
|
|
5035
|
+
if (typeof raw.parentId === "string" && raw.parentId.trim() !== "") {
|
|
5036
|
+
parsed.parentId = raw.parentId.trim();
|
|
5037
|
+
}
|
|
5038
|
+
if (typeof raw.recordId === "string" && raw.recordId.trim() !== "") {
|
|
5039
|
+
parsed.recordId = raw.recordId.trim();
|
|
5040
|
+
}
|
|
5041
|
+
if (typeof raw.memberId === "string" && raw.memberId.trim() !== "") {
|
|
5042
|
+
parsed.memberId = raw.memberId.trim();
|
|
5043
|
+
}
|
|
5044
|
+
if (typeof raw.teamId === "string" && raw.teamId.trim() !== "") {
|
|
5045
|
+
parsed.teamId = raw.teamId.trim();
|
|
5046
|
+
}
|
|
5047
|
+
if (typeof raw.contentType === "string" && raw.contentType.trim() !== "") {
|
|
5048
|
+
parsed.contentType = raw.contentType.trim();
|
|
5049
|
+
}
|
|
5050
|
+
if (raw.treeView === true) {
|
|
5051
|
+
parsed.treeView = true;
|
|
5052
|
+
}
|
|
5053
|
+
return parsed;
|
|
5054
|
+
}
|
|
5055
|
+
function baseNodeFields() {
|
|
5056
|
+
return [
|
|
5057
|
+
"toolKey",
|
|
5058
|
+
"nodeKey",
|
|
5059
|
+
"nodeKind",
|
|
5060
|
+
"runtimeLabel",
|
|
5061
|
+
"resolvedScope { parentId recordId memberId teamId contentType }",
|
|
5062
|
+
"isLeaf",
|
|
5063
|
+
"treeView",
|
|
5064
|
+
"details"
|
|
5065
|
+
].join(" ");
|
|
5066
|
+
}
|
|
5067
|
+
function buildChildSelection(depth) {
|
|
5068
|
+
if (depth <= 0) return "";
|
|
5069
|
+
const nested = buildChildSelection(depth - 1);
|
|
5070
|
+
return nested.length > 0 ? `children { ${baseNodeFields()} ${nested} }` : `children { ${baseNodeFields()} }`;
|
|
5071
|
+
}
|
|
5072
|
+
function buildNodeSelectionSet(depth) {
|
|
5073
|
+
const nested = buildChildSelection(depth);
|
|
5074
|
+
return nested.length > 0 ? `{ ${baseNodeFields()} ${nested} }` : `{ ${baseNodeFields()} }`;
|
|
5075
|
+
}
|
|
5076
|
+
function requireExplicitDepth(rawDepth) {
|
|
5077
|
+
if (rawDepth === void 0 || rawDepth === null || rawDepth === "") {
|
|
5078
|
+
throw new CliError({
|
|
5079
|
+
message: "Missing required --depth for markdown-tree subtree.",
|
|
5080
|
+
kind: "invalid_args",
|
|
5081
|
+
status: 400,
|
|
5082
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5083
|
+
});
|
|
5084
|
+
}
|
|
5085
|
+
return nonNegativeInt.parse(rawDepth);
|
|
5086
|
+
}
|
|
5087
|
+
function registerMarkdownTreeCommands(program) {
|
|
5088
|
+
const markdownTree = program.command("markdown-tree").description("Markdown tree traversal operations");
|
|
5089
|
+
markdownTree.command("root").option("--tree-view").action(async (opts, cmd) => {
|
|
5090
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5091
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5092
|
+
await runGraphqlQueryCommand({
|
|
5093
|
+
command: "markdown-tree.root",
|
|
5094
|
+
operationName: "MarkdownTreeRoot",
|
|
5095
|
+
runtimeOptions: context.runtimeOptions,
|
|
5096
|
+
field: "markdown_tree_root",
|
|
5097
|
+
variables: {
|
|
5098
|
+
organization_id: organizationId,
|
|
5099
|
+
tree_view: opts.treeView === true ? true : void 0
|
|
5100
|
+
},
|
|
5101
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
5102
|
+
isShow: true
|
|
5103
|
+
});
|
|
5104
|
+
});
|
|
5105
|
+
addScopeOptions(markdownTree.command("resolve")).action(async (opts, cmd) => {
|
|
5106
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5107
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5108
|
+
const scope = parseScopeOptions(opts);
|
|
5109
|
+
await runGraphqlQueryCommand({
|
|
5110
|
+
command: "markdown-tree.resolve",
|
|
5111
|
+
operationName: "MarkdownTreeNode",
|
|
5112
|
+
runtimeOptions: context.runtimeOptions,
|
|
5113
|
+
field: "markdown_tree_node",
|
|
5114
|
+
variables: {
|
|
5115
|
+
organization_id: organizationId,
|
|
5116
|
+
tool_key: scope.toolKey,
|
|
5117
|
+
node_key: scope.nodeKey,
|
|
5118
|
+
parent_id: scope.parentId,
|
|
5119
|
+
record_id: scope.recordId,
|
|
5120
|
+
member_id: scope.memberId,
|
|
5121
|
+
team_id: scope.teamId,
|
|
5122
|
+
content_type: scope.contentType,
|
|
5123
|
+
tree_view: scope.treeView
|
|
5124
|
+
},
|
|
5125
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
5126
|
+
isShow: true
|
|
5127
|
+
});
|
|
5128
|
+
});
|
|
5129
|
+
addScopeOptions(markdownTree.command("children")).action(async (opts, cmd) => {
|
|
5130
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5131
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5132
|
+
const scope = parseScopeOptions(opts);
|
|
5133
|
+
await runGraphqlQueryCommand({
|
|
5134
|
+
command: "markdown-tree.children",
|
|
5135
|
+
operationName: "MarkdownTreeChildren",
|
|
5136
|
+
runtimeOptions: context.runtimeOptions,
|
|
5137
|
+
field: "markdown_tree_children",
|
|
5138
|
+
variables: {
|
|
5139
|
+
organization_id: organizationId,
|
|
5140
|
+
tool_key: scope.toolKey,
|
|
5141
|
+
node_key: scope.nodeKey,
|
|
5142
|
+
parent_id: scope.parentId,
|
|
5143
|
+
record_id: scope.recordId,
|
|
5144
|
+
member_id: scope.memberId,
|
|
5145
|
+
team_id: scope.teamId,
|
|
5146
|
+
content_type: scope.contentType,
|
|
5147
|
+
tree_view: scope.treeView
|
|
5148
|
+
},
|
|
5149
|
+
selectionSet: buildNodeSelectionSet(1),
|
|
5150
|
+
isShow: true
|
|
5151
|
+
});
|
|
5152
|
+
});
|
|
5153
|
+
addScopeOptions(
|
|
5154
|
+
markdownTree.command("subtree").requiredOption("--depth <depth>")
|
|
5155
|
+
).action(async (opts, cmd) => {
|
|
5156
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5157
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5158
|
+
const scope = parseScopeOptions(opts);
|
|
5159
|
+
const depth = requireExplicitDepth(opts.depth);
|
|
5160
|
+
await runGraphqlQueryCommand({
|
|
5161
|
+
command: "markdown-tree.subtree",
|
|
5162
|
+
operationName: "MarkdownTreeSubtree",
|
|
5163
|
+
runtimeOptions: context.runtimeOptions,
|
|
5164
|
+
field: "markdown_tree_subtree",
|
|
5165
|
+
variables: {
|
|
5166
|
+
organization_id: organizationId,
|
|
5167
|
+
tool_key: scope.toolKey,
|
|
5168
|
+
node_key: scope.nodeKey,
|
|
5169
|
+
parent_id: scope.parentId,
|
|
5170
|
+
record_id: scope.recordId,
|
|
5171
|
+
member_id: scope.memberId,
|
|
5172
|
+
team_id: scope.teamId,
|
|
5173
|
+
content_type: scope.contentType,
|
|
5174
|
+
tree_view: scope.treeView,
|
|
5175
|
+
depth
|
|
5176
|
+
},
|
|
5177
|
+
selectionSet: buildNodeSelectionSet(depth + 1),
|
|
5178
|
+
isShow: true
|
|
5179
|
+
});
|
|
5180
|
+
});
|
|
5181
|
+
}
|
|
5182
|
+
|
|
5183
|
+
// src/commands/navigation.ts
|
|
5184
|
+
var import_zod15 = require("zod");
|
|
5185
|
+
|
|
5186
|
+
// src/internalOptions.ts
|
|
5187
|
+
var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
|
|
5188
|
+
function asRecord3(value) {
|
|
5189
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5190
|
+
return null;
|
|
5191
|
+
}
|
|
5192
|
+
return value;
|
|
5193
|
+
}
|
|
5194
|
+
function setInternalCliOptions(program, options) {
|
|
5195
|
+
if (!options) return;
|
|
5196
|
+
const target = program;
|
|
5197
|
+
target[INTERNAL_OPTIONS_KEY] = { ...options };
|
|
5198
|
+
}
|
|
5199
|
+
function getInternalCliOptions(command) {
|
|
5200
|
+
let current = command;
|
|
5201
|
+
while (current) {
|
|
5202
|
+
const record = asRecord3(current[INTERNAL_OPTIONS_KEY]);
|
|
5203
|
+
if (record) {
|
|
5204
|
+
return {
|
|
5205
|
+
enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
|
|
5206
|
+
};
|
|
5207
|
+
}
|
|
5208
|
+
current = current.parent ?? null;
|
|
5209
|
+
}
|
|
5210
|
+
return {};
|
|
5211
|
+
}
|
|
5212
|
+
|
|
5213
|
+
// src/commands/navigation.ts
|
|
5214
|
+
var nonEmpty = import_zod15.z.string().min(1);
|
|
5215
|
+
var nonNegativeInt2 = import_zod15.z.coerce.number().int().min(0);
|
|
5216
|
+
var MIGRATED_BRANCHES = ["directory", "projects", "knowledge"];
|
|
5217
|
+
function normalizeText(input) {
|
|
5218
|
+
if (typeof input !== "string") return "";
|
|
5219
|
+
return input.trim().toLowerCase().replace(/\s+/g, " ");
|
|
5220
|
+
}
|
|
5221
|
+
function toDisplay(input) {
|
|
5222
|
+
if (typeof input !== "string") return "";
|
|
5223
|
+
const value = input.trim();
|
|
5224
|
+
return value.length > 0 ? value : "";
|
|
5225
|
+
}
|
|
5226
|
+
function asObject(value) {
|
|
5227
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5228
|
+
}
|
|
5229
|
+
function asArray(value) {
|
|
5230
|
+
return Array.isArray(value) ? value : [];
|
|
5231
|
+
}
|
|
5232
|
+
function parseScopeFromOptions(raw) {
|
|
5233
|
+
const scope = {
|
|
5234
|
+
toolKey: nonEmpty.parse(raw.toolKey),
|
|
5235
|
+
nodeKey: nonEmpty.parse(raw.nodeKey)
|
|
5236
|
+
};
|
|
5237
|
+
if (typeof raw.parentId === "string" && raw.parentId.trim() !== "") {
|
|
5238
|
+
scope.parentId = raw.parentId.trim();
|
|
5239
|
+
}
|
|
5240
|
+
if (typeof raw.recordId === "string" && raw.recordId.trim() !== "") {
|
|
5241
|
+
scope.recordId = raw.recordId.trim();
|
|
5242
|
+
}
|
|
5243
|
+
if (typeof raw.memberId === "string" && raw.memberId.trim() !== "") {
|
|
5244
|
+
scope.memberId = raw.memberId.trim();
|
|
5245
|
+
}
|
|
5246
|
+
if (typeof raw.teamId === "string" && raw.teamId.trim() !== "") {
|
|
5247
|
+
scope.teamId = raw.teamId.trim();
|
|
5248
|
+
}
|
|
5249
|
+
if (typeof raw.contentType === "string" && raw.contentType.trim() !== "") {
|
|
5250
|
+
scope.contentType = raw.contentType.trim();
|
|
5251
|
+
}
|
|
5252
|
+
if (raw.treeView === true) {
|
|
5253
|
+
scope.treeView = true;
|
|
5254
|
+
}
|
|
5255
|
+
return scope;
|
|
5256
|
+
}
|
|
5257
|
+
function parseOptionalScopeFromOptions(raw) {
|
|
5258
|
+
if (typeof raw.toolKey !== "string" || raw.toolKey.trim() === "") {
|
|
5259
|
+
return null;
|
|
5260
|
+
}
|
|
5261
|
+
if (typeof raw.nodeKey !== "string" || raw.nodeKey.trim() === "") {
|
|
5262
|
+
return null;
|
|
5263
|
+
}
|
|
5264
|
+
return parseScopeFromOptions(raw);
|
|
5265
|
+
}
|
|
5266
|
+
function scopeFromCandidate(candidate, treeView) {
|
|
5267
|
+
const scopeObj = asObject(candidate.scope);
|
|
5268
|
+
const resolvedScopeObj = asObject(candidate.resolvedScope);
|
|
5269
|
+
const normalizedScope = Object.keys(scopeObj).length > 0 ? scopeObj : resolvedScopeObj;
|
|
5270
|
+
const toolKey = toDisplay(candidate.toolKey);
|
|
5271
|
+
const nodeKey = toDisplay(candidate.nodeKey);
|
|
5272
|
+
return {
|
|
5273
|
+
toolKey,
|
|
5274
|
+
nodeKey,
|
|
5275
|
+
parentId: toDisplay(normalizedScope.parentId) || void 0,
|
|
5276
|
+
recordId: toDisplay(normalizedScope.recordId) || void 0,
|
|
5277
|
+
memberId: toDisplay(normalizedScope.memberId) || void 0,
|
|
5278
|
+
teamId: toDisplay(normalizedScope.teamId) || void 0,
|
|
5279
|
+
contentType: toDisplay(normalizedScope.contentType) || void 0,
|
|
5280
|
+
treeView
|
|
5281
|
+
};
|
|
5282
|
+
}
|
|
5283
|
+
function notFoundEnvelope(params) {
|
|
5284
|
+
return {
|
|
5285
|
+
ok: false,
|
|
5286
|
+
command: params.command,
|
|
5287
|
+
status: 404,
|
|
5288
|
+
data: null,
|
|
5289
|
+
error: {
|
|
5290
|
+
code: "not_found",
|
|
5291
|
+
message: params.message,
|
|
5292
|
+
details: {}
|
|
5293
|
+
},
|
|
5294
|
+
meta: {
|
|
5295
|
+
requestId: params.requestId ?? "local_error"
|
|
5296
|
+
}
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
function ambiguityEnvelope(params) {
|
|
5300
|
+
return {
|
|
5301
|
+
ok: false,
|
|
5302
|
+
command: params.command,
|
|
5303
|
+
status: 409,
|
|
5304
|
+
data: null,
|
|
5305
|
+
error: {
|
|
5306
|
+
code: "ambiguous_match",
|
|
5307
|
+
message: params.message,
|
|
5308
|
+
details: {
|
|
5309
|
+
candidates: params.candidates
|
|
5310
|
+
}
|
|
5311
|
+
},
|
|
5312
|
+
meta: {
|
|
5313
|
+
requestId: params.requestId ?? "local_error"
|
|
5314
|
+
}
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5317
|
+
function unsupportedBranchEnvelope(params) {
|
|
5318
|
+
const tool = params.tool ?? "unknown";
|
|
5319
|
+
return {
|
|
5320
|
+
ok: false,
|
|
5321
|
+
command: params.command,
|
|
5322
|
+
status: 400,
|
|
5323
|
+
data: null,
|
|
5324
|
+
error: {
|
|
5325
|
+
code: "unsupported_branch",
|
|
5326
|
+
message: `This branch isn't migrated to markdown-tree yet: ${tool}. Try directory/projects/knowledge.`,
|
|
5327
|
+
details: {
|
|
5328
|
+
tool,
|
|
5329
|
+
migratedBranches: [...MIGRATED_BRANCHES],
|
|
5330
|
+
originalError: params.originalError ?? null
|
|
5331
|
+
}
|
|
5332
|
+
},
|
|
5333
|
+
meta: {
|
|
5334
|
+
requestId: params.requestId ?? "local_error"
|
|
5335
|
+
}
|
|
5336
|
+
};
|
|
5337
|
+
}
|
|
5338
|
+
function parseToolFromGraphqlError(errorBody) {
|
|
5339
|
+
const errorObj = asObject(errorBody);
|
|
5340
|
+
const details = asObject(errorObj.details);
|
|
5341
|
+
const errors = asArray(details.errors);
|
|
5342
|
+
for (const item of errors) {
|
|
5343
|
+
const message = toDisplay(item.message);
|
|
5344
|
+
if (message === "") continue;
|
|
5345
|
+
const match = message.match(/tool_key=([a-zA-Z0-9_]+)/);
|
|
5346
|
+
if (match?.[1]) {
|
|
5347
|
+
return match[1];
|
|
5348
|
+
}
|
|
5349
|
+
}
|
|
5350
|
+
return null;
|
|
5351
|
+
}
|
|
5352
|
+
function toolHintFromPathLike(value) {
|
|
5353
|
+
const text = toDisplay(value);
|
|
5354
|
+
if (text === "") return null;
|
|
5355
|
+
const [first] = text.split("/");
|
|
5356
|
+
return first ? first.trim() : null;
|
|
5357
|
+
}
|
|
5358
|
+
function unsupportedToolFromHints(params) {
|
|
5359
|
+
const fromError = parseToolFromGraphqlError(params.envelopeError);
|
|
5360
|
+
if (fromError) return fromError;
|
|
5361
|
+
return toDisplay(params.explicitTool) || toolHintFromPathLike(params.underPath) || toolHintFromPathLike(params.queryLike) || "unknown";
|
|
5362
|
+
}
|
|
5363
|
+
async function requestTraversal(params) {
|
|
5364
|
+
const config = getConfig(params.runtimeOptions);
|
|
5365
|
+
const result = await graphqlRequest({
|
|
5366
|
+
config,
|
|
5367
|
+
command: params.command,
|
|
5368
|
+
operationName: params.operationName,
|
|
5369
|
+
operationType: "query",
|
|
5370
|
+
field: params.field,
|
|
5371
|
+
variables: params.variables,
|
|
5372
|
+
selectionSet: buildNodeSelectionSet(params.depth),
|
|
5373
|
+
isShow: true
|
|
5374
|
+
});
|
|
5375
|
+
if (!result.envelope.ok) {
|
|
5376
|
+
if (result.envelope.error?.code === "unsupported_branch") {
|
|
5377
|
+
printEnvelopeAndExit({
|
|
5378
|
+
envelope: unsupportedBranchEnvelope({
|
|
5379
|
+
command: params.command,
|
|
5380
|
+
requestId: result.envelope.meta.requestId,
|
|
5381
|
+
tool: unsupportedToolFromHints({
|
|
5382
|
+
explicitTool: params.variables.tool_key,
|
|
5383
|
+
envelopeError: result.envelope.error
|
|
5384
|
+
}),
|
|
5385
|
+
originalError: asObject(result.envelope.error)
|
|
5386
|
+
}),
|
|
5387
|
+
exitCode: result.exitCode
|
|
5388
|
+
});
|
|
5389
|
+
}
|
|
5390
|
+
printEnvelopeAndExit({
|
|
5391
|
+
envelope: result.envelope,
|
|
5392
|
+
exitCode: result.exitCode
|
|
5393
|
+
});
|
|
5394
|
+
}
|
|
5395
|
+
const data = asObject(result.envelope.data);
|
|
5396
|
+
return asObject(data[params.field]);
|
|
5397
|
+
}
|
|
5398
|
+
function findSelectionSet() {
|
|
5399
|
+
return `{
|
|
5400
|
+
query
|
|
5401
|
+
underPath
|
|
5402
|
+
candidates {
|
|
5403
|
+
label
|
|
5404
|
+
canonicalPath
|
|
5405
|
+
toolKey
|
|
5406
|
+
nodeKey
|
|
5407
|
+
nodeKind
|
|
5408
|
+
isLeaf
|
|
5409
|
+
scope { parentId recordId memberId teamId contentType }
|
|
5410
|
+
resolvedScope { parentId recordId memberId teamId contentType }
|
|
5411
|
+
matchType
|
|
5412
|
+
rank
|
|
5413
|
+
aliasMatched
|
|
5414
|
+
breadcrumb
|
|
5415
|
+
}
|
|
5416
|
+
}`;
|
|
5417
|
+
}
|
|
5418
|
+
async function requestFind(params) {
|
|
5419
|
+
const config = getConfig(params.runtimeOptions);
|
|
5420
|
+
const result = await graphqlRequest({
|
|
5421
|
+
config,
|
|
5422
|
+
command: params.command,
|
|
5423
|
+
operationName: "MarkdownTreeFind",
|
|
5424
|
+
operationType: "query",
|
|
5425
|
+
field: "markdown_tree_find",
|
|
5426
|
+
variables: {
|
|
5427
|
+
organization_id: params.organizationId,
|
|
5428
|
+
query: params.query,
|
|
5429
|
+
under_path: params.underPath,
|
|
5430
|
+
tool_key: params.toolKey,
|
|
5431
|
+
node_key: params.nodeKey,
|
|
5432
|
+
limit: params.limit
|
|
5433
|
+
},
|
|
5434
|
+
selectionSet: findSelectionSet(),
|
|
5435
|
+
isShow: true
|
|
5436
|
+
});
|
|
5437
|
+
if (!result.envelope.ok) {
|
|
5438
|
+
if (result.envelope.error?.code === "unsupported_branch") {
|
|
5439
|
+
printEnvelopeAndExit({
|
|
5440
|
+
envelope: unsupportedBranchEnvelope({
|
|
5441
|
+
command: params.command,
|
|
5442
|
+
requestId: result.envelope.meta.requestId,
|
|
5443
|
+
tool: unsupportedToolFromHints({
|
|
5444
|
+
explicitTool: params.toolKey,
|
|
5445
|
+
underPath: params.underPath,
|
|
5446
|
+
queryLike: params.query,
|
|
5447
|
+
envelopeError: result.envelope.error
|
|
5448
|
+
}),
|
|
5449
|
+
originalError: asObject(result.envelope.error)
|
|
5450
|
+
}),
|
|
5451
|
+
exitCode: result.exitCode
|
|
5452
|
+
});
|
|
5453
|
+
}
|
|
5454
|
+
printEnvelopeAndExit({
|
|
5455
|
+
envelope: result.envelope,
|
|
5456
|
+
exitCode: result.exitCode
|
|
5457
|
+
});
|
|
5458
|
+
}
|
|
5459
|
+
const data = asObject(result.envelope.data);
|
|
5460
|
+
const payload = asObject(data.markdown_tree_find);
|
|
5461
|
+
return {
|
|
5462
|
+
...payload,
|
|
5463
|
+
candidates: asArray(payload.candidates)
|
|
5464
|
+
};
|
|
5465
|
+
}
|
|
5466
|
+
function matchTypePrecedence(candidate) {
|
|
5467
|
+
const matchType = toDisplay(candidate.matchType).toLowerCase();
|
|
5468
|
+
const order = {
|
|
5469
|
+
exact_label: 0,
|
|
5470
|
+
exact_path: 1,
|
|
5471
|
+
prefix_label: 2,
|
|
5472
|
+
path_prefix: 3,
|
|
5473
|
+
path_fragment: 4,
|
|
5474
|
+
alias_match: 5,
|
|
5475
|
+
fuzzy: 6
|
|
5476
|
+
};
|
|
5477
|
+
return order[matchType] ?? Number.POSITIVE_INFINITY;
|
|
5478
|
+
}
|
|
5479
|
+
function isTopCandidateDominant(candidates) {
|
|
5480
|
+
if (candidates.length <= 1) {
|
|
5481
|
+
return true;
|
|
5482
|
+
}
|
|
5483
|
+
const first = candidates[0];
|
|
5484
|
+
const second = candidates[1];
|
|
5485
|
+
if (typeof first.rank === "number" && typeof second.rank === "number") {
|
|
5486
|
+
return first.rank < second.rank;
|
|
5487
|
+
}
|
|
5488
|
+
const firstMatch = matchTypePrecedence(first);
|
|
5489
|
+
const secondMatch = matchTypePrecedence(second);
|
|
5490
|
+
if (Number.isFinite(firstMatch) || Number.isFinite(secondMatch)) {
|
|
5491
|
+
return firstMatch < secondMatch;
|
|
5492
|
+
}
|
|
5493
|
+
return false;
|
|
5494
|
+
}
|
|
5495
|
+
function findExactPathMatches(candidates, path) {
|
|
5496
|
+
const target = normalizeText(path);
|
|
5497
|
+
if (target === "") return [];
|
|
5498
|
+
return candidates.filter((candidate) => {
|
|
5499
|
+
const canonicalPath = toDisplay(candidate.canonicalPath);
|
|
5500
|
+
return normalizeText(canonicalPath) === target;
|
|
5501
|
+
});
|
|
5502
|
+
}
|
|
5503
|
+
async function resolvePathScope(params) {
|
|
5504
|
+
const findPayload = await requestFind({
|
|
5505
|
+
command: params.command,
|
|
5506
|
+
runtimeOptions: params.runtimeOptions,
|
|
5507
|
+
organizationId: params.organizationId,
|
|
5508
|
+
query: params.path,
|
|
5509
|
+
underPath: params.underPath,
|
|
5510
|
+
limit: 25
|
|
5511
|
+
});
|
|
5512
|
+
const exactMatches = findExactPathMatches(findPayload.candidates, params.path);
|
|
5513
|
+
if (exactMatches.length === 1) {
|
|
5514
|
+
return {
|
|
5515
|
+
scope: scopeFromCandidate(exactMatches[0], params.treeView),
|
|
5516
|
+
match: exactMatches[0],
|
|
5517
|
+
ambiguous: []
|
|
5518
|
+
};
|
|
5519
|
+
}
|
|
5520
|
+
if (exactMatches.length > 1) {
|
|
5521
|
+
return {
|
|
5522
|
+
ambiguous: exactMatches.slice(0, 10)
|
|
5523
|
+
};
|
|
5524
|
+
}
|
|
5525
|
+
return {
|
|
5526
|
+
ambiguous: []
|
|
5527
|
+
};
|
|
5528
|
+
}
|
|
5529
|
+
function isMultiWordQuery(query) {
|
|
5530
|
+
const parts = query.trim().split(/\s+/).filter((part) => part.length > 0);
|
|
5531
|
+
return parts.length > 1;
|
|
5532
|
+
}
|
|
5533
|
+
function reduceMultiWordQuery(query) {
|
|
5534
|
+
const tokens = query.trim().split(/\s+/).map((token) => token.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")).filter((token) => token.length > 0);
|
|
5535
|
+
if (tokens.length <= 1) return null;
|
|
5536
|
+
const meaningful = tokens.filter((token) => token.length >= 3);
|
|
5537
|
+
const selected = meaningful.length > 0 ? meaningful[meaningful.length - 1] : tokens[tokens.length - 1];
|
|
5538
|
+
return selected ?? null;
|
|
5539
|
+
}
|
|
5540
|
+
function registerNavigationCommands(program) {
|
|
5541
|
+
program.command("find <query>").description("Find nodes via backend-native markdown tree discovery").option("--under <under>").option("--path <path>").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--limit <limit>").action(async (query, opts, cmd) => {
|
|
5542
|
+
const globals = cmd.optsWithGlobals();
|
|
5543
|
+
const context = await resolveCommandContext(globals);
|
|
5544
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5545
|
+
const internalOptions = getInternalCliOptions(cmd);
|
|
5546
|
+
const limit = typeof opts.limit === "string" && opts.limit.trim() !== "" ? Math.max(1, Number.parseInt(opts.limit, 10) || 20) : 20;
|
|
5547
|
+
const underPath = typeof opts.under === "string" && opts.under.trim() !== "" ? opts.under.trim() : typeof opts.path === "string" && opts.path.trim() !== "" ? opts.path.trim() : void 0;
|
|
5548
|
+
const payload = await requestFind({
|
|
5549
|
+
command: "find",
|
|
5550
|
+
runtimeOptions: context.runtimeOptions,
|
|
5551
|
+
organizationId,
|
|
5552
|
+
query,
|
|
5553
|
+
underPath,
|
|
5554
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
5555
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
5556
|
+
limit
|
|
5557
|
+
});
|
|
5558
|
+
let finalPayload = payload;
|
|
5559
|
+
let assistantRecovery;
|
|
5560
|
+
if (internalOptions.enableRetryOnEmptyPhrase === true && payload.candidates.length === 0 && isMultiWordQuery(query)) {
|
|
5561
|
+
const retryQuery = reduceMultiWordQuery(query);
|
|
5562
|
+
if (retryQuery && normalizeText(retryQuery) !== normalizeText(query)) {
|
|
5563
|
+
finalPayload = await requestFind({
|
|
5564
|
+
command: "find",
|
|
5565
|
+
runtimeOptions: context.runtimeOptions,
|
|
5566
|
+
organizationId,
|
|
5567
|
+
query: retryQuery,
|
|
5568
|
+
underPath,
|
|
5569
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
5570
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
5571
|
+
limit
|
|
5572
|
+
});
|
|
5573
|
+
assistantRecovery = {
|
|
5574
|
+
triggered: true,
|
|
5575
|
+
originalQuery: query,
|
|
5576
|
+
retryQuery,
|
|
5577
|
+
reason: "empty_multi_word_query"
|
|
5578
|
+
};
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
printEnvelopeAndExit({
|
|
5582
|
+
envelope: {
|
|
5583
|
+
ok: true,
|
|
5584
|
+
command: "find",
|
|
5585
|
+
status: 200,
|
|
5586
|
+
data: assistantRecovery ? {
|
|
5587
|
+
...finalPayload,
|
|
5588
|
+
assistantRecovery
|
|
5589
|
+
} : finalPayload,
|
|
5590
|
+
error: null,
|
|
5591
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5592
|
+
}
|
|
5593
|
+
});
|
|
5594
|
+
});
|
|
5595
|
+
program.command("open <name>").description("Resolve one node by backend discovery").option("--under <under>").option("--path <path>").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--limit <limit>").option("--tree-view").action(async (name, opts, cmd) => {
|
|
5596
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5597
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5598
|
+
const limit = typeof opts.limit === "string" && opts.limit.trim() !== "" ? Math.max(1, Number.parseInt(opts.limit, 10) || 10) : 10;
|
|
5599
|
+
const underPath = typeof opts.under === "string" && opts.under.trim() !== "" ? opts.under.trim() : typeof opts.path === "string" && opts.path.trim() !== "" ? opts.path.trim() : void 0;
|
|
5600
|
+
const payload = await requestFind({
|
|
5601
|
+
command: "open",
|
|
5602
|
+
runtimeOptions: context.runtimeOptions,
|
|
5603
|
+
organizationId,
|
|
5604
|
+
query: name,
|
|
5605
|
+
underPath,
|
|
5606
|
+
toolKey: typeof opts.toolKey === "string" ? opts.toolKey : void 0,
|
|
5607
|
+
nodeKey: typeof opts.nodeKey === "string" ? opts.nodeKey : void 0,
|
|
5608
|
+
limit
|
|
5609
|
+
});
|
|
5610
|
+
const candidates = payload.candidates;
|
|
5611
|
+
if (candidates.length === 0) {
|
|
5612
|
+
printEnvelopeAndExit({
|
|
5613
|
+
envelope: notFoundEnvelope({
|
|
5614
|
+
command: "open",
|
|
5615
|
+
message: `No node matched "${name}".`
|
|
5616
|
+
}),
|
|
5617
|
+
exitCode: EXIT_CODES.notFound
|
|
5618
|
+
});
|
|
5619
|
+
}
|
|
5620
|
+
if (candidates.length > 1 && !isTopCandidateDominant(candidates)) {
|
|
5621
|
+
printEnvelopeAndExit({
|
|
5622
|
+
envelope: ambiguityEnvelope({
|
|
5623
|
+
command: "open",
|
|
5624
|
+
message: `Multiple nodes matched "${name}".`,
|
|
5625
|
+
candidates: candidates.slice(0, 10)
|
|
5626
|
+
}),
|
|
5627
|
+
exitCode: EXIT_CODES.generic
|
|
5628
|
+
});
|
|
5629
|
+
}
|
|
5630
|
+
const selected = candidates[0];
|
|
5631
|
+
const scope = scopeFromCandidate(selected, opts.treeView === true);
|
|
5632
|
+
const node = await requestTraversal({
|
|
5633
|
+
command: "open",
|
|
5634
|
+
runtimeOptions: context.runtimeOptions,
|
|
5635
|
+
operationName: "MarkdownTreeNode",
|
|
5636
|
+
field: "markdown_tree_node",
|
|
5637
|
+
variables: {
|
|
5638
|
+
organization_id: organizationId,
|
|
5639
|
+
tool_key: scope.toolKey,
|
|
5640
|
+
node_key: scope.nodeKey,
|
|
5641
|
+
parent_id: scope.parentId,
|
|
5642
|
+
record_id: scope.recordId,
|
|
5643
|
+
member_id: scope.memberId,
|
|
5644
|
+
team_id: scope.teamId,
|
|
5645
|
+
content_type: scope.contentType,
|
|
5646
|
+
tree_view: scope.treeView
|
|
5647
|
+
},
|
|
5648
|
+
depth: 1
|
|
5649
|
+
});
|
|
5650
|
+
printEnvelopeAndExit({
|
|
5651
|
+
envelope: {
|
|
5652
|
+
ok: true,
|
|
5653
|
+
command: "open",
|
|
5654
|
+
status: 200,
|
|
5655
|
+
data: {
|
|
5656
|
+
match: selected,
|
|
5657
|
+
node
|
|
5658
|
+
},
|
|
5659
|
+
error: null,
|
|
5660
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5661
|
+
}
|
|
5662
|
+
});
|
|
5663
|
+
});
|
|
5664
|
+
program.command("ls [query]").description("List direct children for a target").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (query, opts, cmd) => {
|
|
5665
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5666
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5667
|
+
let scope = null;
|
|
5668
|
+
let pathMatch = null;
|
|
5669
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5670
|
+
const resolved = await resolvePathScope({
|
|
5671
|
+
command: "ls",
|
|
5672
|
+
runtimeOptions: context.runtimeOptions,
|
|
5673
|
+
organizationId,
|
|
5674
|
+
path: opts.path,
|
|
5675
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5676
|
+
treeView: opts.treeView === true
|
|
5677
|
+
});
|
|
5678
|
+
if (!resolved.scope) {
|
|
5679
|
+
if (resolved.ambiguous.length > 0) {
|
|
5680
|
+
printEnvelopeAndExit({
|
|
5681
|
+
envelope: ambiguityEnvelope({
|
|
5682
|
+
command: "ls",
|
|
5683
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5684
|
+
candidates: resolved.ambiguous
|
|
5685
|
+
}),
|
|
5686
|
+
exitCode: EXIT_CODES.generic
|
|
5687
|
+
});
|
|
5688
|
+
}
|
|
5689
|
+
printEnvelopeAndExit({
|
|
5690
|
+
envelope: notFoundEnvelope({
|
|
5691
|
+
command: "ls",
|
|
5692
|
+
message: `Path "${opts.path}" was not found.`
|
|
5693
|
+
}),
|
|
5694
|
+
exitCode: EXIT_CODES.notFound
|
|
5695
|
+
});
|
|
5696
|
+
}
|
|
5697
|
+
scope = resolved.scope;
|
|
5698
|
+
pathMatch = resolved.match ?? null;
|
|
5699
|
+
} else {
|
|
5700
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5701
|
+
}
|
|
5702
|
+
if (!scope) {
|
|
5703
|
+
printEnvelopeAndExit({
|
|
5704
|
+
envelope: {
|
|
5705
|
+
ok: false,
|
|
5706
|
+
command: "ls",
|
|
5707
|
+
status: 400,
|
|
5708
|
+
data: null,
|
|
5709
|
+
error: {
|
|
5710
|
+
code: "invalid_args",
|
|
5711
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5712
|
+
details: {}
|
|
5713
|
+
},
|
|
5714
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5715
|
+
},
|
|
5716
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5717
|
+
});
|
|
5718
|
+
}
|
|
5719
|
+
const node = await requestTraversal({
|
|
5720
|
+
command: "ls",
|
|
5721
|
+
runtimeOptions: context.runtimeOptions,
|
|
5722
|
+
operationName: "MarkdownTreeChildren",
|
|
5723
|
+
field: "markdown_tree_children",
|
|
5724
|
+
variables: {
|
|
5725
|
+
organization_id: organizationId,
|
|
5726
|
+
tool_key: scope.toolKey,
|
|
5727
|
+
node_key: scope.nodeKey,
|
|
5728
|
+
parent_id: scope.parentId,
|
|
5729
|
+
record_id: scope.recordId,
|
|
5730
|
+
member_id: scope.memberId,
|
|
5731
|
+
team_id: scope.teamId,
|
|
5732
|
+
content_type: scope.contentType,
|
|
5733
|
+
tree_view: scope.treeView
|
|
5734
|
+
},
|
|
5735
|
+
depth: 1
|
|
5736
|
+
});
|
|
5737
|
+
const children = asArray(node.children);
|
|
5738
|
+
const filtered = typeof query === "string" && query.trim() !== "" ? children.filter(
|
|
5739
|
+
(child) => normalizeText(child.runtimeLabel).includes(normalizeText(query))
|
|
5740
|
+
) : children;
|
|
5741
|
+
printEnvelopeAndExit({
|
|
5742
|
+
envelope: {
|
|
5743
|
+
ok: true,
|
|
5744
|
+
command: "ls",
|
|
5745
|
+
status: 200,
|
|
5746
|
+
data: {
|
|
5747
|
+
target: pathMatch,
|
|
5748
|
+
children: filtered
|
|
5749
|
+
},
|
|
5750
|
+
error: null,
|
|
5751
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5752
|
+
}
|
|
5753
|
+
});
|
|
5754
|
+
});
|
|
5755
|
+
program.command("cat").description("Read one node").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (opts, cmd) => {
|
|
5756
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5757
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5758
|
+
let scope = null;
|
|
5759
|
+
let pathMatch = null;
|
|
5760
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5761
|
+
const resolved = await resolvePathScope({
|
|
5762
|
+
command: "cat",
|
|
5763
|
+
runtimeOptions: context.runtimeOptions,
|
|
5764
|
+
organizationId,
|
|
5765
|
+
path: opts.path,
|
|
5766
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5767
|
+
treeView: opts.treeView === true
|
|
5768
|
+
});
|
|
5769
|
+
if (!resolved.scope) {
|
|
5770
|
+
if (resolved.ambiguous.length > 0) {
|
|
5771
|
+
printEnvelopeAndExit({
|
|
5772
|
+
envelope: ambiguityEnvelope({
|
|
5773
|
+
command: "cat",
|
|
5774
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5775
|
+
candidates: resolved.ambiguous
|
|
5776
|
+
}),
|
|
5777
|
+
exitCode: EXIT_CODES.generic
|
|
5778
|
+
});
|
|
5779
|
+
}
|
|
5780
|
+
printEnvelopeAndExit({
|
|
5781
|
+
envelope: notFoundEnvelope({
|
|
5782
|
+
command: "cat",
|
|
5783
|
+
message: `Path "${opts.path}" was not found.`
|
|
5784
|
+
}),
|
|
5785
|
+
exitCode: EXIT_CODES.notFound
|
|
5786
|
+
});
|
|
5787
|
+
}
|
|
5788
|
+
scope = resolved.scope;
|
|
5789
|
+
pathMatch = resolved.match ?? null;
|
|
5790
|
+
} else {
|
|
5791
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5792
|
+
}
|
|
5793
|
+
if (!scope) {
|
|
5794
|
+
printEnvelopeAndExit({
|
|
5795
|
+
envelope: {
|
|
5796
|
+
ok: false,
|
|
5797
|
+
command: "cat",
|
|
5798
|
+
status: 400,
|
|
5799
|
+
data: null,
|
|
5800
|
+
error: {
|
|
5801
|
+
code: "invalid_args",
|
|
5802
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5803
|
+
details: {}
|
|
5804
|
+
},
|
|
5805
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5806
|
+
},
|
|
5807
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5808
|
+
});
|
|
5809
|
+
}
|
|
5810
|
+
const node = await requestTraversal({
|
|
5811
|
+
command: "cat",
|
|
5812
|
+
runtimeOptions: context.runtimeOptions,
|
|
5813
|
+
operationName: "MarkdownTreeNode",
|
|
5814
|
+
field: "markdown_tree_node",
|
|
5815
|
+
variables: {
|
|
5816
|
+
organization_id: organizationId,
|
|
5817
|
+
tool_key: scope.toolKey,
|
|
5818
|
+
node_key: scope.nodeKey,
|
|
5819
|
+
parent_id: scope.parentId,
|
|
5820
|
+
record_id: scope.recordId,
|
|
5821
|
+
member_id: scope.memberId,
|
|
5822
|
+
team_id: scope.teamId,
|
|
5823
|
+
content_type: scope.contentType,
|
|
5824
|
+
tree_view: scope.treeView
|
|
5825
|
+
},
|
|
5826
|
+
depth: 1
|
|
5827
|
+
});
|
|
5828
|
+
printEnvelopeAndExit({
|
|
5829
|
+
envelope: {
|
|
5830
|
+
ok: true,
|
|
5831
|
+
command: "cat",
|
|
5832
|
+
status: 200,
|
|
5833
|
+
data: {
|
|
5834
|
+
target: pathMatch,
|
|
5835
|
+
node
|
|
5836
|
+
},
|
|
5837
|
+
error: null,
|
|
5838
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5839
|
+
}
|
|
5840
|
+
});
|
|
5841
|
+
});
|
|
5842
|
+
program.command("tree").description("Read bounded subtree").requiredOption("--depth <depth>").option("--path <path>").option("--under <under>").option("--tree-view").option("--tool-key <toolKey>").option("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").action(async (opts, cmd) => {
|
|
5843
|
+
const context = await resolveCommandContext(cmd.optsWithGlobals());
|
|
5844
|
+
const organizationId = resolveOrganizationId(context.organizationId);
|
|
5845
|
+
const depth = nonNegativeInt2.parse(opts.depth);
|
|
5846
|
+
let scope = null;
|
|
5847
|
+
let pathMatch = null;
|
|
5848
|
+
if (typeof opts.path === "string" && opts.path.trim() !== "") {
|
|
5849
|
+
const resolved = await resolvePathScope({
|
|
5850
|
+
command: "tree",
|
|
5851
|
+
runtimeOptions: context.runtimeOptions,
|
|
5852
|
+
organizationId,
|
|
5853
|
+
path: opts.path,
|
|
5854
|
+
underPath: typeof opts.under === "string" ? opts.under : void 0,
|
|
5855
|
+
treeView: opts.treeView === true
|
|
5856
|
+
});
|
|
5857
|
+
if (!resolved.scope) {
|
|
5858
|
+
if (resolved.ambiguous.length > 0) {
|
|
5859
|
+
printEnvelopeAndExit({
|
|
5860
|
+
envelope: ambiguityEnvelope({
|
|
5861
|
+
command: "tree",
|
|
5862
|
+
message: `Path "${opts.path}" is ambiguous.`,
|
|
5863
|
+
candidates: resolved.ambiguous
|
|
5864
|
+
}),
|
|
5865
|
+
exitCode: EXIT_CODES.generic
|
|
5866
|
+
});
|
|
5867
|
+
}
|
|
5868
|
+
printEnvelopeAndExit({
|
|
5869
|
+
envelope: notFoundEnvelope({
|
|
5870
|
+
command: "tree",
|
|
5871
|
+
message: `Path "${opts.path}" was not found.`
|
|
5872
|
+
}),
|
|
5873
|
+
exitCode: EXIT_CODES.notFound
|
|
5874
|
+
});
|
|
5875
|
+
}
|
|
5876
|
+
scope = resolved.scope;
|
|
5877
|
+
pathMatch = resolved.match ?? null;
|
|
5878
|
+
} else {
|
|
5879
|
+
scope = parseOptionalScopeFromOptions(opts);
|
|
5880
|
+
}
|
|
5881
|
+
if (!scope) {
|
|
5882
|
+
printEnvelopeAndExit({
|
|
5883
|
+
envelope: {
|
|
5884
|
+
ok: false,
|
|
5885
|
+
command: "tree",
|
|
5886
|
+
status: 400,
|
|
5887
|
+
data: null,
|
|
5888
|
+
error: {
|
|
5889
|
+
code: "invalid_args",
|
|
5890
|
+
message: "Provide either --path or full scope args (--tool-key and --node-key).",
|
|
5891
|
+
details: {}
|
|
5892
|
+
},
|
|
5893
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local_error" }
|
|
5894
|
+
},
|
|
5895
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5896
|
+
});
|
|
5897
|
+
}
|
|
5898
|
+
const node = await requestTraversal({
|
|
5899
|
+
command: "tree",
|
|
5900
|
+
runtimeOptions: context.runtimeOptions,
|
|
5901
|
+
operationName: "MarkdownTreeSubtree",
|
|
5902
|
+
field: "markdown_tree_subtree",
|
|
5903
|
+
variables: {
|
|
5904
|
+
organization_id: organizationId,
|
|
5905
|
+
tool_key: scope.toolKey,
|
|
5906
|
+
node_key: scope.nodeKey,
|
|
5907
|
+
parent_id: scope.parentId,
|
|
5908
|
+
record_id: scope.recordId,
|
|
5909
|
+
member_id: scope.memberId,
|
|
5910
|
+
team_id: scope.teamId,
|
|
5911
|
+
content_type: scope.contentType,
|
|
5912
|
+
tree_view: scope.treeView,
|
|
5913
|
+
depth
|
|
5914
|
+
},
|
|
5915
|
+
depth: depth + 1
|
|
5916
|
+
});
|
|
5917
|
+
printEnvelopeAndExit({
|
|
5918
|
+
envelope: {
|
|
5919
|
+
ok: true,
|
|
5920
|
+
command: "tree",
|
|
5921
|
+
status: 200,
|
|
5922
|
+
data: {
|
|
5923
|
+
target: pathMatch,
|
|
5924
|
+
depth,
|
|
5925
|
+
node
|
|
5926
|
+
},
|
|
5927
|
+
error: null,
|
|
5928
|
+
meta: { requestId: context.runtimeOptions.requestId ?? "local" }
|
|
5929
|
+
}
|
|
5930
|
+
});
|
|
5931
|
+
});
|
|
5932
|
+
}
|
|
5933
|
+
|
|
5934
|
+
// src/commands/mutationCapability.ts
|
|
5935
|
+
function unsupportedMutationEnvelope(params) {
|
|
5936
|
+
return {
|
|
5937
|
+
ok: false,
|
|
5938
|
+
command: params.command,
|
|
5939
|
+
status: 400,
|
|
5940
|
+
data: null,
|
|
5941
|
+
error: {
|
|
5942
|
+
code: "mutation_unsupported",
|
|
5943
|
+
message: "No mutation command is supported for this node type.",
|
|
5944
|
+
details: {
|
|
5945
|
+
node: params.node
|
|
5946
|
+
}
|
|
5947
|
+
},
|
|
5948
|
+
meta: {
|
|
5949
|
+
requestId: "local_error"
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
}
|
|
5953
|
+
function emitUnsupportedMutation(params) {
|
|
5954
|
+
const canonicalPath = typeof params.canonicalPath === "string" && params.canonicalPath.trim().length > 0 ? params.canonicalPath.trim() : null;
|
|
5955
|
+
printEnvelopeAndExit({
|
|
5956
|
+
envelope: unsupportedMutationEnvelope({
|
|
5957
|
+
command: params.command,
|
|
5958
|
+
node: {
|
|
5959
|
+
toolKey: params.toolKey,
|
|
5960
|
+
nodeKey: params.nodeKey,
|
|
5961
|
+
canonicalPath
|
|
5962
|
+
}
|
|
5963
|
+
}),
|
|
5964
|
+
exitCode: EXIT_CODES.invalidArgs
|
|
5965
|
+
});
|
|
5966
|
+
}
|
|
5967
|
+
function registerMutationCapabilityCommands(program) {
|
|
5968
|
+
const projectNotes = program.command("project-notes").description("Project notes node (read-only in CLI mutation surface)");
|
|
5969
|
+
projectNotes.command("create").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5970
|
+
emitUnsupportedMutation({
|
|
5971
|
+
command: "project-notes.create",
|
|
5972
|
+
toolKey: "projects",
|
|
5973
|
+
nodeKey: "project_notes",
|
|
5974
|
+
canonicalPath: opts.path
|
|
5975
|
+
});
|
|
5976
|
+
});
|
|
5977
|
+
projectNotes.command("update").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5978
|
+
emitUnsupportedMutation({
|
|
5979
|
+
command: "project-notes.update",
|
|
5980
|
+
toolKey: "projects",
|
|
5981
|
+
nodeKey: "project_notes",
|
|
5982
|
+
canonicalPath: opts.path
|
|
5983
|
+
});
|
|
5984
|
+
});
|
|
5985
|
+
projectNotes.command("destroy").option("--path <path>", "Canonical path for the selected node").action((opts) => {
|
|
5986
|
+
emitUnsupportedMutation({
|
|
5987
|
+
command: "project-notes.destroy",
|
|
5988
|
+
toolKey: "projects",
|
|
5989
|
+
nodeKey: "project_notes",
|
|
5990
|
+
canonicalPath: opts.path
|
|
5991
|
+
});
|
|
5992
|
+
});
|
|
5993
|
+
}
|
|
5994
|
+
|
|
3028
5995
|
// src/cli.ts
|
|
3029
|
-
function buildCli() {
|
|
5996
|
+
function buildCli(options) {
|
|
3030
5997
|
const program = new import_commander.Command();
|
|
3031
5998
|
program.name("wave").description("Wave agent CLI").showHelpAfterError(false).allowExcessArguments(false).option("--token <token>", "API token (prefer WAVE_API_TOKEN env var)").option("--jwt <jwt>", "Legacy alias for --token (prefer WAVE_API_TOKEN env var)").option("--token-stdin", "Read API token from stdin").option(
|
|
3032
5999
|
"--auth-json-stdin",
|
|
@@ -3047,6 +6014,7 @@ function buildCli() {
|
|
|
3047
6014
|
"--openapi-version <openapiVersion>",
|
|
3048
6015
|
"Optional pinned OpenAPI version/hash"
|
|
3049
6016
|
).exitOverride();
|
|
6017
|
+
setInternalCliOptions(program, options?.internal);
|
|
3050
6018
|
registerTaskCommands(program);
|
|
3051
6019
|
registerProjectCommands(program);
|
|
3052
6020
|
registerRockCommands(program);
|
|
@@ -3059,6 +6027,9 @@ function buildCli() {
|
|
|
3059
6027
|
registerFoundationCommands(program);
|
|
3060
6028
|
registerChildEntityCommands(program);
|
|
3061
6029
|
registerNoteCommands(program);
|
|
6030
|
+
registerMutationCapabilityCommands(program);
|
|
6031
|
+
registerMarkdownTreeCommands(program);
|
|
6032
|
+
registerNavigationCommands(program);
|
|
3062
6033
|
return program;
|
|
3063
6034
|
}
|
|
3064
6035
|
|
|
@@ -3107,13 +6078,13 @@ main().catch((error) => {
|
|
|
3107
6078
|
exitCode: EXIT_CODES.invalidArgs
|
|
3108
6079
|
});
|
|
3109
6080
|
}
|
|
3110
|
-
if (error instanceof
|
|
6081
|
+
if (error instanceof import_zod16.ZodError || error instanceof import_commander2.InvalidArgumentError) {
|
|
3111
6082
|
printCliFailure({
|
|
3112
6083
|
status: 400,
|
|
3113
6084
|
code: "invalid_args",
|
|
3114
6085
|
message: "Invalid command arguments.",
|
|
3115
6086
|
details: {
|
|
3116
|
-
issues: error instanceof
|
|
6087
|
+
issues: error instanceof import_zod16.ZodError ? error.issues : [{ message: error.message, code: "invalid_argument" }]
|
|
3117
6088
|
},
|
|
3118
6089
|
exitCode: EXIT_CODES.invalidArgs
|
|
3119
6090
|
});
|