@orbitpanel/cli 1.0.5 → 1.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/dist/components/ShellApp.d.ts +13 -5
- package/dist/components/ShellApp.js +40 -29
- package/dist/components/ShellApp.js.map +1 -1
- package/dist/lib/message-queue.d.ts +44 -0
- package/dist/lib/message-queue.js +82 -0
- package/dist/lib/message-queue.js.map +1 -0
- package/oclif.manifest.json +71 -71
- package/package.json +1 -1
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Main Ink shell —
|
|
2
|
+
* Main Ink shell — queue-based UX.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Layout:
|
|
5
|
+
* [Static output + processing status] ← output area (scrolls up)
|
|
6
|
+
* ╭──────────────────────────────╮
|
|
7
|
+
* │ ❯ always available input │ ← ALWAYS visible
|
|
8
|
+
* ╰──────────────────────────────╯
|
|
9
|
+
* suggestions (if typing /)
|
|
10
|
+
* ● site │ ◆ env │ ⎇ branch ← status bar
|
|
11
|
+
*
|
|
12
|
+
* Key change from v1.0.5:
|
|
13
|
+
* - Input box NEVER disappears (no 'processing' mode that hides it)
|
|
14
|
+
* - Processing status shown in Static output area above the box
|
|
15
|
+
* - Serial queue: user can type/submit while previous is processing
|
|
8
16
|
*/
|
|
9
17
|
import { type SelectItem } from './SelectList.js';
|
|
10
18
|
import type { OrbitStore } from '../state/store.js';
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* Main Ink shell —
|
|
3
|
+
* Main Ink shell — queue-based UX.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Layout:
|
|
6
|
+
* [Static output + processing status] ← output area (scrolls up)
|
|
7
|
+
* ╭──────────────────────────────╮
|
|
8
|
+
* │ ❯ always available input │ ← ALWAYS visible
|
|
9
|
+
* ╰──────────────────────────────╯
|
|
10
|
+
* suggestions (if typing /)
|
|
11
|
+
* ● site │ ◆ env │ ⎇ branch ← status bar
|
|
12
|
+
*
|
|
13
|
+
* Key change from v1.0.5:
|
|
14
|
+
* - Input box NEVER disappears (no 'processing' mode that hides it)
|
|
15
|
+
* - Processing status shown in Static output area above the box
|
|
16
|
+
* - Serial queue: user can type/submit while previous is processing
|
|
9
17
|
*/
|
|
10
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
18
|
+
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
11
19
|
import { Box, Text, Static, useInput, useApp, useFocusManager } from 'ink';
|
|
12
20
|
import { StatusBar } from './StatusBar.js';
|
|
13
21
|
import { SuggestionList } from './SuggestionList.js';
|
|
14
22
|
import { SelectList } from './SelectList.js';
|
|
15
23
|
import { getSuggestions } from '../lib/shell-completer.js';
|
|
16
24
|
import { SLASH_COMMANDS } from '../lib/shell-render.js';
|
|
25
|
+
import { createMessageQueue } from '../lib/message-queue.js';
|
|
17
26
|
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
18
27
|
function buildBarProps(store) {
|
|
19
28
|
const { tokenEntry, siteLink, session, gitBranch } = store.getState();
|
|
@@ -33,23 +42,26 @@ export function ShellApp({ store, version, onCommand }) {
|
|
|
33
42
|
const { exit } = useApp();
|
|
34
43
|
const { disableFocus } = useFocusManager();
|
|
35
44
|
useEffect(() => { disableFocus(); }, [disableFocus]);
|
|
36
|
-
const [mode, setMode] = useState('input');
|
|
37
45
|
const [input, setInput] = useState('');
|
|
38
46
|
const [outputItems, setOutputItems] = useState([]);
|
|
39
47
|
const [suggestions, setSuggestions] = useState([]);
|
|
40
48
|
const [selectedIdx, setSelectedIdx] = useState(0);
|
|
41
49
|
const [spinnerFrame, setSpinnerFrame] = useState(0);
|
|
42
50
|
const [barProps, setBarProps] = useState(buildBarProps(store));
|
|
51
|
+
const [selectMode, setSelectMode] = useState(false);
|
|
43
52
|
const [selectState, setSelectState] = useState(null);
|
|
44
|
-
const
|
|
53
|
+
const [queuedItems, setQueuedItems] = useState([]);
|
|
54
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
55
|
+
const suggestionsActive = suggestions.length > 0 && !selectMode;
|
|
56
|
+
// Spinner animation (when processing)
|
|
45
57
|
useEffect(() => {
|
|
46
|
-
if (
|
|
58
|
+
if (!isProcessing)
|
|
47
59
|
return;
|
|
48
60
|
const timer = setInterval(() => {
|
|
49
61
|
setSpinnerFrame(prev => (prev + 1) % SPINNER.length);
|
|
50
62
|
}, 80);
|
|
51
63
|
return () => clearInterval(timer);
|
|
52
|
-
}, [
|
|
64
|
+
}, [isProcessing]);
|
|
53
65
|
const addOutput = useCallback((text) => {
|
|
54
66
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55
67
|
setOutputItems(prev => [...prev, { id, text }]);
|
|
@@ -67,21 +79,27 @@ export function ShellApp({ store, version, onCommand }) {
|
|
|
67
79
|
setSelectedIdx(0);
|
|
68
80
|
}
|
|
69
81
|
}, []);
|
|
70
|
-
/** Show an interactive selection list. Returns selected item or null if cancelled. */
|
|
71
82
|
const showSelect = useCallback((title, items) => {
|
|
72
83
|
return new Promise((resolve) => {
|
|
73
84
|
setSelectState({ items, title, resolve });
|
|
74
|
-
|
|
85
|
+
setSelectMode(true);
|
|
75
86
|
});
|
|
76
87
|
}, []);
|
|
77
88
|
const handleSelectDone = useCallback((item) => {
|
|
78
|
-
if (selectState?.resolve)
|
|
89
|
+
if (selectState?.resolve)
|
|
79
90
|
selectState.resolve(item);
|
|
80
|
-
}
|
|
81
91
|
setSelectState(null);
|
|
82
|
-
|
|
92
|
+
setSelectMode(false);
|
|
83
93
|
}, [selectState]);
|
|
84
|
-
|
|
94
|
+
// Message queue — processes one command at a time
|
|
95
|
+
const queueRef = useRef(createMessageQueue(async (text) => {
|
|
96
|
+
await onCommand(text, addOutput, showSelect);
|
|
97
|
+
refreshBar();
|
|
98
|
+
}, (state) => {
|
|
99
|
+
setQueuedItems(state.messages.filter(m => m.status === 'queued'));
|
|
100
|
+
setIsProcessing(state.isProcessing);
|
|
101
|
+
}));
|
|
102
|
+
const handleSubmit = useCallback((value) => {
|
|
85
103
|
const cmd = value.trim();
|
|
86
104
|
if (!cmd)
|
|
87
105
|
return;
|
|
@@ -93,19 +111,12 @@ export function ShellApp({ store, version, onCommand }) {
|
|
|
93
111
|
exit();
|
|
94
112
|
return;
|
|
95
113
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
catch (err) {
|
|
101
|
-
addOutput(` ✗ Errore: ${err instanceof Error ? err.message : String(err)}`);
|
|
102
|
-
}
|
|
103
|
-
setMode('input');
|
|
104
|
-
refreshBar();
|
|
105
|
-
}, [onCommand, addOutput, showSelect, refreshBar, exit]);
|
|
106
|
-
// Keyboard — only active in INPUT mode
|
|
114
|
+
// Enqueue — queue handles serial processing
|
|
115
|
+
queueRef.current.enqueue(cmd);
|
|
116
|
+
}, [addOutput, exit]);
|
|
117
|
+
// Keyboard — active when NOT in select mode
|
|
107
118
|
useInput((ch, key) => {
|
|
108
|
-
if (
|
|
119
|
+
if (selectMode)
|
|
109
120
|
return;
|
|
110
121
|
if (key.tab || ch === '\t')
|
|
111
122
|
return;
|
|
@@ -155,6 +166,6 @@ export function ShellApp({ store, version, onCommand }) {
|
|
|
155
166
|
updateSuggestions(newVal);
|
|
156
167
|
}
|
|
157
168
|
});
|
|
158
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: outputItems, children: (item) => _jsx(Text, { children: item.text }, item.id) }), _jsx(Text, { children:
|
|
169
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: outputItems, children: (item) => _jsx(Text, { children: item.text }, item.id) }), isProcessing && (_jsxs(Box, { paddingX: 2, marginTop: 1, children: [_jsxs(Text, { color: "yellow", children: [SPINNER[spinnerFrame], " "] }), _jsx(Text, { color: "yellow", children: "elaborazione in corso..." })] })), queuedItems.length > 0 && (_jsx(Box, { paddingX: 2, children: _jsxs(Text, { dimColor: true, children: ["\u23F3 ", queuedItems.length, " in coda", queuedItems.length > 1 ? `: ${queuedItems.map(q => q.text.slice(0, 20)).join(', ')}` : `: ${queuedItems[0]?.text.slice(0, 30)}`] }) })), _jsx(Text, { children: '' }), selectMode && selectState && (_jsx(SelectList, { items: selectState.items, title: selectState.title, onSelect: (item) => handleSelectDone(item), onCancel: () => handleSelectDone(null) })), !selectMode && (_jsxs(Box, { borderStyle: "round", borderColor: isProcessing ? 'yellow' : 'blue', paddingX: 1, children: [_jsx(Text, { color: isProcessing ? 'yellow' : 'blue', bold: true, children: "\u276F " }), _jsx(Text, { children: input }), _jsx(Text, { inverse: true, children: ' ' })] })), suggestionsActive && (_jsx(SuggestionList, { items: suggestions, selectedIndex: selectedIdx })), _jsx(StatusBar, { ...barProps })] }));
|
|
159
170
|
}
|
|
160
171
|
//# sourceMappingURL=ShellApp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShellApp.js","sourceRoot":"","sources":["../../src/components/ShellApp.tsx"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"ShellApp.js","sourceRoot":"","sources":["../../src/components/ShellApp.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serial message queue for @orbitpanel/cli.
|
|
3
|
+
*
|
|
4
|
+
* Allows users to submit multiple prompts while one is being processed.
|
|
5
|
+
* Processes one at a time. No parallelism.
|
|
6
|
+
*
|
|
7
|
+
* State machine per message:
|
|
8
|
+
* queued → processing → completed | failed
|
|
9
|
+
*
|
|
10
|
+
* Pure logic — no UI, no rendering. Used by ShellApp via hook.
|
|
11
|
+
*/
|
|
12
|
+
export type MessageStatus = 'queued' | 'processing' | 'completed' | 'failed';
|
|
13
|
+
export interface QueuedMessage {
|
|
14
|
+
id: string;
|
|
15
|
+
text: string;
|
|
16
|
+
status: MessageStatus;
|
|
17
|
+
/** Set when completed — holds the output text */
|
|
18
|
+
result?: string;
|
|
19
|
+
/** Set when failed */
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface MessageQueueState {
|
|
23
|
+
messages: QueuedMessage[];
|
|
24
|
+
isProcessing: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create a serial message queue.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* const q = createMessageQueue(processOneFn);
|
|
31
|
+
* q.enqueue("ciao"); // starts processing immediately
|
|
32
|
+
* q.enqueue("come stai?"); // queued, will process after first completes
|
|
33
|
+
* q.getState(); // { messages: [...], isProcessing: true }
|
|
34
|
+
*/
|
|
35
|
+
export declare function createMessageQueue(processOne: (text: string) => Promise<void>, onChange?: (state: MessageQueueState) => void): {
|
|
36
|
+
enqueue(text: string): string;
|
|
37
|
+
getState(): MessageQueueState;
|
|
38
|
+
/** Get messages that are currently queued (waiting). */
|
|
39
|
+
getQueued(): QueuedMessage[];
|
|
40
|
+
/** Get the currently processing message, if any. */
|
|
41
|
+
getActive(): QueuedMessage | undefined;
|
|
42
|
+
/** Clear completed/failed messages from history. */
|
|
43
|
+
clearCompleted(): void;
|
|
44
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serial message queue for @orbitpanel/cli.
|
|
3
|
+
*
|
|
4
|
+
* Allows users to submit multiple prompts while one is being processed.
|
|
5
|
+
* Processes one at a time. No parallelism.
|
|
6
|
+
*
|
|
7
|
+
* State machine per message:
|
|
8
|
+
* queued → processing → completed | failed
|
|
9
|
+
*
|
|
10
|
+
* Pure logic — no UI, no rendering. Used by ShellApp via hook.
|
|
11
|
+
*/
|
|
12
|
+
/** Create a unique message ID */
|
|
13
|
+
function msgId() {
|
|
14
|
+
return `msg-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a serial message queue.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* const q = createMessageQueue(processOneFn);
|
|
21
|
+
* q.enqueue("ciao"); // starts processing immediately
|
|
22
|
+
* q.enqueue("come stai?"); // queued, will process after first completes
|
|
23
|
+
* q.getState(); // { messages: [...], isProcessing: true }
|
|
24
|
+
*/
|
|
25
|
+
export function createMessageQueue(processOne, onChange) {
|
|
26
|
+
const messages = [];
|
|
27
|
+
let isProcessing = false;
|
|
28
|
+
function notify() {
|
|
29
|
+
onChange?.({ messages: [...messages], isProcessing });
|
|
30
|
+
}
|
|
31
|
+
async function processNext() {
|
|
32
|
+
if (isProcessing)
|
|
33
|
+
return;
|
|
34
|
+
const next = messages.find(m => m.status === 'queued');
|
|
35
|
+
if (!next)
|
|
36
|
+
return;
|
|
37
|
+
isProcessing = true;
|
|
38
|
+
next.status = 'processing';
|
|
39
|
+
notify();
|
|
40
|
+
try {
|
|
41
|
+
await processOne(next.text);
|
|
42
|
+
next.status = 'completed';
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
next.status = 'failed';
|
|
46
|
+
next.error = err instanceof Error ? err.message : String(err);
|
|
47
|
+
}
|
|
48
|
+
isProcessing = false;
|
|
49
|
+
notify();
|
|
50
|
+
// Process next in queue (if any)
|
|
51
|
+
await processNext();
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
enqueue(text) {
|
|
55
|
+
const id = msgId();
|
|
56
|
+
messages.push({ id, text, status: 'queued' });
|
|
57
|
+
notify();
|
|
58
|
+
// Start processing (non-blocking — don't await here)
|
|
59
|
+
void processNext();
|
|
60
|
+
return id;
|
|
61
|
+
},
|
|
62
|
+
getState() {
|
|
63
|
+
return { messages: [...messages], isProcessing };
|
|
64
|
+
},
|
|
65
|
+
/** Get messages that are currently queued (waiting). */
|
|
66
|
+
getQueued() {
|
|
67
|
+
return messages.filter(m => m.status === 'queued');
|
|
68
|
+
},
|
|
69
|
+
/** Get the currently processing message, if any. */
|
|
70
|
+
getActive() {
|
|
71
|
+
return messages.find(m => m.status === 'processing');
|
|
72
|
+
},
|
|
73
|
+
/** Clear completed/failed messages from history. */
|
|
74
|
+
clearCompleted() {
|
|
75
|
+
const active = messages.filter(m => m.status === 'queued' || m.status === 'processing');
|
|
76
|
+
messages.length = 0;
|
|
77
|
+
messages.push(...active);
|
|
78
|
+
notify();
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=message-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../src/lib/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,iCAAiC;AACjC,SAAS,KAAK;IACZ,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAA2C,EAC3C,QAA6C;IAE7C,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,SAAS,MAAM;QACb,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,UAAU,WAAW;QACxB,IAAI,YAAY;YAAE,OAAO;QAEzB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,YAAY,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC3B,MAAM,EAAE,CAAC;QAET,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,YAAY,GAAG,KAAK,CAAC;QACrB,MAAM,EAAE,CAAC;QAET,iCAAiC;QACjC,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC;IAED,OAAO;QACL,OAAO,CAAC,IAAY;YAClB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9C,MAAM,EAAE,CAAC;YACT,qDAAqD;YACrD,KAAK,WAAW,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,QAAQ;YACN,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;QACnD,CAAC;QAED,wDAAwD;QACxD,SAAS;YACP,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;QACrD,CAAC;QAED,oDAAoD;QACpD,SAAS;YACP,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,oDAAoD;QACpD,cAAc;YACZ,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC;YACxF,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;YACzB,MAAM,EAAE,CAAC;QACX,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/oclif.manifest.json
CHANGED
|
@@ -592,6 +592,76 @@
|
|
|
592
592
|
"add.js"
|
|
593
593
|
]
|
|
594
594
|
},
|
|
595
|
+
"session:end": {
|
|
596
|
+
"aliases": [],
|
|
597
|
+
"args": {},
|
|
598
|
+
"description": "Chiude la sessione attiva, cattura il commit finale\ne mostra un riepilogo del lavoro svolto.",
|
|
599
|
+
"examples": [
|
|
600
|
+
"<%= config.bin %> session end",
|
|
601
|
+
"<%= config.bin %> session end --summary \"Completato refactor homepage\""
|
|
602
|
+
],
|
|
603
|
+
"flags": {
|
|
604
|
+
"summary": {
|
|
605
|
+
"char": "s",
|
|
606
|
+
"description": "Summary finale del lavoro svolto",
|
|
607
|
+
"name": "summary",
|
|
608
|
+
"hasDynamicHelp": false,
|
|
609
|
+
"multiple": false,
|
|
610
|
+
"type": "option"
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
"hasDynamicHelp": false,
|
|
614
|
+
"hiddenAliases": [],
|
|
615
|
+
"id": "session:end",
|
|
616
|
+
"pluginAlias": "@orbitpanel/cli",
|
|
617
|
+
"pluginName": "@orbitpanel/cli",
|
|
618
|
+
"pluginType": "core",
|
|
619
|
+
"strict": true,
|
|
620
|
+
"summary": "Chiude la sessione di lavoro corrente",
|
|
621
|
+
"enableJsonFlag": false,
|
|
622
|
+
"isESM": true,
|
|
623
|
+
"relativePath": [
|
|
624
|
+
"dist",
|
|
625
|
+
"commands",
|
|
626
|
+
"session",
|
|
627
|
+
"end.js"
|
|
628
|
+
]
|
|
629
|
+
},
|
|
630
|
+
"session:start": {
|
|
631
|
+
"aliases": [],
|
|
632
|
+
"args": {},
|
|
633
|
+
"description": "Avvia una sessione di lavoro collegata al sito Orbit.\nCattura automaticamente branch git e commit corrente.",
|
|
634
|
+
"examples": [
|
|
635
|
+
"<%= config.bin %> session start",
|
|
636
|
+
"<%= config.bin %> session start --note \"Refactor homepage\""
|
|
637
|
+
],
|
|
638
|
+
"flags": {
|
|
639
|
+
"note": {
|
|
640
|
+
"char": "n",
|
|
641
|
+
"description": "Nota iniziale sulla sessione",
|
|
642
|
+
"name": "note",
|
|
643
|
+
"hasDynamicHelp": false,
|
|
644
|
+
"multiple": false,
|
|
645
|
+
"type": "option"
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
"hasDynamicHelp": false,
|
|
649
|
+
"hiddenAliases": [],
|
|
650
|
+
"id": "session:start",
|
|
651
|
+
"pluginAlias": "@orbitpanel/cli",
|
|
652
|
+
"pluginName": "@orbitpanel/cli",
|
|
653
|
+
"pluginType": "core",
|
|
654
|
+
"strict": true,
|
|
655
|
+
"summary": "Inizia una sessione di lavoro locale",
|
|
656
|
+
"enableJsonFlag": false,
|
|
657
|
+
"isESM": true,
|
|
658
|
+
"relativePath": [
|
|
659
|
+
"dist",
|
|
660
|
+
"commands",
|
|
661
|
+
"session",
|
|
662
|
+
"start.js"
|
|
663
|
+
]
|
|
664
|
+
},
|
|
595
665
|
"report:send": {
|
|
596
666
|
"aliases": [],
|
|
597
667
|
"args": {},
|
|
@@ -677,77 +747,7 @@
|
|
|
677
747
|
"report",
|
|
678
748
|
"send.js"
|
|
679
749
|
]
|
|
680
|
-
},
|
|
681
|
-
"session:end": {
|
|
682
|
-
"aliases": [],
|
|
683
|
-
"args": {},
|
|
684
|
-
"description": "Chiude la sessione attiva, cattura il commit finale\ne mostra un riepilogo del lavoro svolto.",
|
|
685
|
-
"examples": [
|
|
686
|
-
"<%= config.bin %> session end",
|
|
687
|
-
"<%= config.bin %> session end --summary \"Completato refactor homepage\""
|
|
688
|
-
],
|
|
689
|
-
"flags": {
|
|
690
|
-
"summary": {
|
|
691
|
-
"char": "s",
|
|
692
|
-
"description": "Summary finale del lavoro svolto",
|
|
693
|
-
"name": "summary",
|
|
694
|
-
"hasDynamicHelp": false,
|
|
695
|
-
"multiple": false,
|
|
696
|
-
"type": "option"
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
"hasDynamicHelp": false,
|
|
700
|
-
"hiddenAliases": [],
|
|
701
|
-
"id": "session:end",
|
|
702
|
-
"pluginAlias": "@orbitpanel/cli",
|
|
703
|
-
"pluginName": "@orbitpanel/cli",
|
|
704
|
-
"pluginType": "core",
|
|
705
|
-
"strict": true,
|
|
706
|
-
"summary": "Chiude la sessione di lavoro corrente",
|
|
707
|
-
"enableJsonFlag": false,
|
|
708
|
-
"isESM": true,
|
|
709
|
-
"relativePath": [
|
|
710
|
-
"dist",
|
|
711
|
-
"commands",
|
|
712
|
-
"session",
|
|
713
|
-
"end.js"
|
|
714
|
-
]
|
|
715
|
-
},
|
|
716
|
-
"session:start": {
|
|
717
|
-
"aliases": [],
|
|
718
|
-
"args": {},
|
|
719
|
-
"description": "Avvia una sessione di lavoro collegata al sito Orbit.\nCattura automaticamente branch git e commit corrente.",
|
|
720
|
-
"examples": [
|
|
721
|
-
"<%= config.bin %> session start",
|
|
722
|
-
"<%= config.bin %> session start --note \"Refactor homepage\""
|
|
723
|
-
],
|
|
724
|
-
"flags": {
|
|
725
|
-
"note": {
|
|
726
|
-
"char": "n",
|
|
727
|
-
"description": "Nota iniziale sulla sessione",
|
|
728
|
-
"name": "note",
|
|
729
|
-
"hasDynamicHelp": false,
|
|
730
|
-
"multiple": false,
|
|
731
|
-
"type": "option"
|
|
732
|
-
}
|
|
733
|
-
},
|
|
734
|
-
"hasDynamicHelp": false,
|
|
735
|
-
"hiddenAliases": [],
|
|
736
|
-
"id": "session:start",
|
|
737
|
-
"pluginAlias": "@orbitpanel/cli",
|
|
738
|
-
"pluginName": "@orbitpanel/cli",
|
|
739
|
-
"pluginType": "core",
|
|
740
|
-
"strict": true,
|
|
741
|
-
"summary": "Inizia una sessione di lavoro locale",
|
|
742
|
-
"enableJsonFlag": false,
|
|
743
|
-
"isESM": true,
|
|
744
|
-
"relativePath": [
|
|
745
|
-
"dist",
|
|
746
|
-
"commands",
|
|
747
|
-
"session",
|
|
748
|
-
"start.js"
|
|
749
|
-
]
|
|
750
750
|
}
|
|
751
751
|
},
|
|
752
|
-
"version": "1.0
|
|
752
|
+
"version": "1.1.0"
|
|
753
753
|
}
|