@orbitpanel/cli 0.1.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 +100 -0
- package/bin/dev.js +3 -0
- package/bin/run.js +3 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.js +86 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/intervention/delete.d.ts +12 -0
- package/dist/commands/intervention/delete.js +70 -0
- package/dist/commands/intervention/delete.js.map +1 -0
- package/dist/commands/intervention/get.d.ts +12 -0
- package/dist/commands/intervention/get.js +64 -0
- package/dist/commands/intervention/get.js.map +1 -0
- package/dist/commands/intervention/list.d.ts +15 -0
- package/dist/commands/intervention/list.js +102 -0
- package/dist/commands/intervention/list.js.map +1 -0
- package/dist/commands/intervention/update.d.ts +16 -0
- package/dist/commands/intervention/update.js +78 -0
- package/dist/commands/intervention/update.js.map +1 -0
- package/dist/commands/link.d.ts +13 -0
- package/dist/commands/link.js +77 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/login.d.ts +12 -0
- package/dist/commands/login.js +61 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +9 -0
- package/dist/commands/logout.js +23 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/note/add.d.ts +13 -0
- package/dist/commands/note/add.js +53 -0
- package/dist/commands/note/add.js.map +1 -0
- package/dist/commands/report/send.d.ts +15 -0
- package/dist/commands/report/send.js +124 -0
- package/dist/commands/report/send.js.map +1 -0
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.js +24 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/session/end.d.ts +10 -0
- package/dist/commands/session/end.js +61 -0
- package/dist/commands/session/end.js.map +1 -0
- package/dist/commands/session/start.d.ts +10 -0
- package/dist/commands/session/start.js +61 -0
- package/dist/commands/session/start.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.js +56 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/unlink.d.ts +10 -0
- package/dist/commands/unlink.js +43 -0
- package/dist/commands/unlink.js.map +1 -0
- package/dist/hooks/prerun.d.ts +9 -0
- package/dist/hooks/prerun.js +13 -0
- package/dist/hooks/prerun.js.map +1 -0
- package/dist/lib/client.d.ts +34 -0
- package/dist/lib/client.js +151 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/config.js +67 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/git.d.ts +19 -0
- package/dist/lib/git.js +48 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/report-builder.d.ts +16 -0
- package/dist/lib/report-builder.js +73 -0
- package/dist/lib/report-builder.js.map +1 -0
- package/dist/lib/session.d.ts +28 -0
- package/dist/lib/session.js +106 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/site.d.ts +21 -0
- package/dist/lib/site.js +59 -0
- package/dist/lib/site.js.map +1 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.js +319 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/oclif.manifest.json +732 -0
- package/package.json +62 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { loadConfig } from '../lib/config.js';
|
|
4
|
+
import { OrbitClient } from '../lib/client.js';
|
|
5
|
+
export default class Status extends Command {
|
|
6
|
+
static summary = 'Mostra lo stato corrente: sito, sessione, token';
|
|
7
|
+
static examples = ['<%= config.bin %> status'];
|
|
8
|
+
async run() {
|
|
9
|
+
const config = await loadConfig();
|
|
10
|
+
this.log('');
|
|
11
|
+
this.log(chalk.bold(`Orbit CLI v${this.config.version}`));
|
|
12
|
+
this.log('');
|
|
13
|
+
// Token info
|
|
14
|
+
const defaultSite = config.default_site;
|
|
15
|
+
const tokenEntry = defaultSite ? config.tokens[defaultSite] : undefined;
|
|
16
|
+
if (!tokenEntry) {
|
|
17
|
+
this.log(chalk.yellow(' Nessun token configurato.'));
|
|
18
|
+
this.log(chalk.dim(' Esegui: orbit login --token <token>'));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const maskedToken = `${tokenEntry.token.slice(0, 15)}...${tokenEntry.token.slice(-4)}`;
|
|
22
|
+
// Validate connection
|
|
23
|
+
const client = new OrbitClient(tokenEntry.token, config.api_url);
|
|
24
|
+
const validation = await client.validateToken();
|
|
25
|
+
this.log(` Token: ${maskedToken} ${validation.valid ? chalk.green('(valido)') : chalk.red('(non valido)')}`);
|
|
26
|
+
this.log(` API: ${config.api_url} ${validation.valid ? chalk.green('(raggiungibile)') : chalk.red('(non raggiungibile)')}`);
|
|
27
|
+
this.log(` Site ID: ${defaultSite}`);
|
|
28
|
+
if (validation.valid) {
|
|
29
|
+
try {
|
|
30
|
+
const stats = await client.getStats();
|
|
31
|
+
const total = stats.total_interventions ?? 0;
|
|
32
|
+
const byStatus = stats.by_status ?? {};
|
|
33
|
+
this.log('');
|
|
34
|
+
this.log(` Interventi: ${total} totali`);
|
|
35
|
+
if (total > 0) {
|
|
36
|
+
const parts = [];
|
|
37
|
+
if (byStatus.in_progress)
|
|
38
|
+
parts.push(`${byStatus.in_progress} in corso`);
|
|
39
|
+
if (byStatus.completed)
|
|
40
|
+
parts.push(`${byStatus.completed} completati`);
|
|
41
|
+
if (byStatus.scheduled)
|
|
42
|
+
parts.push(`${byStatus.scheduled} pianificati`);
|
|
43
|
+
if (parts.length > 0) {
|
|
44
|
+
this.log(` ${chalk.dim(parts.join(', '))}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
this.log(chalk.dim(` Stats non disponibili: ${msg}`));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.log('');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Unlink extends Command {
|
|
3
|
+
static summary: string;
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
confirm: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { removeSiteLink, loadSiteLink } from '../lib/site.js';
|
|
5
|
+
export default class Unlink extends Command {
|
|
6
|
+
static summary = 'Rimuove il collegamento della directory corrente';
|
|
7
|
+
static description = 'Elimina il file .orbit.json dalla directory corrente.';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> unlink',
|
|
10
|
+
'<%= config.bin %> unlink --confirm',
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
confirm: Flags.boolean({
|
|
14
|
+
char: 'y',
|
|
15
|
+
description: 'Salta la conferma interattiva',
|
|
16
|
+
default: false,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
async run() {
|
|
20
|
+
const { flags } = await this.parse(Unlink);
|
|
21
|
+
const cwd = process.cwd();
|
|
22
|
+
const existing = await loadSiteLink(cwd);
|
|
23
|
+
if (!existing) {
|
|
24
|
+
this.log(chalk.yellow('Nessun .orbit.json trovato nella directory corrente.'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.log(`Sito collegato: ${existing.orbit_site_id} (${existing.platform})`);
|
|
28
|
+
if (!flags.confirm) {
|
|
29
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
30
|
+
const answer = await new Promise((resolve) => {
|
|
31
|
+
rl.question(chalk.yellow('Rimuovere il collegamento? [y/N] '), resolve);
|
|
32
|
+
});
|
|
33
|
+
rl.close();
|
|
34
|
+
if (answer.toLowerCase() !== 'y') {
|
|
35
|
+
this.log('Annullato.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
await removeSiteLink(cwd);
|
|
40
|
+
this.log(chalk.green('Collegamento rimosso.'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=unlink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unlink.js","sourceRoot":"","sources":["../../src/commands/unlink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IACzC,MAAM,CAAC,OAAO,GAAG,kDAAkD,CAAC;IAEpE,MAAM,CAAC,WAAW,GAAG,uDAAuD,CAAC;IAE7E,MAAM,CAAC,QAAQ,GAAG;QAChB,0BAA0B;QAC1B,oCAAoC;KACrC,CAAC;IAEF,MAAM,CAAC,KAAK,GAAG;QACb,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,+BAA+B;YAC5C,OAAO,EAAE,KAAK;SACf,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE1B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sDAAsD,CAAC,CAAC,CAAC;YAC/E,OAAO;QACT,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,mBAAmB,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC;QAE7E,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7E,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;gBACnD,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1E,CAAC,CAAC,CAAC;YACH,EAAE,CAAC,KAAK,EAAE,CAAC;YAEX,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;gBACjC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBACvB,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;QAE1B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACjD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prerun hook — runs before every command.
|
|
3
|
+
*
|
|
4
|
+
* Currently a placeholder for future auth enforcement.
|
|
5
|
+
* Each command handles its own auth check for now.
|
|
6
|
+
*/
|
|
7
|
+
const hook = async function (_options) {
|
|
8
|
+
// Auth enforcement will be added when the command set grows.
|
|
9
|
+
// For now, commands like login/doctor skip auth internally,
|
|
10
|
+
// and status/report check for tokens themselves.
|
|
11
|
+
};
|
|
12
|
+
export default hook;
|
|
13
|
+
//# sourceMappingURL=prerun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../src/hooks/prerun.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,IAAI,GAAgB,KAAK,WAAW,QAAQ;IAChD,6DAA6D;IAC7D,4DAA4D;IAC5D,iDAAiD;AACnD,CAAC,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrbitPanel HTTP Client for @orbitpanel/cli.
|
|
3
|
+
*
|
|
4
|
+
* Communicates with the Orbit backend API for intervention CRUD.
|
|
5
|
+
* Reuses the same auth pattern as @orbitpanel/mcp-server.
|
|
6
|
+
*/
|
|
7
|
+
import type { TokenValidation } from '../types.js';
|
|
8
|
+
export declare class OrbitClient {
|
|
9
|
+
readonly apiUrl: string;
|
|
10
|
+
private readonly token;
|
|
11
|
+
constructor(token: string, apiUrl: string);
|
|
12
|
+
private headers;
|
|
13
|
+
private fetchWithTimeout;
|
|
14
|
+
/** Fetch with retry on 5xx/429 errors. Exponential backoff. */
|
|
15
|
+
private fetchWithRetry;
|
|
16
|
+
/** Validate token by calling stats endpoint. */
|
|
17
|
+
validateToken(): Promise<TokenValidation>;
|
|
18
|
+
/** List interventions with optional filters. */
|
|
19
|
+
listInterventions(filters?: Record<string, string | number>): Promise<{
|
|
20
|
+
items: Record<string, unknown>[];
|
|
21
|
+
total: number;
|
|
22
|
+
}>;
|
|
23
|
+
/** Create a new intervention. */
|
|
24
|
+
createIntervention(data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
25
|
+
/** Get a single intervention by ID. */
|
|
26
|
+
getIntervention(id: string): Promise<Record<string, unknown>>;
|
|
27
|
+
/** Update an intervention. */
|
|
28
|
+
updateIntervention(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
29
|
+
/** Delete an intervention. */
|
|
30
|
+
deleteIntervention(id: string): Promise<void>;
|
|
31
|
+
/** Get intervention stats. */
|
|
32
|
+
getStats(): Promise<Record<string, unknown>>;
|
|
33
|
+
private handleError;
|
|
34
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrbitPanel HTTP Client for @orbitpanel/cli.
|
|
3
|
+
*
|
|
4
|
+
* Communicates with the Orbit backend API for intervention CRUD.
|
|
5
|
+
* Reuses the same auth pattern as @orbitpanel/mcp-server.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
8
|
+
const MAX_RETRIES = 2;
|
|
9
|
+
const RETRY_BASE_MS = 500;
|
|
10
|
+
/** Retryable status codes (server errors, not client errors). */
|
|
11
|
+
const RETRYABLE_STATUSES = new Set([502, 503, 504, 429]);
|
|
12
|
+
export class OrbitClient {
|
|
13
|
+
apiUrl;
|
|
14
|
+
token;
|
|
15
|
+
constructor(token, apiUrl) {
|
|
16
|
+
if (!token)
|
|
17
|
+
throw new Error('token is required');
|
|
18
|
+
if (!apiUrl)
|
|
19
|
+
throw new Error('apiUrl is required');
|
|
20
|
+
this.token = token;
|
|
21
|
+
this.apiUrl = apiUrl.replace(/\/+$/, '');
|
|
22
|
+
}
|
|
23
|
+
headers() {
|
|
24
|
+
return {
|
|
25
|
+
Authorization: `Bearer ${this.token}`,
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
'User-Agent': '@orbitpanel/cli/0.1.0',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async fetchWithTimeout(url, options, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
33
|
+
try {
|
|
34
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Fetch with retry on 5xx/429 errors. Exponential backoff. */
|
|
41
|
+
async fetchWithRetry(url, options, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
42
|
+
let lastError;
|
|
43
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
44
|
+
try {
|
|
45
|
+
const res = await this.fetchWithTimeout(url, options, timeoutMs);
|
|
46
|
+
if (!RETRYABLE_STATUSES.has(res.status) || attempt === MAX_RETRIES) {
|
|
47
|
+
return res;
|
|
48
|
+
}
|
|
49
|
+
// Retryable status — wait and try again
|
|
50
|
+
lastError = new Error(`HTTP ${res.status}`);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
54
|
+
if (attempt === MAX_RETRIES)
|
|
55
|
+
throw lastError;
|
|
56
|
+
}
|
|
57
|
+
// Exponential backoff: 500ms, 1000ms
|
|
58
|
+
const delay = RETRY_BASE_MS * Math.pow(2, attempt);
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
60
|
+
}
|
|
61
|
+
throw lastError ?? new Error('Retry exhausted');
|
|
62
|
+
}
|
|
63
|
+
/** Validate token by calling stats endpoint. */
|
|
64
|
+
async validateToken() {
|
|
65
|
+
try {
|
|
66
|
+
const res = await this.fetchWithTimeout(`${this.apiUrl}/api/v1/maintenance/stats`, { method: 'GET', headers: this.headers() }, 10_000);
|
|
67
|
+
if (!res.ok) {
|
|
68
|
+
const body = await res.json().catch(() => ({}));
|
|
69
|
+
const detail = body.detail || res.statusText;
|
|
70
|
+
return { valid: false, error: `HTTP ${res.status}: ${detail}` };
|
|
71
|
+
}
|
|
72
|
+
return { valid: true };
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
76
|
+
return { valid: false, error: message };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** List interventions with optional filters. */
|
|
80
|
+
async listInterventions(filters = {}) {
|
|
81
|
+
const params = new URLSearchParams();
|
|
82
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
83
|
+
if (value !== undefined && value !== null) {
|
|
84
|
+
params.set(key, String(value));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const qs = params.toString();
|
|
88
|
+
const url = `${this.apiUrl}/api/v1/maintenance/${qs ? `?${qs}` : ''}`;
|
|
89
|
+
const res = await this.fetchWithRetry(url, {
|
|
90
|
+
method: 'GET',
|
|
91
|
+
headers: this.headers(),
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
await this.handleError(res);
|
|
95
|
+
}
|
|
96
|
+
return res.json();
|
|
97
|
+
}
|
|
98
|
+
/** Create a new intervention. */
|
|
99
|
+
async createIntervention(data) {
|
|
100
|
+
const res = await this.fetchWithRetry(`${this.apiUrl}/api/v1/maintenance/`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: this.headers(),
|
|
103
|
+
body: JSON.stringify(data),
|
|
104
|
+
});
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
await this.handleError(res);
|
|
107
|
+
}
|
|
108
|
+
return res.json();
|
|
109
|
+
}
|
|
110
|
+
/** Get a single intervention by ID. */
|
|
111
|
+
async getIntervention(id) {
|
|
112
|
+
const res = await this.fetchWithRetry(`${this.apiUrl}/api/v1/maintenance/${id}`, { method: 'GET', headers: this.headers() });
|
|
113
|
+
if (!res.ok) {
|
|
114
|
+
await this.handleError(res);
|
|
115
|
+
}
|
|
116
|
+
return res.json();
|
|
117
|
+
}
|
|
118
|
+
/** Update an intervention. */
|
|
119
|
+
async updateIntervention(id, data) {
|
|
120
|
+
const res = await this.fetchWithRetry(`${this.apiUrl}/api/v1/maintenance/${id}`, {
|
|
121
|
+
method: 'PATCH',
|
|
122
|
+
headers: this.headers(),
|
|
123
|
+
body: JSON.stringify(data),
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok) {
|
|
126
|
+
await this.handleError(res);
|
|
127
|
+
}
|
|
128
|
+
return res.json();
|
|
129
|
+
}
|
|
130
|
+
/** Delete an intervention. */
|
|
131
|
+
async deleteIntervention(id) {
|
|
132
|
+
const res = await this.fetchWithRetry(`${this.apiUrl}/api/v1/maintenance/${id}`, { method: 'DELETE', headers: this.headers() });
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
await this.handleError(res);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Get intervention stats. */
|
|
138
|
+
async getStats() {
|
|
139
|
+
const res = await this.fetchWithRetry(`${this.apiUrl}/api/v1/maintenance/stats`, { method: 'GET', headers: this.headers() });
|
|
140
|
+
if (!res.ok) {
|
|
141
|
+
await this.handleError(res);
|
|
142
|
+
}
|
|
143
|
+
return res.json();
|
|
144
|
+
}
|
|
145
|
+
async handleError(res) {
|
|
146
|
+
const body = await res.json().catch(() => ({}));
|
|
147
|
+
const detail = body.detail || res.statusText;
|
|
148
|
+
throw new Error(`HTTP ${res.status}: ${detail}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for @orbitpanel/cli.
|
|
3
|
+
* Stores config in ~/.orbit/config.json.
|
|
4
|
+
*/
|
|
5
|
+
import type { OrbitConfig, TokenEntry } from '../types.js';
|
|
6
|
+
export declare const DEFAULT_API_URL = "https://api.orbit.principi.it";
|
|
7
|
+
export declare const CONFIG_DIR: string;
|
|
8
|
+
export declare const CONFIG_PATH: string;
|
|
9
|
+
/** File I/O interface — overridable for testing. */
|
|
10
|
+
export interface FileIO {
|
|
11
|
+
read(path: string): Promise<string>;
|
|
12
|
+
write(path: string, data: string): Promise<void>;
|
|
13
|
+
mkdirp(path: string): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function loadConfig(io?: FileIO): Promise<OrbitConfig>;
|
|
16
|
+
export declare function saveConfig(config: OrbitConfig, io?: FileIO): Promise<void>;
|
|
17
|
+
export declare function setToken(siteId: string, entry: TokenEntry, io?: FileIO): Promise<void>;
|
|
18
|
+
export declare function getToken(siteId?: string, io?: FileIO): Promise<string | undefined>;
|
|
19
|
+
export declare function removeToken(siteId: string, io?: FileIO): Promise<void>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for @orbitpanel/cli.
|
|
3
|
+
* Stores config in ~/.orbit/config.json.
|
|
4
|
+
*/
|
|
5
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
export const DEFAULT_API_URL = 'https://api.orbit.principi.it';
|
|
9
|
+
export const CONFIG_DIR = join(homedir(), '.orbit');
|
|
10
|
+
export const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
|
|
11
|
+
const defaultIO = {
|
|
12
|
+
read: (path) => readFile(path, 'utf-8'),
|
|
13
|
+
write: async (path, data) => {
|
|
14
|
+
await writeFile(path, data, { encoding: 'utf-8', mode: 0o600 });
|
|
15
|
+
},
|
|
16
|
+
mkdirp: (path) => mkdir(path, { recursive: true, mode: 0o700 }).then(() => { }),
|
|
17
|
+
};
|
|
18
|
+
function defaultConfig() {
|
|
19
|
+
return { api_url: DEFAULT_API_URL, tokens: {} };
|
|
20
|
+
}
|
|
21
|
+
export async function loadConfig(io = defaultIO) {
|
|
22
|
+
let raw;
|
|
23
|
+
try {
|
|
24
|
+
raw = await io.read(CONFIG_PATH);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// File doesn't exist — return fresh config
|
|
28
|
+
return defaultConfig();
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(raw);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// File exists but is corrupted — warn and return fresh
|
|
35
|
+
console.error(`[orbit] Attenzione: ${CONFIG_PATH} corrotto. Uso config predefinita.`);
|
|
36
|
+
return defaultConfig();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export async function saveConfig(config, io = defaultIO) {
|
|
40
|
+
await io.mkdirp(CONFIG_DIR);
|
|
41
|
+
await io.write(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
42
|
+
}
|
|
43
|
+
export async function setToken(siteId, entry, io = defaultIO) {
|
|
44
|
+
const config = await loadConfig(io);
|
|
45
|
+
config.tokens[siteId] = entry;
|
|
46
|
+
if (!config.default_site) {
|
|
47
|
+
config.default_site = siteId;
|
|
48
|
+
}
|
|
49
|
+
await saveConfig(config, io);
|
|
50
|
+
}
|
|
51
|
+
export async function getToken(siteId, io = defaultIO) {
|
|
52
|
+
const config = await loadConfig(io);
|
|
53
|
+
const id = siteId ?? config.default_site;
|
|
54
|
+
if (!id)
|
|
55
|
+
return undefined;
|
|
56
|
+
return config.tokens[id]?.token;
|
|
57
|
+
}
|
|
58
|
+
export async function removeToken(siteId, io = defaultIO) {
|
|
59
|
+
const config = await loadConfig(io);
|
|
60
|
+
delete config.tokens[siteId];
|
|
61
|
+
if (config.default_site === siteId) {
|
|
62
|
+
const remaining = Object.keys(config.tokens);
|
|
63
|
+
config.default_site = remaining.length > 0 ? remaining[0] : undefined;
|
|
64
|
+
}
|
|
65
|
+
await saveConfig(config, io);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git operations for @orbitpanel/cli.
|
|
3
|
+
* Reads branch, commit, and diff information from the current repo.
|
|
4
|
+
*/
|
|
5
|
+
/** Git command runner — overridable for testing. */
|
|
6
|
+
export interface GitRunner {
|
|
7
|
+
exec(args: string[]): Promise<string>;
|
|
8
|
+
}
|
|
9
|
+
/** Get current git branch name. Returns null if not in a git repo. */
|
|
10
|
+
export declare function getGitBranch(runner?: GitRunner): Promise<string | null>;
|
|
11
|
+
/** Get current HEAD commit hash (short). Returns null on error. */
|
|
12
|
+
export declare function getGitCommitHead(runner?: GitRunner): Promise<string | null>;
|
|
13
|
+
/** Diff stat between two commits. */
|
|
14
|
+
export interface DiffStat {
|
|
15
|
+
files_changed: number;
|
|
16
|
+
raw: string;
|
|
17
|
+
}
|
|
18
|
+
/** Get diff stat between two commits. Returns zero on error. */
|
|
19
|
+
export declare function getGitDiffStat(fromCommit: string, toCommit: string, runner?: GitRunner): Promise<DiffStat>;
|
package/dist/lib/git.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git operations for @orbitpanel/cli.
|
|
3
|
+
* Reads branch, commit, and diff information from the current repo.
|
|
4
|
+
*/
|
|
5
|
+
import { execFile } from 'node:child_process';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
const defaultRunner = {
|
|
9
|
+
exec: async (args) => {
|
|
10
|
+
const { stdout } = await execFileAsync('git', args, { timeout: 5000 });
|
|
11
|
+
return stdout;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
/** Get current git branch name. Returns null if not in a git repo. */
|
|
15
|
+
export async function getGitBranch(runner = defaultRunner) {
|
|
16
|
+
try {
|
|
17
|
+
const output = await runner.exec(['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
18
|
+
return output.trim() || null;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Get current HEAD commit hash (short). Returns null on error. */
|
|
25
|
+
export async function getGitCommitHead(runner = defaultRunner) {
|
|
26
|
+
try {
|
|
27
|
+
const output = await runner.exec(['rev-parse', '--short', 'HEAD']);
|
|
28
|
+
return output.trim() || null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Get diff stat between two commits. Returns zero on error. */
|
|
35
|
+
export async function getGitDiffStat(fromCommit, toCommit, runner = defaultRunner) {
|
|
36
|
+
try {
|
|
37
|
+
const output = await runner.exec(['diff', '--stat', `${fromCommit}..${toCommit}`]);
|
|
38
|
+
const raw = output.trim();
|
|
39
|
+
// Parse "N files changed" from last line
|
|
40
|
+
const match = raw.match(/(\d+)\s+files?\s+changed/);
|
|
41
|
+
const files_changed = match ? parseInt(match[1], 10) : 0;
|
|
42
|
+
return { files_changed, raw };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return { files_changed: 0, raw: '' };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAO1C,MAAM,aAAa,GAAc;IAC/B,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACnB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAoB,aAAa;IAClE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,SAAoB,aAAa;IACtE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QACnE,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAQD,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,QAAgB,EAChB,SAAoB,aAAa;IAEjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC;QACnF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAE1B,yCAAyC;QACzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACpD,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report builder for @orbitpanel/cli.
|
|
3
|
+
* Assembles intervention payload from session data + git info.
|
|
4
|
+
*/
|
|
5
|
+
import type { SessionState } from '../types.js';
|
|
6
|
+
export interface ReportOptions {
|
|
7
|
+
session: SessionState;
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
priority?: string;
|
|
11
|
+
type_tag?: string;
|
|
12
|
+
git_commit_end?: string;
|
|
13
|
+
files_changed?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Build a complete intervention payload ready for POST /api/v1/maintenance/ */
|
|
16
|
+
export declare function buildReportPayload(opts: ReportOptions): Record<string, unknown>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report builder for @orbitpanel/cli.
|
|
3
|
+
* Assembles intervention payload from session data + git info.
|
|
4
|
+
*/
|
|
5
|
+
/** Build a complete intervention payload ready for POST /api/v1/maintenance/ */
|
|
6
|
+
export function buildReportPayload(opts) {
|
|
7
|
+
const { session } = opts;
|
|
8
|
+
// Auto-generate title from session if not provided
|
|
9
|
+
const title = opts.title ?? generateTitle(session);
|
|
10
|
+
// Convert notes to actions_taken format
|
|
11
|
+
const actions_taken = session.notes.map(note => ({
|
|
12
|
+
action: note.text,
|
|
13
|
+
tool_used: 'manual',
|
|
14
|
+
result: 'success',
|
|
15
|
+
timestamp: note.timestamp,
|
|
16
|
+
}));
|
|
17
|
+
// Auto-generate description from notes if not provided
|
|
18
|
+
const description = opts.description ?? generateDescription(session);
|
|
19
|
+
// Build report_data matching backend schema v1.0
|
|
20
|
+
const report_data = {
|
|
21
|
+
findings: [],
|
|
22
|
+
actions_taken,
|
|
23
|
+
blocking_issues: [],
|
|
24
|
+
session: {
|
|
25
|
+
local_session_id: session.id,
|
|
26
|
+
started_at: session.started_at,
|
|
27
|
+
ended_at: new Date().toISOString(),
|
|
28
|
+
git_branch: session.git_branch,
|
|
29
|
+
git_commit_start: session.git_commit_start,
|
|
30
|
+
git_commit_end: opts.git_commit_end,
|
|
31
|
+
files_changed: opts.files_changed ?? 0,
|
|
32
|
+
environment: 'local-dev',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
site_id: session.site_id,
|
|
37
|
+
title,
|
|
38
|
+
description,
|
|
39
|
+
priority: opts.priority ?? 'MEDIUM',
|
|
40
|
+
origin: 'cli',
|
|
41
|
+
status: 'completed',
|
|
42
|
+
type_tag: opts.type_tag,
|
|
43
|
+
report_data,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function generateTitle(session) {
|
|
47
|
+
const parts = ['Sessione locale'];
|
|
48
|
+
if (session.git_branch) {
|
|
49
|
+
parts.push(`— ${session.git_branch}`);
|
|
50
|
+
}
|
|
51
|
+
return parts.join(' ');
|
|
52
|
+
}
|
|
53
|
+
function generateDescription(session) {
|
|
54
|
+
const lines = [];
|
|
55
|
+
lines.push('## Sessione locale');
|
|
56
|
+
lines.push('');
|
|
57
|
+
if (session.git_branch) {
|
|
58
|
+
lines.push(`- Branch: ${session.git_branch}`);
|
|
59
|
+
}
|
|
60
|
+
if (session.git_commit_start) {
|
|
61
|
+
lines.push(`- Commit inizio: ${session.git_commit_start}`);
|
|
62
|
+
}
|
|
63
|
+
if (session.notes.length > 0) {
|
|
64
|
+
lines.push('');
|
|
65
|
+
lines.push('## Note');
|
|
66
|
+
lines.push('');
|
|
67
|
+
for (const note of session.notes) {
|
|
68
|
+
lines.push(`- ${note.text}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return lines.join('\n');
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=report-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-builder.js","sourceRoot":"","sources":["../../src/lib/report-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session management for @orbitpanel/cli.
|
|
3
|
+
* Tracks local work sessions in ~/.orbit/sessions/.
|
|
4
|
+
*/
|
|
5
|
+
import type { SessionState, SessionNote } from '../types.js';
|
|
6
|
+
export declare const SESSIONS_DIR: string;
|
|
7
|
+
/** Session I/O interface — overridable for testing. */
|
|
8
|
+
export interface SessionIO {
|
|
9
|
+
read(path: string): Promise<string>;
|
|
10
|
+
write(path: string, data: string): Promise<void>;
|
|
11
|
+
mkdirp(path: string): Promise<void>;
|
|
12
|
+
list(dir: string): Promise<string[]>;
|
|
13
|
+
}
|
|
14
|
+
/** Create a new session. */
|
|
15
|
+
export declare function createSession(siteId: string, opts: {
|
|
16
|
+
git_branch?: string;
|
|
17
|
+
git_commit?: string;
|
|
18
|
+
note?: string;
|
|
19
|
+
}, io?: SessionIO): Promise<SessionState>;
|
|
20
|
+
/** Load the active session for a site_id. Returns null if none found. */
|
|
21
|
+
export declare function loadActiveSession(siteId: string, io?: SessionIO): Promise<SessionState | null>;
|
|
22
|
+
/** Add a note to an existing session. */
|
|
23
|
+
export declare function addNote(sessionId: string, text: string, priority?: SessionNote['priority'], io?: SessionIO): Promise<SessionState>;
|
|
24
|
+
/** End a session, marking it as completed. */
|
|
25
|
+
export declare function endSession(sessionId: string, opts?: {
|
|
26
|
+
git_commit_end?: string;
|
|
27
|
+
summary?: string;
|
|
28
|
+
}, io?: SessionIO): Promise<SessionState>;
|