citadel_cli 1.1.3 → 1.1.5
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 +59 -106
- package/dist/citadel.css +1 -1
- package/dist/citadel.es.js +882 -1447
- package/dist/citadel.umd.js +52 -61
- package/dist/components/Citadel/Citadel.d.ts +18 -5
- package/dist/components/Citadel/__tests__/CitadelTty.test.d.ts +1 -0
- package/dist/components/Citadel/__tests__/InlineController.test.d.ts +1 -0
- package/dist/components/Citadel/__tests__/PanelController.test.d.ts +1 -0
- package/dist/components/Citadel/__tests__/integration.test.d.ts +1 -0
- package/dist/components/Citadel/__tests__/user-journey.test.d.ts +1 -0
- package/dist/components/Citadel/components/CitadelTty.d.ts +9 -0
- package/dist/components/Citadel/config/types.d.ts +6 -0
- package/dist/components/Citadel/controllers/InlineController.d.ts +2 -0
- package/dist/components/Citadel/controllers/PanelController.d.ts +2 -0
- package/dist/components/Citadel/types/command-registry.d.ts +7 -3
- package/dist/examples/basicCommands.d.ts +6 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Citadel CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A keyboard-first command console for the power users of your web apps.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# Use Cases
|
|
6
6
|
|
|
7
7
|
- **API Testing & Debugging**: Execute REST calls, inspect responses, and manipulate cookies/localStorage without leaving your
|
|
8
8
|
application context
|
|
@@ -16,104 +16,94 @@ application context
|
|
|
16
16
|
# Installation
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm
|
|
19
|
+
npm i citadel_cli
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## "Hello world" Example
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
A core concept in Citadel are commands. Commands are things like "user add 1234"
|
|
25
|
+
or "qa1 deploy my_feature_branch". To initialize and add commands:
|
|
26
|
+
|
|
27
|
+
1. Create a `CommandRegistry` instance
|
|
28
|
+
2. Add one or more commands to that registry
|
|
29
|
+
3. Pass the registry to `Citadel`
|
|
25
30
|
|
|
26
31
|
```typescript
|
|
32
|
+
import {
|
|
33
|
+
Citadel,
|
|
34
|
+
CommandRegistry,
|
|
35
|
+
TextCommandResult,
|
|
36
|
+
} from "citadel_cli";
|
|
37
|
+
|
|
38
|
+
// 1. Create the registry
|
|
39
|
+
const registry = new CommandRegistry();
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
// 2. Add commands
|
|
42
|
+
registry.addCommand(
|
|
43
|
+
[
|
|
44
|
+
{ type: "word", name: "greet" },
|
|
45
|
+
{ type: "argument", name: "name", description: "Who are we greeting?" },
|
|
46
|
+
],
|
|
47
|
+
"Say hello to someone", // Description used by the built-in `help` command
|
|
48
|
+
async (args: string[]) => new TextCommandResult(`Hello ${args[0]} world!`)
|
|
49
|
+
);
|
|
29
50
|
|
|
51
|
+
// 3. Pass the registry to the component
|
|
30
52
|
function App() {
|
|
31
|
-
return
|
|
32
|
-
<>
|
|
33
|
-
<Citadel />
|
|
34
|
-
</>
|
|
35
|
-
);
|
|
53
|
+
return <Citadel commandRegistry={registry} />;
|
|
36
54
|
}
|
|
37
55
|
```
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Now this doesn't do much, yet: it just shows the "help" command. You can
|
|
42
|
-
execute it by pressing <kbd>h[Enter]</kbd>. If you do then you should see the
|
|
43
|
-
following:
|
|
44
|
-
|
|
45
|
-

|
|
57
|
+

|
|
46
58
|
|
|
47
|
-
##
|
|
59
|
+
## Command Expansion
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
Citadel CLI uses **auto-expansion** to make entering commands as fast as
|
|
62
|
+
possible. When you type the first letter of a command it automatically expands
|
|
63
|
+
to the full word. For the above example, typing <kbd>g</kbd> would expand
|
|
64
|
+
in-place to `greet ` (with a trailing space) whereupon you can enter in a value
|
|
65
|
+
for the `name` argument.
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
2. Add commands to the registry object via the `addCommand` function
|
|
53
|
-
3. Pass the registry to the `Citadel` component
|
|
67
|
+
## `addCommand` Details
|
|
54
68
|
|
|
55
|
-
|
|
69
|
+
The `addCommand` method has the following signature:
|
|
56
70
|
|
|
71
|
+
```typescript
|
|
72
|
+
addCommand(segments: CommandSegment[], description: string, handler: CommandHandler): void
|
|
57
73
|
```
|
|
58
|
-
import { Citadel, CommandRegistry, TextCommandResult } from "citadel_cli";
|
|
59
|
-
|
|
60
|
-
// 1. Create the registry where your commands will be stored
|
|
61
|
-
const cmdRegistry = new CommandRegistry();
|
|
62
|
-
|
|
63
|
-
// 2. Add a command to the registry. This can be called as many times as you like.
|
|
64
|
-
cmdRegistry.addCommand(
|
|
65
|
-
[
|
|
66
|
-
{ type: 'word', name: 'greet' },
|
|
67
|
-
{ type: 'argument', name: 'name', description: 'Enter your name' }
|
|
68
|
-
],
|
|
69
|
-
'Say hello to the world', // The description of this command. Used by "help".
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// types of command result that we'll cover later.
|
|
74
|
-
async (args: string[]) => new TextCommandResult(`Hello, ${args[0]}!`)
|
|
75
|
-
);
|
|
76
|
-
```
|
|
77
|
-
The first argument to the `addCommand` function is an array of "command
|
|
78
|
-
segments". There are two types of command segments: `word`s and `argument`s.
|
|
79
|
-
Here we are defining a command with two segments named `greet` and `name`.
|
|
80
|
-
`greet` being a `word` segment and `name` being an `argument`.
|
|
75
|
+
`segments[]` - Each `CommandSegment` in this array consists of a `type` (one of
|
|
76
|
+
"word" or "argument"), a `name`, and an optional `description`
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
`description` - Description of the command itself. Used by the built-in help
|
|
79
|
+
command
|
|
84
80
|
|
|
85
|
-
|
|
81
|
+
`handler` - What gets executed when <kbd>Enter</kbd> is pressed. The handler
|
|
82
|
+
must return one of the following:
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
3. Arguments can be single- or double-quoted. This allows users to enter in
|
|
92
|
-
values that have spaces or other special characters.
|
|
84
|
+
- `TextCommandResult`
|
|
85
|
+
- `JsonCommandResult`
|
|
86
|
+
- `ImageCommandResult`
|
|
87
|
+
- `ErrorCommandResult`
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
description ("Say hello..."). This is the text that will be shown by the help
|
|
96
|
-
command.
|
|
89
|
+
### Arguments
|
|
97
90
|
|
|
98
|
-
|
|
91
|
+
1. Each command can have zero or more arguments
|
|
92
|
+
2. Argument values are passed to the handler as a `String[]`
|
|
93
|
+
3. Arguments can be single- or double-quoted
|
|
99
94
|
|
|
100
|
-
|
|
101
|
-
async (args: string[]) => new TextCommandResult(`Hello, ${args[0]}!`)
|
|
102
|
-
```
|
|
95
|
+
### Example Handlers
|
|
103
96
|
|
|
104
|
-
|
|
105
|
-
values for the arguments entered by the user (if any) are passed in to the
|
|
106
|
-
handler as `args: string[]`. What you do inside the handler is completely up to
|
|
107
|
-
your imagination. For example, say you wanted to clear the localstorage:
|
|
97
|
+
Clearing localstorage:
|
|
108
98
|
|
|
109
99
|
```
|
|
110
|
-
async (
|
|
100
|
+
async () => {
|
|
111
101
|
localStorage.clear();
|
|
112
102
|
return new TextCommandResult('localStorage cleared!');
|
|
113
103
|
}
|
|
114
104
|
```
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
Make an HTTP POST with a body containing a given `name`:
|
|
117
107
|
|
|
118
108
|
```
|
|
119
109
|
async (args: string[]) => {
|
|
@@ -128,42 +118,6 @@ async (args: string[]) => {
|
|
|
128
118
|
}
|
|
129
119
|
```
|
|
130
120
|
|
|
131
|
-
At the time of this writing the following command result types are available:
|
|
132
|
-
|
|
133
|
-
- `ErrorCommandResult`
|
|
134
|
-
- `ImageCommandResult`
|
|
135
|
-
- `JsonCommandResult`
|
|
136
|
-
- `TextCommandResult`
|
|
137
|
-
|
|
138
|
-
Back to our `greeting` command. The final code for it (without comments) should
|
|
139
|
-
now look like this:
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
import { CommandRegistry, TextCommandResult } from "citadel_cli";
|
|
143
|
-
|
|
144
|
-
const cmdRegistry = new CommandRegistry();
|
|
145
|
-
|
|
146
|
-
cmdRegistry.addCommand(
|
|
147
|
-
[
|
|
148
|
-
{ type: 'word', name: 'greet' },
|
|
149
|
-
{ type: 'argument', name: 'name', description: 'Enter your name' }
|
|
150
|
-
],
|
|
151
|
-
'Say hello to the world',
|
|
152
|
-
async (args: string[]) => new TextCommandResult(`Hello, ${args[0]}!`)
|
|
153
|
-
);
|
|
154
|
-
```
|
|
155
|
-
Now that the command has been added all that is left is to pass the registry to
|
|
156
|
-
the `Citadel` component:
|
|
157
|
-
|
|
158
|
-
```
|
|
159
|
-
<Citadel commandRegistry={cmdRegistry} />
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
The result of this should look like this:
|
|
163
|
-
|
|
164
|
-

|
|
165
|
-
|
|
166
|
-
Go forth and make your application experience better!
|
|
167
121
|
|
|
168
122
|
## Configuration
|
|
169
123
|
|
|
@@ -180,7 +134,7 @@ const config = {
|
|
|
180
134
|
outputFontSize: '0.875rem',
|
|
181
135
|
resetStateOnHide: false,
|
|
182
136
|
showCitadelKey: '.',
|
|
183
|
-
cursorType: '
|
|
137
|
+
cursorType: 'blink', // 'blink', 'spin', 'solid', or 'bbs'
|
|
184
138
|
cursorSpeed: 530,
|
|
185
139
|
storage: {
|
|
186
140
|
type: 'localStorage',
|
|
@@ -273,4 +227,3 @@ Load your appliation and press <kbd>.</kbd>
|
|
|
273
227
|
- Comment complex logic or non-obvious code
|
|
274
228
|
- Keep functions focused and modular
|
|
275
229
|
- Use consistent formatting (the project uses ESLint and Prettier)
|
|
276
|
-
|
package/dist/citadel.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.
|
|
1
|
+
._panelContainer_1pav9_3{position:fixed;height:var(--citadel-default-height);min-height:var(--citadel-min-height);max-height:var(--citadel-max-height);background-color:var(--citadel-bg);overflow:hidden;width:100%;box-sizing:border-box;margin:0;padding:0;bottom:0;left:0;right:0}._innerContainer_1pav9_19{height:100%;flex:1;width:100%;display:flex;flex-direction:column;margin:0;padding:0}._inputSection_1pav9_29{border-top:1px solid var(--citadel-border);padding:1rem;margin:0;box-sizing:border-box}._resizeHandle_1pav9_36{width:100%;height:6px;background:transparent;cursor:ns-resize;position:absolute;top:-3px;left:0;right:0;z-index:10;-moz-user-select:none;user-select:none;-webkit-user-select:none;pointer-events:all}._resizeHandle_1pav9_36:hover{background:#ffffff1a}@keyframes _citadel_slideUp_1pav9_65{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes _citadel_slideDown_1pav9_69{0%{transform:translateY(0)}to{transform:translateY(100%)}}._citadel_slideUp_1pav9_65{animation:_citadel_slideUp_1pav9_65 .2s ease-out forwards}._citadel_slideDown_1pav9_69{animation:_citadel_slideDown_1pav9_69 .2s ease-out forwards}._inlineContainer_1pav9_73{position:relative;width:100%;height:100%;display:flex;flex-direction:column;background-color:var(--citadel-bg);overflow:hidden;box-sizing:border-box}
|