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