@bussolabs/closeyourit-cli 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -5
- package/dist/base.d.ts +22 -0
- package/dist/base.js +46 -0
- package/dist/commands/alerts/notifications/read-all.js +3 -0
- package/dist/commands/alerts/preferences/show.js +2 -0
- package/dist/commands/ideas/convert.d.ts +2 -2
- package/dist/commands/ideas/convert.js +25 -8
- package/dist/commands/kb/book/add-page.d.ts +18 -0
- package/dist/commands/kb/book/add-page.js +55 -0
- package/dist/commands/kb/book/list.d.ts +12 -0
- package/dist/commands/kb/book/list.js +33 -0
- package/dist/commands/kb/book/show.d.ts +9 -0
- package/dist/commands/kb/book/show.js +22 -0
- package/dist/commands/kb/create.js +29 -6
- package/dist/commands/kb/publish.d.ts +15 -0
- package/dist/commands/kb/publish.js +106 -0
- package/dist/commands/kb/update.js +26 -5
- package/dist/commands/logout.js +3 -0
- package/dist/commands/org/show.js +2 -0
- package/dist/commands/personal/import.js +2 -2
- package/dist/commands/personal/run.js +1 -1
- package/dist/commands/run.js +1 -1
- package/dist/commands/secrets/import.js +2 -2
- package/dist/commands/seo/ignore.d.ts +12 -0
- package/dist/commands/seo/ignore.js +27 -0
- package/dist/commands/seo/list.d.ts +13 -0
- package/dist/commands/seo/list.js +52 -0
- package/dist/commands/seo/pages.d.ts +11 -0
- package/dist/commands/seo/pages.js +44 -0
- package/dist/commands/seo/promote.d.ts +9 -0
- package/dist/commands/seo/promote.js +22 -0
- package/dist/commands/seo/reopen.d.ts +9 -0
- package/dist/commands/seo/reopen.js +21 -0
- package/dist/commands/seo/rescan.d.ts +9 -0
- package/dist/commands/seo/rescan.js +21 -0
- package/dist/commands/seo/show.d.ts +9 -0
- package/dist/commands/seo/show.js +35 -0
- package/dist/commands/seo-sites/create.d.ts +14 -0
- package/dist/commands/seo-sites/create.js +43 -0
- package/dist/commands/seo-sites/delete.d.ts +9 -0
- package/dist/commands/seo-sites/delete.js +21 -0
- package/dist/commands/seo-sites/list.d.ts +10 -0
- package/dist/commands/seo-sites/list.js +38 -0
- package/dist/commands/seo-sites/update.d.ts +17 -0
- package/dist/commands/seo-sites/update.js +45 -0
- package/dist/commands/tickets/comment.d.ts +14 -3
- package/dist/commands/tickets/comment.js +29 -1
- package/dist/commands/tickets/create.d.ts +6 -6
- package/dist/commands/tickets/create.js +21 -2
- package/dist/commands/tickets/report-show.d.ts +20 -0
- package/dist/commands/tickets/report-show.js +38 -0
- package/dist/commands/tickets/report-versions.d.ts +19 -0
- package/dist/commands/tickets/report-versions.js +40 -0
- package/dist/commands/tickets/report.d.ts +24 -0
- package/dist/commands/tickets/report.js +69 -0
- package/dist/commands/tickets/status.d.ts +1 -1
- package/dist/commands/tickets/status.js +14 -4
- package/dist/commands/tickets/update.d.ts +25 -6
- package/dist/commands/tickets/update.js +144 -9
- package/dist/commands/whoami.js +3 -0
- package/dist/errors/error-codes.d.ts +12 -0
- package/dist/errors/error-codes.js +19 -0
- package/dist/errors/input-error.d.ts +16 -0
- package/dist/errors/input-error.js +42 -0
- package/dist/lib/alert-events.js +1 -0
- package/dist/lib/knowledge.d.ts +24 -0
- package/dist/lib/knowledge.js +68 -0
- package/dist/lib/limits.d.ts +59 -0
- package/dist/lib/limits.js +92 -0
- package/dist/lib/stdin.d.ts +1 -2
- package/dist/lib/stdin.js +1 -2
- package/dist/lib/subprocess.d.ts +1 -1
- package/dist/lib/subprocess.js +1 -1
- package/dist/lib/ticket-body.d.ts +22 -6
- package/dist/lib/ticket-body.js +71 -9
- package/dist/lib/ticket-lookup.d.ts +53 -0
- package/dist/lib/ticket-lookup.js +78 -0
- package/dist/lib/ticket-report.d.ts +7 -0
- package/dist/lib/ticket-report.js +14 -0
- package/oclif.manifest.json +3931 -2876
- package/opencli.json +860 -113
- package/package.json +4 -1
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { type LengthCheck } from './limits';
|
|
1
2
|
export declare const ticketBodyFlags: {
|
|
3
|
+
'assignee-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
4
|
+
'milestone-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
5
|
+
'parent-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
|
+
'platform-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
|
+
status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
priority: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
2
9
|
description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
3
10
|
'technical-analysis': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
4
11
|
scenarios: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -9,12 +16,10 @@ export declare const ticketBodyFlags: {
|
|
|
9
16
|
condition: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
17
|
weight: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
18
|
'due-at': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'parent-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
-
'platform-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
};
|
|
20
|
+
export declare const CLEARABLE_FIELDS: Record<string, string>;
|
|
21
|
+
export declare const clearFlag: {
|
|
22
|
+
clear: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
23
|
};
|
|
19
24
|
type BodyFlags = Record<string, unknown>;
|
|
20
25
|
export declare function scenariosFromFlags(flags: BodyFlags): Array<Record<string, unknown>> | undefined;
|
|
@@ -22,4 +27,15 @@ export declare function conditionsFromFlags(flags: BodyFlags): Array<{
|
|
|
22
27
|
text: string;
|
|
23
28
|
}> | undefined;
|
|
24
29
|
export declare function applyTicketBody(body: BodyFlags, flags: BodyFlags): void;
|
|
30
|
+
/**
|
|
31
|
+
* I campi del corpo che il server misura, pronti per `tooLongMessage` (CYCL-32): titolo, descrizione
|
|
32
|
+
* e analisi tecnica. Scenari e condizioni non ci sono — non hanno tetto.
|
|
33
|
+
*
|
|
34
|
+
* `current` è il ticket com'è adesso, per i comandi che lo leggono prima di scrivere: fa da
|
|
35
|
+
* salvaguardia, così un testo scritto prima che il tetto esistesse resta correggibile finché non si
|
|
36
|
+
* allunga. Chi non lo conosce lo omette e il tetto vale pieno.
|
|
37
|
+
*/
|
|
38
|
+
export declare function ticketLengthChecks(flags: BodyFlags, current?: BodyFlags): LengthCheck[];
|
|
39
|
+
/** Marca come vuoti i campi elencati da `--clear`: null, o lista vuota per le piattaforme. */
|
|
40
|
+
export declare function applyTicketClears(body: BodyFlags, fields: string[] | undefined): void;
|
|
25
41
|
export {};
|
package/dist/lib/ticket-body.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ticketBodyFlags = void 0;
|
|
3
|
+
exports.clearFlag = exports.CLEARABLE_FIELDS = exports.ticketBodyFlags = void 0;
|
|
4
4
|
exports.scenariosFromFlags = scenariosFromFlags;
|
|
5
5
|
exports.conditionsFromFlags = conditionsFromFlags;
|
|
6
6
|
exports.applyTicketBody = applyTicketBody;
|
|
7
|
+
exports.ticketLengthChecks = ticketLengthChecks;
|
|
8
|
+
exports.applyTicketClears = applyTicketClears;
|
|
7
9
|
const core_1 = require("@oclif/core");
|
|
10
|
+
const limits_1 = require("./limits");
|
|
11
|
+
const ticket_lookup_1 = require("./ticket-lookup");
|
|
8
12
|
// Flag del corpo ticket condivisi da `tickets create` e `tickets update`: descrizione (sommario
|
|
9
13
|
// human-simple) + N scenari BDD + N condizioni DoD + analisi tecnica (registro tecnico separato) +
|
|
10
14
|
// metadati. Gli scenari si passano come JSON (--scenarios) oppure, per un SINGOLO scenario, con le
|
|
11
15
|
// scorciatoie --step-*. Le condizioni DoD sono --condition (ripetibile). Parità piena col form web.
|
|
12
16
|
exports.ticketBodyFlags = {
|
|
13
|
-
description: core_1.Flags.string({
|
|
14
|
-
|
|
17
|
+
description: core_1.Flags.string({
|
|
18
|
+
description: `Free-form description (human-simple summary, max ${limits_1.LENGTH_LIMITS.description} characters)`,
|
|
19
|
+
}),
|
|
20
|
+
'technical-analysis': core_1.Flags.string({
|
|
21
|
+
description: `Technical analysis (stack, cause) — kept out of the human-simple body (max ${limits_1.LENGTH_LIMITS.technicalAnalysis} characters)`,
|
|
22
|
+
}),
|
|
15
23
|
scenarios: core_1.Flags.string({
|
|
16
24
|
description: 'BDD scenarios as a JSON array: [{"title","step_given","step_when","step_then","step_expected"}]',
|
|
17
25
|
}),
|
|
@@ -22,13 +30,34 @@ exports.ticketBodyFlags = {
|
|
|
22
30
|
condition: core_1.Flags.string({ description: 'Definition-of-Done line (repeatable)', multiple: true }),
|
|
23
31
|
weight: core_1.Flags.string({ description: 'Story points (positive integer)' }),
|
|
24
32
|
'due-at': core_1.Flags.string({ description: 'Due date (ISO 8601)' }),
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
// Stato e priorità si indicano per code, etichetta o id, e il comando li risolve (CYCL-34).
|
|
34
|
+
...ticket_lookup_1.ticketLookupFlags,
|
|
27
35
|
'assignee-id': core_1.Flags.string({ description: 'Assignee account id' }),
|
|
28
36
|
'milestone-id': core_1.Flags.string({ description: 'Milestone id (of this project)' }),
|
|
29
37
|
'parent-id': core_1.Flags.string({ description: 'Parent epic id (of this project) — pass an empty string to detach' }),
|
|
30
38
|
'platform-id': core_1.Flags.string({ description: 'Affected platform id (repeatable)', multiple: true }),
|
|
31
39
|
};
|
|
40
|
+
// Campi che `tickets update` svuota solo se glielo si chiede (`--clear <campo>`): nome del flag che
|
|
41
|
+
// li imposta → chiave del corpo. Svuotarli è una richiesta a sé, mai l'effetto collaterale di un
|
|
42
|
+
// campo omesso (CYCL-30). Scenari e condizioni non ci sono: il backend li sostituisce quando il
|
|
43
|
+
// corpo ne porta di nuovi, li lascia intatti quando li omette, e un array vuoto non li cancella.
|
|
44
|
+
exports.CLEARABLE_FIELDS = {
|
|
45
|
+
description: 'description',
|
|
46
|
+
'technical-analysis': 'technical_analysis',
|
|
47
|
+
weight: 'weight',
|
|
48
|
+
'due-at': 'due_at',
|
|
49
|
+
assignee: 'assignee_id',
|
|
50
|
+
milestone: 'milestone_id',
|
|
51
|
+
parent: 'parent_id',
|
|
52
|
+
platforms: 'platform_ids',
|
|
53
|
+
};
|
|
54
|
+
exports.clearFlag = {
|
|
55
|
+
clear: core_1.Flags.string({
|
|
56
|
+
description: `Empty a field on purpose (repeatable): ${Object.keys(exports.CLEARABLE_FIELDS).join(', ')}`,
|
|
57
|
+
multiple: true,
|
|
58
|
+
options: Object.keys(exports.CLEARABLE_FIELDS),
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
32
61
|
const STEP_KEYS = [
|
|
33
62
|
['step-given', 'step_given'],
|
|
34
63
|
['step-when', 'step_when'],
|
|
@@ -64,6 +93,8 @@ function conditionsFromFlags(flags) {
|
|
|
64
93
|
return conditions.map((text) => ({ text }));
|
|
65
94
|
}
|
|
66
95
|
// Popola `body` coi campi del corpo presenti nei flag (chiavi snake_case attese dall'API CLI).
|
|
96
|
+
// Stato e priorità restano fuori: vanno risolti in id contro le lookup dell'organizzazione, cioè
|
|
97
|
+
// con una chiamata, e ogni comando li aggiunge dopo — con o senza predefinito (CYCL-34).
|
|
67
98
|
function applyTicketBody(body, flags) {
|
|
68
99
|
if (flags.description !== undefined)
|
|
69
100
|
body.description = flags.description;
|
|
@@ -73,10 +104,6 @@ function applyTicketBody(body, flags) {
|
|
|
73
104
|
body.weight = flags.weight;
|
|
74
105
|
if (flags['due-at'] !== undefined)
|
|
75
106
|
body.due_at = flags['due-at'];
|
|
76
|
-
if (flags['status-id'] !== undefined)
|
|
77
|
-
body.status_id = flags['status-id'];
|
|
78
|
-
if (flags['priority-id'] !== undefined)
|
|
79
|
-
body.priority_id = flags['priority-id'];
|
|
80
107
|
if (flags['assignee-id'] !== undefined)
|
|
81
108
|
body.assignee_id = flags['assignee-id'];
|
|
82
109
|
if (flags['milestone-id'] !== undefined)
|
|
@@ -92,3 +119,38 @@ function applyTicketBody(body, flags) {
|
|
|
92
119
|
if (conditions !== undefined)
|
|
93
120
|
body.conditions_attributes = conditions;
|
|
94
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* I campi del corpo che il server misura, pronti per `tooLongMessage` (CYCL-32): titolo, descrizione
|
|
124
|
+
* e analisi tecnica. Scenari e condizioni non ci sono — non hanno tetto.
|
|
125
|
+
*
|
|
126
|
+
* `current` è il ticket com'è adesso, per i comandi che lo leggono prima di scrivere: fa da
|
|
127
|
+
* salvaguardia, così un testo scritto prima che il tetto esistesse resta correggibile finché non si
|
|
128
|
+
* allunga. Chi non lo conosce lo omette e il tetto vale pieno.
|
|
129
|
+
*/
|
|
130
|
+
function ticketLengthChecks(flags, current = {}) {
|
|
131
|
+
// `orthography`: il server corregge l'ortografia italiana di questi tre campi prima di misurarli.
|
|
132
|
+
return [
|
|
133
|
+
{ flag: '--title', value: flags.title, max: limits_1.LENGTH_LIMITS.title, previous: current.title, orthography: true },
|
|
134
|
+
{
|
|
135
|
+
flag: '--description',
|
|
136
|
+
value: flags.description,
|
|
137
|
+
max: limits_1.LENGTH_LIMITS.description,
|
|
138
|
+
previous: current.description,
|
|
139
|
+
orthography: true,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
flag: '--technical-analysis',
|
|
143
|
+
value: flags['technical-analysis'],
|
|
144
|
+
max: limits_1.LENGTH_LIMITS.technicalAnalysis,
|
|
145
|
+
previous: current.technical_analysis,
|
|
146
|
+
orthography: true,
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
/** Marca come vuoti i campi elencati da `--clear`: null, o lista vuota per le piattaforme. */
|
|
151
|
+
function applyTicketClears(body, fields) {
|
|
152
|
+
for (const field of fields ?? []) {
|
|
153
|
+
const key = exports.CLEARABLE_FIELDS[field];
|
|
154
|
+
body[key] = key === 'platform_ids' ? [] : null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Le due lookup d'organizzazione che ogni ticket si porta addosso: stato e priorità (CYCL-34).
|
|
3
|
+
*
|
|
4
|
+
* Il server le pretende entrambe alla creazione (R422-TICKET-001 "Status must exist and Priority
|
|
5
|
+
* must exist") mentre l'aiuto della CLI le dava per opzionali, e i loro id andavano cercati prima
|
|
6
|
+
* con `tickets statuses`/`tickets priorities` e incollati come UUID. Qui vivono l'endpoint da
|
|
7
|
+
* leggere, il code che vale quando il ticket nasce senza che li si sia indicati, e come si chiama
|
|
8
|
+
* il campo nei messaggi.
|
|
9
|
+
*/
|
|
10
|
+
export interface TicketLookup {
|
|
11
|
+
/** Lookup d'organizzazione (non di progetto): gli id valgono per un ticket di qualunque progetto. */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Nome del campo nei messaggi d'errore. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Il flag che lo imposta. */
|
|
16
|
+
flag: string;
|
|
17
|
+
/** Il code che vale quando il ticket nasce e non lo si è indicato. */
|
|
18
|
+
fallback: string;
|
|
19
|
+
errorCode: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const TICKET_STATUS: TicketLookup;
|
|
22
|
+
export declare const TICKET_PRIORITY: TicketLookup;
|
|
23
|
+
/**
|
|
24
|
+
* `--status`/`--priority` di un comando che modifica un ticket già esistente. `--status-id` e
|
|
25
|
+
* `--priority-id` restano come alias: erano l'unico modo di indicarli, e gli script che li usano
|
|
26
|
+
* continuano a funzionare senza riscritture.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ticketLookupFlags: {
|
|
29
|
+
status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
|
+
priority: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
|
+
};
|
|
32
|
+
/** Gli stessi due flag su un comando che crea il ticket, dove ometterli ha un valore predefinito. */
|
|
33
|
+
export declare const newTicketLookupFlags: {
|
|
34
|
+
status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
priority: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Le voci che corrispondono al riferimento scritto a mano: prima il code, poi l'etichetta, senza
|
|
39
|
+
* badare alle maiuscole. Il code ha la precedenza perché è il nome esatto della voce: senza,
|
|
40
|
+
* l'etichetta di un'altra ("Urgent" su `high`) farebbe concorrenza al code di quella cercata
|
|
41
|
+
* (`urgent`) e una scelta legittima diventerebbe un'ambiguità da rifiutare.
|
|
42
|
+
*/
|
|
43
|
+
export declare function matchTicketLookup(rows: unknown, value: string): Array<{
|
|
44
|
+
id: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Il rifiuto di un riferimento che non si risolve: dice cos'è stato cercato, come si scrive il flag
|
|
48
|
+
* e quali voci esistono davvero — così scoprirle non costa un secondo comando.
|
|
49
|
+
*/
|
|
50
|
+
export declare function ticketLookupErrorMessage(lookup: TicketLookup, wanted: string, rows: unknown, { matched, isDefault }: {
|
|
51
|
+
matched: number;
|
|
52
|
+
isDefault: boolean;
|
|
53
|
+
}): string;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newTicketLookupFlags = exports.ticketLookupFlags = exports.TICKET_PRIORITY = exports.TICKET_STATUS = void 0;
|
|
4
|
+
exports.matchTicketLookup = matchTicketLookup;
|
|
5
|
+
exports.ticketLookupErrorMessage = ticketLookupErrorMessage;
|
|
6
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const error_codes_1 = require("../errors/error-codes");
|
|
8
|
+
exports.TICKET_STATUS = {
|
|
9
|
+
path: '/cli/v1/types/ticket_statuses',
|
|
10
|
+
name: 'Status',
|
|
11
|
+
flag: '--status',
|
|
12
|
+
fallback: 'open',
|
|
13
|
+
errorCode: error_codes_1.ErrorCodes.TicketStatus.notFound,
|
|
14
|
+
};
|
|
15
|
+
exports.TICKET_PRIORITY = {
|
|
16
|
+
path: '/cli/v1/types/ticket_priorities',
|
|
17
|
+
name: 'Priority',
|
|
18
|
+
flag: '--priority',
|
|
19
|
+
fallback: 'medium',
|
|
20
|
+
errorCode: error_codes_1.ErrorCodes.TicketPriority.notFound,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* `--status`/`--priority` di un comando che modifica un ticket già esistente. `--status-id` e
|
|
24
|
+
* `--priority-id` restano come alias: erano l'unico modo di indicarli, e gli script che li usano
|
|
25
|
+
* continuano a funzionare senza riscritture.
|
|
26
|
+
*/
|
|
27
|
+
exports.ticketLookupFlags = {
|
|
28
|
+
status: core_1.Flags.string({
|
|
29
|
+
aliases: ['status-id'],
|
|
30
|
+
description: 'Status code, label or id (e.g. open, "In Progress") — unchanged when omitted',
|
|
31
|
+
}),
|
|
32
|
+
priority: core_1.Flags.string({
|
|
33
|
+
aliases: ['priority-id'],
|
|
34
|
+
description: 'Priority code, label or id (e.g. medium, High) — unchanged when omitted',
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
/** Gli stessi due flag su un comando che crea il ticket, dove ometterli ha un valore predefinito. */
|
|
38
|
+
exports.newTicketLookupFlags = {
|
|
39
|
+
status: core_1.Flags.string({
|
|
40
|
+
aliases: ['status-id'],
|
|
41
|
+
description: `Status code, label or id (e.g. open, "In Progress") — default: ${exports.TICKET_STATUS.fallback}`,
|
|
42
|
+
}),
|
|
43
|
+
priority: core_1.Flags.string({
|
|
44
|
+
aliases: ['priority-id'],
|
|
45
|
+
description: `Priority code, label or id (e.g. medium, High) — default: ${exports.TICKET_PRIORITY.fallback}`,
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Le voci che corrispondono al riferimento scritto a mano: prima il code, poi l'etichetta, senza
|
|
50
|
+
* badare alle maiuscole. Il code ha la precedenza perché è il nome esatto della voce: senza,
|
|
51
|
+
* l'etichetta di un'altra ("Urgent" su `high`) farebbe concorrenza al code di quella cercata
|
|
52
|
+
* (`urgent`) e una scelta legittima diventerebbe un'ambiguità da rifiutare.
|
|
53
|
+
*/
|
|
54
|
+
function matchTicketLookup(rows, value) {
|
|
55
|
+
const wanted = value.trim().toLowerCase();
|
|
56
|
+
const list = (Array.isArray(rows) ? rows : []);
|
|
57
|
+
const identified = list.filter((row) => typeof row.id === 'string' && row.id !== '');
|
|
58
|
+
const sameAs = (field) => typeof field === 'string' && field.trim().toLowerCase() === wanted;
|
|
59
|
+
const byCode = identified.filter((row) => sameAs(row.code));
|
|
60
|
+
return byCode.length > 0 ? byCode : identified.filter((row) => sameAs(row.label));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Il rifiuto di un riferimento che non si risolve: dice cos'è stato cercato, come si scrive il flag
|
|
64
|
+
* e quali voci esistono davvero — così scoprirle non costa un secondo comando.
|
|
65
|
+
*/
|
|
66
|
+
function ticketLookupErrorMessage(lookup, wanted, rows, { matched, isDefault }) {
|
|
67
|
+
const known = (Array.isArray(rows) ? rows : [])
|
|
68
|
+
.map((row) => (typeof row.code === 'string' && row.code !== '' ? row.code : String(row.label ?? '')))
|
|
69
|
+
.filter((name) => name !== '')
|
|
70
|
+
.join(', ');
|
|
71
|
+
const hint = `Pass ${lookup.flag} with a code, a label or an id${known === '' ? '' : ` — known: ${known}`}.`;
|
|
72
|
+
if (matched > 1)
|
|
73
|
+
return `${lookup.name} "${wanted}" matches ${matched} entries. ${hint}`;
|
|
74
|
+
if (isDefault) {
|
|
75
|
+
return `This organization has no ${lookup.name.toLowerCase()} "${wanted}", the default for a new ticket. ${hint}`;
|
|
76
|
+
}
|
|
77
|
+
return `${lookup.name} not found: "${wanted}". ${hint}`;
|
|
78
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Una versione del resoconto di lavorazione: intestazione coi metadati + il testo per intero
|
|
3
|
+
* (CYCL-31). Il corpo passa da `sanitizeMultiline` e non da `renderRecord`: quest'ultimo appiattisce
|
|
4
|
+
* ogni valore con `sanitize`, che trasforma gli a capo in spazi — su un resoconto di migliaia di
|
|
5
|
+
* caratteri significherebbe stamparlo come un muro di testo su una riga sola.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderReport(report: Record<string, unknown>): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderReport = renderReport;
|
|
4
|
+
const output_1 = require("./output");
|
|
5
|
+
/**
|
|
6
|
+
* Una versione del resoconto di lavorazione: intestazione coi metadati + il testo per intero
|
|
7
|
+
* (CYCL-31). Il corpo passa da `sanitizeMultiline` e non da `renderRecord`: quest'ultimo appiattisce
|
|
8
|
+
* ogni valore con `sanitize`, che trasforma gli a capo in spazi — su un resoconto di migliaia di
|
|
9
|
+
* caratteri significherebbe stamparlo come un muro di testo su una riga sola.
|
|
10
|
+
*/
|
|
11
|
+
function renderReport(report) {
|
|
12
|
+
const header = `── version ${(0, output_1.sanitize)(report.version ?? '?')} · ${(0, output_1.sanitize)(report.author ?? '?')} · ${(0, output_1.sanitize)(report.source ?? '-')} · ${(0, output_1.sanitize)(report.created_at ?? '-')}`;
|
|
13
|
+
return `${header}\n${(0, output_1.sanitizeMultiline)(report.body ?? '')}`;
|
|
14
|
+
}
|