@qodalis/cli 2.0.0-beta.1
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 +603 -0
- package/assets/cli-panel.css +817 -0
- package/package.json +41 -0
- package/public-api.d.mts +2302 -0
- package/public-api.d.ts +2302 -0
- package/public-api.js +16228 -0
- package/public-api.js.map +1 -0
- package/public-api.mjs +16099 -0
- package/public-api.mjs.map +1 -0
- package/wasm/qodalis_cli_wasm_bg.wasm +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
<h1 align="center">Qodalis Web CLI</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">A web-based terminal for Angular, React, and Vue — extensible, themeable, and packed with built-in developer tools.</p>
|
|
4
|
+
|
|
5
|
+
<div align="center">
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@qodalis/cli)
|
|
8
|
+
[](https://www.npmjs.com/package/@qodalis/angular-cli)
|
|
9
|
+
[](https://www.npmjs.com/package/@qodalis/react-cli)
|
|
10
|
+
[](https://www.npmjs.com/package/@qodalis/vue-cli)
|
|
11
|
+
[](https://github.com/qodalis-solutions/web-cli/actions)
|
|
12
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://cli.qodalis.com/">Live Demo</a> ·
|
|
18
|
+
<a href="https://cli.qodalis.com/docs/">Documentation</a> ·
|
|
19
|
+
<a href="https://www.npmjs.com/package/@qodalis/cli">npm</a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
## Packages
|
|
27
|
+
|
|
28
|
+
| Package | Description |
|
|
29
|
+
|---------|-------------|
|
|
30
|
+
| [`@qodalis/cli-core`](https://www.npmjs.com/package/@qodalis/cli-core) | Shared interfaces, models, and types |
|
|
31
|
+
| [`@qodalis/cli`](https://www.npmjs.com/package/@qodalis/cli) | Framework-agnostic terminal engine (50+ built-in commands) |
|
|
32
|
+
| [`@qodalis/angular-cli`](https://www.npmjs.com/package/@qodalis/angular-cli) | Angular wrapper |
|
|
33
|
+
| [`@qodalis/react-cli`](https://www.npmjs.com/package/@qodalis/react-cli) | React wrapper |
|
|
34
|
+
| [`@qodalis/vue-cli`](https://www.npmjs.com/package/@qodalis/vue-cli) | Vue 3 wrapper |
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### Angular
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @qodalis/angular-cli
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { CliModule } from '@qodalis/angular-cli';
|
|
46
|
+
|
|
47
|
+
@NgModule({
|
|
48
|
+
imports: [CliModule],
|
|
49
|
+
})
|
|
50
|
+
export class AppModule {}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Add styles to `angular.json`:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"styles": [
|
|
58
|
+
"node_modules/@qodalis/angular-cli/src/assets/styles.sass"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<!-- Full terminal -->
|
|
65
|
+
<cli [options]="cliOptions" />
|
|
66
|
+
|
|
67
|
+
<!-- Collapsible panel -->
|
|
68
|
+
<cli-panel />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### React
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install @qodalis/react-cli
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { Cli } from '@qodalis/react-cli';
|
|
79
|
+
|
|
80
|
+
function App() {
|
|
81
|
+
return <Cli style={{ width: '100vw', height: '100vh' }} />;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Vue
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm install @qodalis/vue-cli
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<script setup lang="ts">
|
|
93
|
+
import { Cli } from '@qodalis/vue-cli';
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<template>
|
|
97
|
+
<Cli :style="{ width: '100vw', height: '100vh' }" />
|
|
98
|
+
</template>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Configuration (all frameworks)
|
|
102
|
+
|
|
103
|
+
Pass options to customize the terminal:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const options = {
|
|
107
|
+
welcomeMessage: {
|
|
108
|
+
message: '-- your custom welcome message --',
|
|
109
|
+
show: 'daily', // 'never', 'once', 'daily', 'always'
|
|
110
|
+
},
|
|
111
|
+
usersModule: {
|
|
112
|
+
enabled: true,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Built-in Commands
|
|
118
|
+
|
|
119
|
+
### System
|
|
120
|
+
|
|
121
|
+
| Command | Aliases | Description |
|
|
122
|
+
|---------|---------|-------------|
|
|
123
|
+
| `help` | `man` | Show all commands or help for a specific command |
|
|
124
|
+
| `version` | `ver` | Display CLI version and documentation link |
|
|
125
|
+
| `hotkeys` | `shortcuts`, `keys` | Show keyboard shortcuts |
|
|
126
|
+
| `history` | `hist` | Browse and clear command history |
|
|
127
|
+
| `theme` | `themes` | Apply, customize, and save terminal themes (interactive selection with live preview) |
|
|
128
|
+
| `feedback` | `support` | Report bugs or request features on GitHub |
|
|
129
|
+
| `pkg` | `packages` | Install, update, remove, and browse packages |
|
|
130
|
+
|
|
131
|
+
### Utilities
|
|
132
|
+
|
|
133
|
+
| Command | Aliases | Description |
|
|
134
|
+
|---------|---------|-------------|
|
|
135
|
+
| `clear` | `cls` | Clear the terminal (or `Ctrl+L`) |
|
|
136
|
+
| `echo` | `print` | Print text to the terminal |
|
|
137
|
+
| `eval` | `calc`, `js` | Evaluate JavaScript expressions |
|
|
138
|
+
| `sleep` | `wait` | Pause execution for N milliseconds |
|
|
139
|
+
| `time` | `date` | Show current local and UTC time |
|
|
140
|
+
| `uptime` | — | Show session uptime |
|
|
141
|
+
| `uname` | `sysinfo` | System and browser information |
|
|
142
|
+
| `screen` | `display` | Screen, viewport, and terminal dimensions |
|
|
143
|
+
| `open` | — | Open a URL in a new browser tab |
|
|
144
|
+
| `alias` / `unalias` | — | Create and remove command aliases |
|
|
145
|
+
| `yes` | — | Output a string repeatedly |
|
|
146
|
+
| `seq` | `sequence` | Print number sequences |
|
|
147
|
+
| `cal` | `calendar` | Display a monthly calendar |
|
|
148
|
+
|
|
149
|
+
### Developer Tools
|
|
150
|
+
|
|
151
|
+
| Command | Aliases | Description |
|
|
152
|
+
|---------|---------|-------------|
|
|
153
|
+
| `base64` | `b64` | Encode / decode Base64 |
|
|
154
|
+
| `json` | — | Format, minify, and validate JSON |
|
|
155
|
+
| `url` | — | Encode, decode, and parse URLs |
|
|
156
|
+
| `jwt` | — | Decode and inspect JWT tokens |
|
|
157
|
+
| `hash` | — | SHA-256, SHA-1, SHA-384, SHA-512 hashes |
|
|
158
|
+
| `hex` | — | Hex encode/decode and base conversion (2-36) |
|
|
159
|
+
| `color` | `colour` | Convert between hex, rgb, hsl with preview |
|
|
160
|
+
| `random` | `rand` | Random numbers, strings, UUIDs, coin flip, dice |
|
|
161
|
+
| `lorem` | `lipsum` | Generate placeholder text |
|
|
162
|
+
| `timestamp` | `ts`, `epoch` | Convert between Unix timestamps and dates |
|
|
163
|
+
| `convert` | `conv` | Unit conversion (length, weight, temperature, data) |
|
|
164
|
+
| `clipboard` | `cb`, `pbcopy` | Copy to / paste from clipboard |
|
|
165
|
+
|
|
166
|
+
### Users
|
|
167
|
+
|
|
168
|
+
| Command | Aliases | Description |
|
|
169
|
+
|---------|---------|-------------|
|
|
170
|
+
| `whoami` | `me` | Display current user |
|
|
171
|
+
| `su` | `switch-user` | Switch user session |
|
|
172
|
+
| `adduser` | `useradd` | Add a new user |
|
|
173
|
+
| `listusers` | `users` | List all users |
|
|
174
|
+
|
|
175
|
+
## Package Manager
|
|
176
|
+
|
|
177
|
+
Install additional commands at runtime from npm — no rebuild needed.
|
|
178
|
+
|
|
179
|
+

|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pkg browse # Browse available packages
|
|
183
|
+
pkg add guid # Install a package
|
|
184
|
+
pkg remove guid # Remove a package
|
|
185
|
+
pkg update # Update all packages
|
|
186
|
+
pkg update guid@1.0.2 # Pin a specific version
|
|
187
|
+
pkg check # Check for updates
|
|
188
|
+
pkg versions guid # Show all published versions
|
|
189
|
+
pkg source set # Interactively select a package source (CDN)
|
|
190
|
+
pkg source set unpkg # Set package source directly
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Available Packages
|
|
194
|
+
|
|
195
|
+
| Package | Command | Description |
|
|
196
|
+
|---------|---------|-------------|
|
|
197
|
+
| [@qodalis/cli-guid](https://www.npmjs.com/package/@qodalis/cli-guid) | `guid` | Generate and validate UUIDs |
|
|
198
|
+
| [@qodalis/cli-string](https://www.npmjs.com/package/@qodalis/cli-string) | `string` | String manipulation (case, trim, reverse, slug, wc, etc.) |
|
|
199
|
+
| [@qodalis/cli-curl](https://www.npmjs.com/package/@qodalis/cli-curl) | `curl` | HTTP requests (GET, POST, PUT, DELETE) |
|
|
200
|
+
| [@qodalis/cli-todo](https://www.npmjs.com/package/@qodalis/cli-todo) | `todo` | Task management |
|
|
201
|
+
| [@qodalis/cli-regex](https://www.npmjs.com/package/@qodalis/cli-regex) | `regex` | Regular expression testing |
|
|
202
|
+
| [@qodalis/cli-qr](https://www.npmjs.com/package/@qodalis/cli-qr) | `qr` | QR code generation |
|
|
203
|
+
| [@qodalis/cli-speed-test](https://www.npmjs.com/package/@qodalis/cli-speed-test) | `speed-test` | Internet speed test |
|
|
204
|
+
| [@qodalis/cli-server-logs](https://www.npmjs.com/package/@qodalis/cli-server-logs) | `server-logs` | Live server log streaming |
|
|
205
|
+
| [@qodalis/cli-browser-storage](https://www.npmjs.com/package/@qodalis/cli-browser-storage) | `local-storage`, `cookies` | Browser storage operations |
|
|
206
|
+
| [@qodalis/cli-text-to-image](https://www.npmjs.com/package/@qodalis/cli-text-to-image) | `text-to-image` | Generate images from text |
|
|
207
|
+
| [@qodalis/cli-password-generator](https://www.npmjs.com/package/@qodalis/cli-password-generator) | `generate-password` | Password generation |
|
|
208
|
+
|
|
209
|
+
Any npm package with UMD support can also be loaded:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
pkg add lodash
|
|
213
|
+
eval _.map([1, 2, 3], n => n * 2)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Creating a CLI Plugin
|
|
217
|
+
|
|
218
|
+
### Quick Start
|
|
219
|
+
|
|
220
|
+
Scaffold a complete plugin project with a single command:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npx @qodalis/create-cli-plugin
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The interactive prompts will ask for:
|
|
227
|
+
|
|
228
|
+
| Prompt | Description | Example |
|
|
229
|
+
|--------|-------------|---------|
|
|
230
|
+
| **Plugin name** | Lowercase, no spaces, no `cli-` prefix (added automatically) | `weather` |
|
|
231
|
+
| **Description** | Short description of the plugin | `Weather forecasts` |
|
|
232
|
+
| **Processor class name** | PascalCase name for the command processor class | `Weather` |
|
|
233
|
+
|
|
234
|
+
You can also skip the prompts by passing arguments directly:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npx @qodalis/create-cli-plugin --name weather --description "Weather forecasts" --processor-name Weather
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Or install globally:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npm install -g @qodalis/create-cli-plugin
|
|
244
|
+
create-cli-plugin
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Standalone vs Monorepo Mode
|
|
248
|
+
|
|
249
|
+
The tool auto-detects whether you're inside the `web-cli` monorepo:
|
|
250
|
+
|
|
251
|
+
| Mode | Detection | Output directory | Package manager |
|
|
252
|
+
|------|-----------|-----------------|-----------------|
|
|
253
|
+
| **Standalone** | Any directory outside web-cli | `./qodalis-cli-<name>/` | npm or pnpm (auto-detected) |
|
|
254
|
+
| **Monorepo** | Inside web-cli workspace | `packages/plugins/<name>/` | pnpm (workspace) |
|
|
255
|
+
|
|
256
|
+
In monorepo mode, the tool also:
|
|
257
|
+
- Creates `project.json` (Nx build + test targets)
|
|
258
|
+
- Creates `tsconfig.spec.json` (Karma/Jasmine test config)
|
|
259
|
+
- Updates `tsconfig.base.json` with the path alias `@qodalis/cli-<name>` → `dist/<name>`
|
|
260
|
+
|
|
261
|
+
### Generated Project Structure
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
qodalis-cli-weather/ # or packages/plugins/weather/ in monorepo
|
|
265
|
+
package.json # npm package with CJS/ESM/UMD exports
|
|
266
|
+
tsup.config.ts # Build config (library + IIFE bundles)
|
|
267
|
+
tsconfig.json # TypeScript config
|
|
268
|
+
README.md # Auto-generated README
|
|
269
|
+
src/
|
|
270
|
+
public-api.ts # Public exports + ICliModule declaration
|
|
271
|
+
cli-entrypoint.ts # IIFE entrypoint for browser runtime loading
|
|
272
|
+
lib/
|
|
273
|
+
version.ts # LIBRARY_VERSION + API_VERSION constants
|
|
274
|
+
index.ts # Barrel re-exports
|
|
275
|
+
processors/
|
|
276
|
+
cli-weather-command-processor.ts # Command processor (your main logic goes here)
|
|
277
|
+
tests/
|
|
278
|
+
index.spec.ts # Jasmine test scaffold
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Step-by-Step Workflow
|
|
282
|
+
|
|
283
|
+
#### 1. Scaffold the plugin
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
npx @qodalis/create-cli-plugin --name weather
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### 2. Implement your command processor
|
|
290
|
+
|
|
291
|
+
Edit `src/lib/processors/cli-weather-command-processor.ts`:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
import {
|
|
295
|
+
CliProcessCommand,
|
|
296
|
+
DefaultLibraryAuthor,
|
|
297
|
+
ICliCommandProcessor,
|
|
298
|
+
ICliExecutionContext,
|
|
299
|
+
} from '@qodalis/cli-core';
|
|
300
|
+
import { LIBRARY_VERSION } from '../version';
|
|
301
|
+
|
|
302
|
+
export class CliWeatherCommandProcessor implements ICliCommandProcessor {
|
|
303
|
+
command = 'weather';
|
|
304
|
+
description = 'Weather forecasts';
|
|
305
|
+
author = DefaultLibraryAuthor;
|
|
306
|
+
version = LIBRARY_VERSION;
|
|
307
|
+
|
|
308
|
+
// Sub-commands
|
|
309
|
+
processors?: ICliCommandProcessor[] = [
|
|
310
|
+
{
|
|
311
|
+
command: 'forecast',
|
|
312
|
+
description: 'Get weather forecast for a city',
|
|
313
|
+
parameters: [
|
|
314
|
+
{
|
|
315
|
+
name: 'city',
|
|
316
|
+
aliases: ['c'],
|
|
317
|
+
description: 'City name',
|
|
318
|
+
required: true,
|
|
319
|
+
type: 'string',
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
name: 'days',
|
|
323
|
+
aliases: ['d'],
|
|
324
|
+
description: 'Number of days',
|
|
325
|
+
required: false,
|
|
326
|
+
type: 'number',
|
|
327
|
+
defaultValue: '3',
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
processCommand: async (command, context) => {
|
|
331
|
+
const city = command.args['city'];
|
|
332
|
+
const days = parseInt(command.args['days'] ?? '3');
|
|
333
|
+
context.writer.writeln(`Forecast for ${city} (${days} days):`);
|
|
334
|
+
context.writer.writeSuccess('Sunny, 25°C');
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
command: 'current',
|
|
339
|
+
description: 'Get current weather',
|
|
340
|
+
acceptsRawInput: true, // command.value = text after 'current'
|
|
341
|
+
valueRequired: true, // error if no value provided
|
|
342
|
+
processCommand: async (command, context) => {
|
|
343
|
+
context.writer.writeln(`Current weather in ${command.value}: Sunny, 25°C`);
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
// Default handler (runs when user types just 'weather')
|
|
349
|
+
async processCommand(command: CliProcessCommand, context: ICliExecutionContext): Promise<void> {
|
|
350
|
+
context.executor.showHelp(command, context);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### 3. Build the plugin
|
|
356
|
+
|
|
357
|
+
**Standalone:**
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
cd qodalis-cli-weather
|
|
361
|
+
npm run build # or: npx tsup
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Monorepo:**
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
pnpm nx build weather
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Build output goes to `dist/weather/` with three bundles:
|
|
371
|
+
- `public-api.js` (CJS) + `public-api.mjs` (ESM) + `public-api.d.ts` (types)
|
|
372
|
+
- `umd/index.js` (IIFE — self-contained browser bundle for runtime `pkg add`)
|
|
373
|
+
|
|
374
|
+
#### 4. Test the plugin
|
|
375
|
+
|
|
376
|
+
**Standalone:** Add your preferred test runner.
|
|
377
|
+
|
|
378
|
+
**Monorepo:**
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
pnpm nx test weather
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### 5. Publish to npm
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
cd dist/weather # or: cd qodalis-cli-weather/dist
|
|
388
|
+
npm publish --access public
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Users can then install your plugin at runtime in any Qodalis CLI terminal:
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
pkg add @qodalis/cli-weather
|
|
395
|
+
weather forecast --city "New York"
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### The ICliModule Export
|
|
399
|
+
|
|
400
|
+
Every plugin exports an `ICliModule` object in `public-api.ts`. This is how frameworks register your plugin:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { ICliModule } from '@qodalis/cli-core';
|
|
404
|
+
import { CliWeatherCommandProcessor } from './lib/processors/cli-weather-command-processor';
|
|
405
|
+
import { API_VERSION } from './lib/version';
|
|
406
|
+
|
|
407
|
+
export const weatherModule: ICliModule = {
|
|
408
|
+
apiVersion: API_VERSION, // must be >= 2
|
|
409
|
+
name: '@qodalis/cli-weather',
|
|
410
|
+
processors: [new CliWeatherCommandProcessor()],
|
|
411
|
+
};
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
`ICliModule` also supports optional lifecycle hooks and configuration:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
export const weatherModule: ICliModule = {
|
|
418
|
+
apiVersion: 2,
|
|
419
|
+
name: '@qodalis/cli-weather',
|
|
420
|
+
processors: [new CliWeatherCommandProcessor()],
|
|
421
|
+
dependencies: ['@qodalis/cli-curl'], // boot other modules first
|
|
422
|
+
priority: 0, // boot order (lower = first)
|
|
423
|
+
configure(config) { /* ... */ return this; },
|
|
424
|
+
onInit(context) { /* before processors initialize */ },
|
|
425
|
+
onAfterBoot(context) { /* after all modules boot */ },
|
|
426
|
+
onDestroy(context) { /* teardown */ },
|
|
427
|
+
};
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### The IIFE Entrypoint
|
|
431
|
+
|
|
432
|
+
`src/cli-entrypoint.ts` enables runtime loading via `pkg add`. It calls `bootCliModule()` which registers the module with the global `window.__cliModuleRegistry`:
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
import { bootCliModule, ICliModule } from '@qodalis/cli-core';
|
|
436
|
+
import { CliWeatherCommandProcessor } from './lib/processors/cli-weather-command-processor';
|
|
437
|
+
import { API_VERSION } from './lib/version';
|
|
438
|
+
|
|
439
|
+
const module: ICliModule = {
|
|
440
|
+
apiVersion: API_VERSION,
|
|
441
|
+
name: '@qodalis/cli-weather',
|
|
442
|
+
processors: [new CliWeatherCommandProcessor()],
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
bootCliModule(module);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Execution Context API
|
|
449
|
+
|
|
450
|
+
The `ICliExecutionContext` passed to `processCommand` provides:
|
|
451
|
+
|
|
452
|
+
| Property | Description |
|
|
453
|
+
|----------|-------------|
|
|
454
|
+
| `context.writer` | Terminal output — `writeln()`, `writeInfo()`, `writeSuccess()`, `writeError()`, `wrapInColor()` |
|
|
455
|
+
| `context.reader` | User input — `readLine()`, `readPassword()`, `readConfirm()`, `readSelect()`, `readMultiSelect()`, `readNumber()` |
|
|
456
|
+
| `context.executor` | Command execution — `showHelp(command, context)` |
|
|
457
|
+
| `context.clipboard` | Clipboard — `write()`, `read()` |
|
|
458
|
+
| `context.state` | Persistent key-value store |
|
|
459
|
+
| `context.progressBar` | Progress bar widget |
|
|
460
|
+
| `context.spinner` | Spinner widget |
|
|
461
|
+
| `context.terminal` | Raw xterm.js `Terminal` instance |
|
|
462
|
+
| `context.onAbort` | `Subject<void>` for Ctrl+C cancellation |
|
|
463
|
+
| `context.enterFullScreenMode()` | Switch to full-screen TUI mode |
|
|
464
|
+
| `context.createInterval()` / `context.createTimeout()` | Managed timers (auto-cleaned on abort) |
|
|
465
|
+
|
|
466
|
+
### Registering Plugins in Your App
|
|
467
|
+
|
|
468
|
+
#### Angular (via providers)
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { CliModule, resolveCliModuleProvider } from '@qodalis/angular-cli';
|
|
472
|
+
import { weatherModule } from '@qodalis/cli-weather';
|
|
473
|
+
|
|
474
|
+
@NgModule({
|
|
475
|
+
imports: [CliModule],
|
|
476
|
+
providers: [resolveCliModuleProvider(weatherModule)],
|
|
477
|
+
})
|
|
478
|
+
export class AppModule {}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### Angular (via template input)
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
import { weatherModule } from '@qodalis/cli-weather';
|
|
485
|
+
|
|
486
|
+
export class AppComponent {
|
|
487
|
+
modules = [weatherModule];
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
```html
|
|
492
|
+
<cli [modules]="modules" />
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
#### React
|
|
496
|
+
|
|
497
|
+
```tsx
|
|
498
|
+
import { CliConfigProvider, Cli } from '@qodalis/react-cli';
|
|
499
|
+
import { weatherModule } from '@qodalis/cli-weather';
|
|
500
|
+
|
|
501
|
+
function App() {
|
|
502
|
+
return (
|
|
503
|
+
<CliConfigProvider modules={[weatherModule]}>
|
|
504
|
+
<Cli />
|
|
505
|
+
</CliConfigProvider>
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### Vue
|
|
511
|
+
|
|
512
|
+
```vue
|
|
513
|
+
<script setup lang="ts">
|
|
514
|
+
import { CliConfigProvider, Cli } from '@qodalis/vue-cli';
|
|
515
|
+
import { weatherModule } from '@qodalis/cli-weather';
|
|
516
|
+
</script>
|
|
517
|
+
|
|
518
|
+
<template>
|
|
519
|
+
<CliConfigProvider :modules="[weatherModule]">
|
|
520
|
+
<Cli />
|
|
521
|
+
</CliConfigProvider>
|
|
522
|
+
</template>
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Extending with Inline Commands
|
|
526
|
+
|
|
527
|
+
For quick one-off commands without creating a full plugin, implement `ICliCommandProcessor` directly in your app:
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
import {
|
|
531
|
+
ICliCommandProcessor,
|
|
532
|
+
CliProcessCommand,
|
|
533
|
+
ICliExecutionContext,
|
|
534
|
+
} from '@qodalis/cli-core';
|
|
535
|
+
|
|
536
|
+
export class GreetCommandProcessor implements ICliCommandProcessor {
|
|
537
|
+
command = 'greet';
|
|
538
|
+
description = 'Greet someone by name';
|
|
539
|
+
acceptsRawInput = true;
|
|
540
|
+
valueRequired = true;
|
|
541
|
+
|
|
542
|
+
async processCommand(
|
|
543
|
+
command: CliProcessCommand,
|
|
544
|
+
context: ICliExecutionContext,
|
|
545
|
+
): Promise<void> {
|
|
546
|
+
context.writer.writeln(`Hello, ${command.value}!`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Register it with your framework (Angular: `resolveCommandProcessorProvider(GreetCommandProcessor)`, React/Vue: pass via `processors` prop), or wrap it in an inline `ICliModule`:
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
const myModule: ICliModule = {
|
|
555
|
+
apiVersion: 2,
|
|
556
|
+
name: 'my-app-commands',
|
|
557
|
+
processors: [new GreetCommandProcessor()],
|
|
558
|
+
};
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
~$ greet World
|
|
563
|
+
Hello, World!
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## Using the Engine Directly
|
|
567
|
+
|
|
568
|
+
For advanced use cases or non-framework environments, use `CliEngine` directly:
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
import { CliEngine } from '@qodalis/cli';
|
|
572
|
+
|
|
573
|
+
const engine = new CliEngine(document.getElementById('terminal')!, {
|
|
574
|
+
welcomeMessage: { message: 'Welcome!', show: 'always' },
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
engine.registerProcessors([new GreetCommandProcessor()]);
|
|
578
|
+
await engine.start();
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
## Features
|
|
582
|
+
|
|
583
|
+
- **Multi-framework** — Angular, React, Vue, or vanilla JS
|
|
584
|
+
- **Command chaining** with `&&`, `||`, `|`, and `>>` operators
|
|
585
|
+
- **Command history** with arrow key navigation
|
|
586
|
+
- **Tab-like completions** and keyboard shortcuts (`Ctrl+C`, `Ctrl+L`, `Escape`)
|
|
587
|
+
- **Theming** with built-in themes and custom color support
|
|
588
|
+
- **User sessions** with multi-user support
|
|
589
|
+
- **State persistence** across sessions
|
|
590
|
+
- **Interactive prompts** with live preview (select menus with real-time feedback)
|
|
591
|
+
- **Full-screen mode API** for rich TUI commands
|
|
592
|
+
- **Progress bars, spinners, and text animations**
|
|
593
|
+
- **Runtime package installation** from npm
|
|
594
|
+
|
|
595
|
+
## Contributing
|
|
596
|
+
|
|
597
|
+
1. Fork this repository
|
|
598
|
+
2. Create a branch for your feature or bugfix
|
|
599
|
+
3. Submit a pull request
|
|
600
|
+
|
|
601
|
+
## License
|
|
602
|
+
|
|
603
|
+
MIT
|