@qodalis/cli-core 2.0.0-beta.16 → 2.0.0-beta.18
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/package.json +1 -1
- package/public-api.d.mts +1210 -779
- package/public-api.d.ts +1210 -779
- package/public-api.js +422 -136
- package/public-api.js.map +1 -1
- package/public-api.mjs +413 -137
- package/public-api.mjs.map +1 -1
package/public-api.d.mts
CHANGED
|
@@ -22,9 +22,18 @@ type CliProcessCommand = {
|
|
|
22
22
|
*/
|
|
23
23
|
rawCommand: string;
|
|
24
24
|
/**
|
|
25
|
-
* The value of the command
|
|
25
|
+
* The value of the command: the text after the command (and sub-command)
|
|
26
|
+
* words, flags removed, as typed (quotes included). Prefer `positionals`
|
|
27
|
+
* to read arguments.
|
|
26
28
|
*/
|
|
27
29
|
value?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The positional arguments, split like a shell: quotes removed
|
|
32
|
+
* (`"my file.txt"` is one argument), backslash escapes applied, flags
|
|
33
|
+
* excluded. `cat "a b.txt" c.txt` has `['a b.txt', 'c.txt']`. Set by the
|
|
34
|
+
* engine for every command; empty when there are none.
|
|
35
|
+
*/
|
|
36
|
+
positionals?: string[];
|
|
28
37
|
/**
|
|
29
38
|
* The arguments that were entered
|
|
30
39
|
*/
|
|
@@ -366,6 +375,11 @@ interface ICliCommandExecutorService {
|
|
|
366
375
|
* @param context The context in which the command is executed
|
|
367
376
|
*/
|
|
368
377
|
executeCommand(command: string, context: ICliExecutionContext): Promise<void>;
|
|
378
|
+
/**
|
|
379
|
+
* Run a command line and return its output as text instead of showing it
|
|
380
|
+
* (as `$(...)` does); its errors and warnings are still shown.
|
|
381
|
+
*/
|
|
382
|
+
capture?(command: string, context: ICliExecutionContext): Promise<string>;
|
|
369
383
|
/**
|
|
370
384
|
* Register a global parameter handler.
|
|
371
385
|
* Global parameters (e.g. --help, --version) are evaluated for every
|
|
@@ -539,8 +553,22 @@ interface ICliKeyValueStore {
|
|
|
539
553
|
*
|
|
540
554
|
* State is a plain object (`Record<string, any>`). Updates are shallow-merged
|
|
541
555
|
* (top-level keys are replaced, nested objects are not deep-merged).
|
|
542
|
-
* `getState()` returns a
|
|
543
|
-
*
|
|
556
|
+
* `getState()` returns a shallow copy: assigning its top-level keys has no
|
|
557
|
+
* effect, and nested objects must not be mutated in place either; always use
|
|
558
|
+
* `updateState()` to change state.
|
|
559
|
+
*
|
|
560
|
+
* Saved state is loaded once, before the store's command first runs (or by
|
|
561
|
+
* `initialize()`), and merged over the initial state, so keys added to the
|
|
562
|
+
* initial state later are present. Changes are saved with `persist()`, or
|
|
563
|
+
* after every change with `autoPersist`.
|
|
564
|
+
*
|
|
565
|
+
* A store is global by default: one saved state shared by every terminal and
|
|
566
|
+
* tab of the browser. A save writes only the top-level keys this terminal
|
|
567
|
+
* changed (merged into what is saved, under a cross-tab lock), so terminals
|
|
568
|
+
* changing different keys never overwrite each other; for the same key the
|
|
569
|
+
* last save wins. Changes saved elsewhere are applied here, except keys
|
|
570
|
+
* changed here and not saved yet. A store with `scope: 'session'` belongs to
|
|
571
|
+
* one terminal and is never saved.
|
|
544
572
|
*/
|
|
545
573
|
interface ICliStateStore {
|
|
546
574
|
/**
|
|
@@ -555,6 +583,17 @@ interface ICliStateStore {
|
|
|
555
583
|
* @param newState Partial state to merge with the current state
|
|
556
584
|
*/
|
|
557
585
|
updateState(newState: Partial<CliState>): void;
|
|
586
|
+
/**
|
|
587
|
+
* Change the state from its latest saved value and save it, atomically
|
|
588
|
+
* (under a lock shared by all tabs): use it for read-modify-write changes
|
|
589
|
+
* such as adding an item to a list, so terminals changing the same key at
|
|
590
|
+
* once never lose each other's change.
|
|
591
|
+
*
|
|
592
|
+
* ```ts
|
|
593
|
+
* await context.state.update((s) => ({ todos: [...s.todos, todo] }));
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
596
|
+
update(change: (state: CliState) => Partial<CliState>): Promise<void>;
|
|
558
597
|
/**
|
|
559
598
|
* Select a specific property or computed value from the state.
|
|
560
599
|
* @param selector A function to project a slice of the state.
|
|
@@ -572,13 +611,16 @@ interface ICliStateStore {
|
|
|
572
611
|
*/
|
|
573
612
|
reset(): void;
|
|
574
613
|
/**
|
|
575
|
-
* Persist the state to storage.
|
|
614
|
+
* Persist the state to storage (does nothing when no storage is available).
|
|
576
615
|
*/
|
|
577
616
|
persist(): Promise<void>;
|
|
578
617
|
/**
|
|
579
|
-
*
|
|
618
|
+
* Load the saved state, once: later calls resolve when that first load
|
|
619
|
+
* is done and keep changes made since.
|
|
580
620
|
*/
|
|
581
621
|
initialize(): Promise<void>;
|
|
622
|
+
/** Read the saved state again, replacing the current state. */
|
|
623
|
+
reload?(): Promise<void>;
|
|
582
624
|
}
|
|
583
625
|
|
|
584
626
|
/** Ownership metadata attached to files, directories, or other resources */
|
|
@@ -593,96 +635,159 @@ declare const DEFAULT_FILE_PERMISSIONS = "rw-r--r--";
|
|
|
593
635
|
/** Default directory permissions: rwxr-xr-x (755) */
|
|
594
636
|
declare const DEFAULT_DIR_PERMISSIONS = "rwxr-xr-x";
|
|
595
637
|
|
|
638
|
+
/** A single audit log entry */
|
|
639
|
+
interface ICliAuditEntry {
|
|
640
|
+
/** Entry id (server-assigned in server mode) */
|
|
641
|
+
id?: string;
|
|
642
|
+
/** When the event occurred */
|
|
643
|
+
timestamp: number;
|
|
644
|
+
/** Event type (e.g., 'login', 'logout', 'login_failed') */
|
|
645
|
+
event: string;
|
|
646
|
+
/** Username involved */
|
|
647
|
+
username: string;
|
|
648
|
+
/** Optional additional details */
|
|
649
|
+
details?: string;
|
|
650
|
+
/** Id of the user the entry is about, when known */
|
|
651
|
+
userId?: string;
|
|
652
|
+
/** The user who performed the action, when different from `username` */
|
|
653
|
+
actor?: string;
|
|
654
|
+
/** Id of the acting user, when different from the subject */
|
|
655
|
+
actorId?: string;
|
|
656
|
+
/** Extra data (e.g. remote address) */
|
|
657
|
+
metadata?: Record<string, unknown>;
|
|
658
|
+
}
|
|
659
|
+
/** Service for persistent audit logging */
|
|
660
|
+
interface ICliAuditService {
|
|
661
|
+
/** Log an audit entry (timestamp is added automatically) */
|
|
662
|
+
log(entry: Omit<ICliAuditEntry, 'timestamp'>): Promise<void>;
|
|
663
|
+
/** Retrieve audit entries with optional filtering */
|
|
664
|
+
getEntries(options?: {
|
|
665
|
+
limit?: number;
|
|
666
|
+
event?: string;
|
|
667
|
+
username?: string;
|
|
668
|
+
}): Promise<ICliAuditEntry[]>;
|
|
669
|
+
/** Clear all audit entries */
|
|
670
|
+
clear(): Promise<void>;
|
|
671
|
+
}
|
|
672
|
+
|
|
596
673
|
/**
|
|
597
|
-
*
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* Token for the CLI users store service.
|
|
602
|
-
*/
|
|
603
|
-
declare const ICliUsersStoreService_TOKEN = "cli-users-store-service";
|
|
604
|
-
/**
|
|
605
|
-
* Token for the CLI groups store service.
|
|
606
|
-
*/
|
|
607
|
-
declare const ICliGroupsStoreService_TOKEN = "cli-groups-store-service";
|
|
608
|
-
/**
|
|
609
|
-
* Token for the CLI auth service.
|
|
610
|
-
*/
|
|
611
|
-
declare const ICliAuthService_TOKEN = "cli-auth-service";
|
|
612
|
-
/**
|
|
613
|
-
* Token for registering completion providers via module services (multi: true).
|
|
614
|
-
*/
|
|
615
|
-
declare const ICliCompletionProvider_TOKEN = "cli-completion-provider";
|
|
616
|
-
/**
|
|
617
|
-
* Token for the drag-and-drop service.
|
|
618
|
-
*/
|
|
619
|
-
declare const ICliDragDropService_TOKEN = "cli-drag-drop-service";
|
|
620
|
-
/**
|
|
621
|
-
* Token for the file transfer service.
|
|
622
|
-
*/
|
|
623
|
-
declare const ICliFileTransferService_TOKEN = "cli-file-transfer-service";
|
|
624
|
-
/**
|
|
625
|
-
* Token for the translation service.
|
|
626
|
-
*/
|
|
627
|
-
declare const ICliTranslationService_TOKEN = "cli-translation-service";
|
|
628
|
-
/**
|
|
629
|
-
* Token for the permission service.
|
|
630
|
-
*/
|
|
631
|
-
declare const ICliPermissionService_TOKEN = "cli-permission-service";
|
|
632
|
-
/**
|
|
633
|
-
* Token for the file picker provider.
|
|
634
|
-
*/
|
|
635
|
-
declare const ICliFilePickerProvider_TOKEN = "cli-file-picker-provider";
|
|
636
|
-
/**
|
|
637
|
-
* Token for the HTTP client service.
|
|
638
|
-
*/
|
|
639
|
-
declare const ICliHttpClient_TOKEN = "cli-http-client";
|
|
640
|
-
/**
|
|
641
|
-
* Token for the user event service (lifecycle events).
|
|
674
|
+
* A permission an extension uses, declared so tools (`perms --list`,
|
|
675
|
+
* `groupmod --grant` completion, docs) can show it. Declaring is optional:
|
|
676
|
+
* any `resource:action` string can be granted and checked.
|
|
642
677
|
*/
|
|
643
|
-
|
|
678
|
+
interface CliPermissionDefinition {
|
|
679
|
+
/** Permission string, `resource:action` (e.g. `files:chown`). */
|
|
680
|
+
name: string;
|
|
681
|
+
/** Human readable description. */
|
|
682
|
+
description?: string;
|
|
683
|
+
/** Module that declared it (filled in at registration). */
|
|
684
|
+
module?: string;
|
|
685
|
+
}
|
|
686
|
+
/** Registry of permissions declared by modules (`ICliModule.permissions`). */
|
|
687
|
+
interface ICliPermissionRegistry {
|
|
688
|
+
register(definitions: CliPermissionDefinition[], module?: string): void;
|
|
689
|
+
list(): CliPermissionDefinition[];
|
|
690
|
+
get(name: string): CliPermissionDefinition | undefined;
|
|
691
|
+
/** Remove the permissions registered by `module` (when it is unloaded). */
|
|
692
|
+
unregister?(module: string): void;
|
|
693
|
+
}
|
|
694
|
+
/** The identity checks are made against. */
|
|
695
|
+
interface ICliPrincipal {
|
|
696
|
+
/** User id */
|
|
697
|
+
id: string;
|
|
698
|
+
/** Login name (used as file owner) */
|
|
699
|
+
name: string;
|
|
700
|
+
/** Group (role) names */
|
|
701
|
+
groups: string[];
|
|
702
|
+
/** Effective permissions (union of the groups' permissions) */
|
|
703
|
+
permissions: string[];
|
|
704
|
+
}
|
|
705
|
+
/** rwx-style protected resource (files, directories, or anything an extension owns). */
|
|
706
|
+
interface ICliProtectedResource {
|
|
707
|
+
ownership?: ICliOwnership;
|
|
708
|
+
/** 9-char mode string, e.g. `rwxr-x---` */
|
|
709
|
+
permissions?: string;
|
|
710
|
+
}
|
|
711
|
+
type CliAccessAction = 'read' | 'write' | 'execute';
|
|
644
712
|
/**
|
|
645
|
-
*
|
|
713
|
+
* Authorization service. Provided by an auth module (the users module provides
|
|
714
|
+
* one in local and in server mode). Extensions should use the helpers
|
|
715
|
+
* {@link cliAuthorize} / {@link cliCanAccess}, which allow everything when no
|
|
716
|
+
* authorization service is registered.
|
|
646
717
|
*/
|
|
647
|
-
|
|
718
|
+
interface ICliAuthorizationService {
|
|
719
|
+
/** The signed-in principal, or undefined when nobody is signed in. */
|
|
720
|
+
getPrincipal(): ICliPrincipal | undefined;
|
|
721
|
+
/** Does the current principal hold `permission` (wildcards honoured)? */
|
|
722
|
+
can(permission: string): boolean;
|
|
723
|
+
/**
|
|
724
|
+
* rwx check on a resource for the current principal (owner / group / other).
|
|
725
|
+
* Principals holding `*` or any of `bypassPermissions` are always allowed.
|
|
726
|
+
* Resources without a mode or ownership are allowed.
|
|
727
|
+
*/
|
|
728
|
+
canAccess(resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
|
|
729
|
+
}
|
|
730
|
+
/** Thrown when an operation is not permitted. The message is user facing. */
|
|
731
|
+
declare class CliAccessDeniedError extends Error {
|
|
732
|
+
readonly code = "EACCES";
|
|
733
|
+
constructor(message?: string);
|
|
734
|
+
}
|
|
735
|
+
/** True for {@link CliAccessDeniedError} (also across bundle copies). */
|
|
736
|
+
declare function isCliAccessDeniedError(error: unknown): error is CliAccessDeniedError;
|
|
648
737
|
/**
|
|
649
|
-
*
|
|
650
|
-
*
|
|
738
|
+
* Check a permission for the current principal. Returns `true` when no
|
|
739
|
+
* authorization service is registered (no auth module loaded).
|
|
651
740
|
*/
|
|
652
|
-
declare
|
|
741
|
+
declare function cliAuthorize(context: Pick<ICliExecutionContext, 'services'>, permission: string): boolean;
|
|
653
742
|
/**
|
|
654
|
-
*
|
|
655
|
-
*
|
|
743
|
+
* rwx check for the current principal. Returns `true` when no authorization
|
|
744
|
+
* service is registered.
|
|
656
745
|
*/
|
|
657
|
-
declare
|
|
746
|
+
declare function cliCanAccess(context: Pick<ICliExecutionContext, 'services'>, resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
|
|
658
747
|
/**
|
|
659
|
-
*
|
|
748
|
+
* Reference rwx evaluation shared by implementations of
|
|
749
|
+
* {@link ICliAuthorizationService.canAccess}.
|
|
660
750
|
*/
|
|
661
|
-
declare
|
|
751
|
+
declare function cliEvaluateAccess(principal: ICliPrincipal | undefined, resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
|
|
752
|
+
|
|
662
753
|
/**
|
|
663
|
-
*
|
|
754
|
+
* Context passed to completion providers describing the current input state.
|
|
664
755
|
*/
|
|
665
|
-
|
|
666
|
-
|
|
756
|
+
interface ICliCompletionContext {
|
|
757
|
+
/** Full current line text */
|
|
758
|
+
input: string;
|
|
759
|
+
/** Cursor position in the line */
|
|
760
|
+
cursor: number;
|
|
761
|
+
/** The token (word) being completed at the cursor position */
|
|
762
|
+
token: string;
|
|
763
|
+
/** Start index of the token in the input string */
|
|
764
|
+
tokenStart: number;
|
|
765
|
+
/** Index of the token among all tokens (0 = command, 1+ = arguments) */
|
|
766
|
+
tokenIndex: number;
|
|
767
|
+
/** All tokens parsed from the input */
|
|
768
|
+
tokens: string[];
|
|
769
|
+
}
|
|
667
770
|
/**
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* replace it via the DI container.
|
|
771
|
+
* Provides tab-completion candidates for CLI input.
|
|
772
|
+
* Plugins can register providers to extend completion (e.g. file paths, custom values).
|
|
671
773
|
*/
|
|
672
|
-
interface
|
|
774
|
+
interface ICliCompletionProvider {
|
|
673
775
|
/**
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
677
|
-
* @param ownership Owner/group of the resource.
|
|
678
|
-
* @param permissions Permission string (e.g. "rwxr-xr-x").
|
|
679
|
-
* @returns true if allowed.
|
|
776
|
+
* Priority order. Lower values are checked first.
|
|
777
|
+
* Built-in defaults: 100 (commands), 200 (parameters).
|
|
778
|
+
* Plugins should use lower values (e.g. 50) to take precedence for specific commands.
|
|
680
779
|
*/
|
|
681
|
-
|
|
682
|
-
/**
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
780
|
+
priority: number;
|
|
781
|
+
/**
|
|
782
|
+
* Return completion candidates for the current input context.
|
|
783
|
+
* Return an empty array if this provider does not apply.
|
|
784
|
+
*/
|
|
785
|
+
getCompletions(context: ICliCompletionContext): string[] | Promise<string[]>;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
interface ICliDragDropService {
|
|
789
|
+
/** Emits an array of dropped File objects each time files are dropped onto the terminal */
|
|
790
|
+
readonly onFileDrop: Observable<File[]>;
|
|
686
791
|
}
|
|
687
792
|
|
|
688
793
|
/**
|
|
@@ -749,591 +854,733 @@ interface ICliFilePickerProvider {
|
|
|
749
854
|
}
|
|
750
855
|
|
|
751
856
|
/**
|
|
752
|
-
* Represents an
|
|
857
|
+
* Represents an entry in a file listing.
|
|
753
858
|
*/
|
|
754
|
-
interface
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
/** Optional description shown as dimmed italic text after the label */
|
|
760
|
-
description?: string;
|
|
761
|
-
/** Group name — options sharing the same group are displayed under a group header */
|
|
762
|
-
group?: string;
|
|
763
|
-
/** When true, the option is visible but cannot be selected (rendered dimmed) */
|
|
764
|
-
disabled?: boolean;
|
|
859
|
+
interface ICliFileEntry {
|
|
860
|
+
name: string;
|
|
861
|
+
type: 'file' | 'directory';
|
|
862
|
+
size: number;
|
|
863
|
+
modified: string;
|
|
765
864
|
}
|
|
865
|
+
|
|
766
866
|
/**
|
|
767
|
-
*
|
|
867
|
+
* Abstraction for file transfer operations.
|
|
868
|
+
* Default implementation uses browser-native APIs (file picker, download dialog).
|
|
869
|
+
* @qodalis/cli-files overrides with virtual FS backed by IndexedDB.
|
|
768
870
|
*/
|
|
769
|
-
interface
|
|
770
|
-
|
|
771
|
-
|
|
871
|
+
interface ICliFileTransferService {
|
|
872
|
+
readFile(path: string): Promise<string | null>;
|
|
873
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
874
|
+
listFiles(path: string): Promise<ICliFileEntry[]>;
|
|
875
|
+
exists(path: string): Promise<boolean>;
|
|
876
|
+
downloadToBrowser(filename: string, content: string | Blob): void;
|
|
877
|
+
uploadFromBrowser(accept?: string): Promise<{
|
|
878
|
+
name: string;
|
|
879
|
+
content: string;
|
|
880
|
+
} | null>;
|
|
772
881
|
}
|
|
882
|
+
|
|
773
883
|
/**
|
|
774
|
-
* Options for
|
|
884
|
+
* Options for HTTP client requests.
|
|
885
|
+
* Extends standard RequestInit with convenience fields.
|
|
775
886
|
*/
|
|
776
|
-
interface
|
|
777
|
-
/**
|
|
778
|
-
* Pre-filled default value. Shown in the buffer when the prompt opens.
|
|
779
|
-
* The cursor starts at the end of the default text.
|
|
780
|
-
*/
|
|
781
|
-
default?: string;
|
|
887
|
+
interface CliHttpRequestOptions extends Omit<RequestInit, 'method' | 'body'> {
|
|
782
888
|
/**
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
* Return null to accept the input.
|
|
889
|
+
* Request timeout in milliseconds. When set, the request is automatically
|
|
890
|
+
* aborted after this duration. Combines with any existing abort signal.
|
|
786
891
|
*/
|
|
787
|
-
|
|
788
|
-
/** Placeholder text shown dimmed when the buffer is empty */
|
|
789
|
-
placeholder?: string;
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* Options for readSelect and readSelectInline.
|
|
793
|
-
*/
|
|
794
|
-
interface CliSelectOptions {
|
|
795
|
-
/** Pre-select an option by its value */
|
|
796
|
-
default?: string;
|
|
797
|
-
/** Enable type-to-filter. When true, printable keystrokes filter the option list. Default: false. */
|
|
798
|
-
searchable?: boolean;
|
|
799
|
-
/** Callback invoked each time the highlighted option changes */
|
|
800
|
-
onChange?: (value: string) => void;
|
|
801
|
-
}
|
|
802
|
-
/**
|
|
803
|
-
* Options for readMultiSelect.
|
|
804
|
-
*/
|
|
805
|
-
interface CliMultiSelectOptions {
|
|
806
|
-
/** Enable type-to-filter. When true, printable keystrokes filter the option list. Default: false. */
|
|
807
|
-
searchable?: boolean;
|
|
808
|
-
/** Callback invoked each time the set of checked options changes */
|
|
809
|
-
onChange?: (values: string[]) => void;
|
|
810
|
-
}
|
|
811
|
-
/**
|
|
812
|
-
* Options for readNumber input.
|
|
813
|
-
*/
|
|
814
|
-
interface CliNumberOptions {
|
|
815
|
-
/** Minimum allowed value */
|
|
816
|
-
min?: number;
|
|
817
|
-
/** Maximum allowed value */
|
|
818
|
-
max?: number;
|
|
819
|
-
/** Pre-filled default value */
|
|
820
|
-
default?: number;
|
|
821
|
-
}
|
|
822
|
-
/**
|
|
823
|
-
* Options for readDate input.
|
|
824
|
-
*/
|
|
825
|
-
interface CliDateOptions {
|
|
826
|
-
/**
|
|
827
|
-
* Date format string. Supported tokens: YYYY (4-digit year), MM (2-digit month),
|
|
828
|
-
* DD (2-digit day). Separators can be `-`, `/`, or `.`.
|
|
829
|
-
* @default 'YYYY-MM-DD'
|
|
830
|
-
*/
|
|
831
|
-
format?: string;
|
|
832
|
-
/** Minimum allowed date in the same format as `format` */
|
|
833
|
-
min?: string;
|
|
834
|
-
/** Maximum allowed date in the same format as `format` */
|
|
835
|
-
max?: string;
|
|
836
|
-
/** Pre-filled default value */
|
|
837
|
-
default?: string;
|
|
892
|
+
timeout?: number;
|
|
838
893
|
}
|
|
839
894
|
/**
|
|
840
|
-
*
|
|
841
|
-
*
|
|
895
|
+
* HTTP client for making requests from command processors.
|
|
896
|
+
*
|
|
897
|
+
* Automatically merges the command's abort signal so that requests are
|
|
898
|
+
* cancelled when the user presses Ctrl+C. Provides typed convenience
|
|
899
|
+
* methods for common HTTP verbs as well as a raw `fetch()` for cases
|
|
900
|
+
* that need full Response access (streaming, progress, etc.).
|
|
901
|
+
*
|
|
902
|
+
* Available on the execution context as `context.http`.
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* ```ts
|
|
906
|
+
* // Typed JSON response
|
|
907
|
+
* const users = await context.http.get<User[]>('https://api.example.com/users');
|
|
908
|
+
*
|
|
909
|
+
* // POST with body
|
|
910
|
+
* await context.http.post('https://api.example.com/users', { name: 'John' });
|
|
911
|
+
*
|
|
912
|
+
* // Raw fetch for streaming
|
|
913
|
+
* const response = await context.http.fetch('https://example.com/file.zip');
|
|
914
|
+
* const reader = response.body?.getReader();
|
|
915
|
+
* ```
|
|
842
916
|
*/
|
|
843
|
-
interface
|
|
844
|
-
/**
|
|
845
|
-
* Read a line of text input.
|
|
846
|
-
* @param prompt - The prompt text displayed to the user
|
|
847
|
-
* @param options - Optional configuration for default value, validation, and placeholder
|
|
848
|
-
* @returns The entered text, or null if aborted
|
|
849
|
-
*/
|
|
850
|
-
readLine(prompt: string, options?: CliLineOptions): Promise<string | null>;
|
|
917
|
+
interface ICliHttpClient {
|
|
851
918
|
/**
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
919
|
+
* Make a raw HTTP request. Returns the full Response object for cases
|
|
920
|
+
* that need streaming, headers, or status inspection.
|
|
921
|
+
* The command's abort signal is automatically merged.
|
|
855
922
|
*/
|
|
856
|
-
|
|
923
|
+
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
857
924
|
/**
|
|
858
|
-
*
|
|
859
|
-
* @param prompt - The prompt text displayed to the user
|
|
860
|
-
* @param defaultValue - Default value when Enter is pressed without input
|
|
861
|
-
* @returns true for yes, false for no, or null if aborted
|
|
925
|
+
* HTTP GET request. Returns the parsed JSON response body.
|
|
862
926
|
*/
|
|
863
|
-
|
|
927
|
+
get<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
864
928
|
/**
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
868
|
-
* @param selectOptions - Optional configuration for default, search, onChange
|
|
869
|
-
* @returns The selected option's value, or null if aborted
|
|
929
|
+
* HTTP POST request. Automatically serializes the body as JSON
|
|
930
|
+
* (unless body is FormData, Blob, string, or ArrayBuffer).
|
|
931
|
+
* Returns the parsed JSON response body.
|
|
870
932
|
*/
|
|
871
|
-
|
|
933
|
+
post<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
872
934
|
/**
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
* @param options - Array of options to choose from
|
|
876
|
-
* @param selectOptions - Optional configuration for default, search, onChange
|
|
877
|
-
* @returns The selected option's value, or null if aborted
|
|
935
|
+
* HTTP PUT request. Automatically serializes the body as JSON.
|
|
936
|
+
* Returns the parsed JSON response body.
|
|
878
937
|
*/
|
|
879
|
-
|
|
938
|
+
put<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
880
939
|
/**
|
|
881
|
-
*
|
|
882
|
-
*
|
|
883
|
-
* @param options - Array of options with optional pre-checked state
|
|
884
|
-
* @param selectOptions - Optional configuration for search, onChange
|
|
885
|
-
* @returns Array of selected option values, or null if aborted
|
|
940
|
+
* HTTP PATCH request. Automatically serializes the body as JSON.
|
|
941
|
+
* Returns the parsed JSON response body.
|
|
886
942
|
*/
|
|
887
|
-
|
|
943
|
+
patch<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
888
944
|
/**
|
|
889
|
-
*
|
|
890
|
-
* @param prompt - The prompt text displayed to the user
|
|
891
|
-
* @param options - Optional configuration for min, max, and default value
|
|
892
|
-
* @returns The entered number, or null if aborted
|
|
945
|
+
* HTTP DELETE request. Returns the parsed JSON response body (if any).
|
|
893
946
|
*/
|
|
894
|
-
|
|
947
|
+
delete<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
895
948
|
/**
|
|
896
|
-
*
|
|
897
|
-
* @param prompt - The prompt text displayed to the user
|
|
898
|
-
* @param options - Optional configuration for format, min/max range, default
|
|
899
|
-
* @returns The date string in the specified format, or null if aborted
|
|
949
|
+
* HTTP HEAD request. Returns the full Response (no body parsing).
|
|
900
950
|
*/
|
|
901
|
-
|
|
951
|
+
head(url: string, options?: CliHttpRequestOptions): Promise<Response>;
|
|
902
952
|
/**
|
|
903
|
-
*
|
|
904
|
-
* @param prompt - The prompt text displayed to the user
|
|
905
|
-
* @param options - Optional configuration for multiple, accept filter, directory mode
|
|
906
|
-
* @returns Array of selected files with content, or null if cancelled/unsupported
|
|
953
|
+
* HTTP OPTIONS request. Returns the parsed JSON response body.
|
|
907
954
|
*/
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* Context passed to completion providers describing the current input state.
|
|
913
|
-
*/
|
|
914
|
-
interface ICliCompletionContext {
|
|
915
|
-
/** Full current line text */
|
|
916
|
-
input: string;
|
|
917
|
-
/** Cursor position in the line */
|
|
918
|
-
cursor: number;
|
|
919
|
-
/** The token (word) being completed at the cursor position */
|
|
920
|
-
token: string;
|
|
921
|
-
/** Start index of the token in the input string */
|
|
922
|
-
tokenStart: number;
|
|
923
|
-
/** Index of the token among all tokens (0 = command, 1+ = arguments) */
|
|
924
|
-
tokenIndex: number;
|
|
925
|
-
/** All tokens parsed from the input */
|
|
926
|
-
tokens: string[];
|
|
955
|
+
options<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
927
956
|
}
|
|
928
957
|
/**
|
|
929
|
-
*
|
|
930
|
-
*
|
|
958
|
+
* Error thrown by `ICliHttpClient` JSON helpers (`get`, `post`, `put`,
|
|
959
|
+
* `patch`, `delete`, `options`) when the server responds with a non-2xx status.
|
|
960
|
+
*
|
|
961
|
+
* Exposes the HTTP status so callers can react to specific responses
|
|
962
|
+
* (for example, clearing a stored session token on `401`).
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* ```ts
|
|
966
|
+
* try {
|
|
967
|
+
* await context.http.get(url);
|
|
968
|
+
* } catch (e) {
|
|
969
|
+
* if (e instanceof CliHttpError && e.status === 401) {
|
|
970
|
+
* // token expired or revoked
|
|
971
|
+
* }
|
|
972
|
+
* }
|
|
973
|
+
* ```
|
|
931
974
|
*/
|
|
932
|
-
|
|
933
|
-
/**
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
975
|
+
declare class CliHttpError extends Error {
|
|
976
|
+
/** HTTP status code of the failed response */
|
|
977
|
+
readonly status: number;
|
|
978
|
+
/** HTTP status text of the failed response */
|
|
979
|
+
readonly statusText: string;
|
|
980
|
+
/** Parsed JSON error body, when the server returned one */
|
|
981
|
+
readonly body?: unknown | undefined;
|
|
982
|
+
constructor(message: string,
|
|
983
|
+
/** HTTP status code of the failed response */
|
|
984
|
+
status: number,
|
|
985
|
+
/** HTTP status text of the failed response */
|
|
986
|
+
statusText?: string,
|
|
987
|
+
/** Parsed JSON error body, when the server returned one */
|
|
988
|
+
body?: unknown | undefined);
|
|
944
989
|
}
|
|
945
990
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
/**
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
991
|
+
/** A sign-in session as listed by {@link ICliSessionsService}. Never carries a token. */
|
|
992
|
+
interface ICliSessionInfo {
|
|
993
|
+
id: string;
|
|
994
|
+
userId: string;
|
|
995
|
+
userName: string;
|
|
996
|
+
createdAt: number;
|
|
997
|
+
lastActivity: number;
|
|
998
|
+
/** When the session expires if idle; undefined when there is no timeout */
|
|
999
|
+
expiresAt?: number;
|
|
1000
|
+
/** True for the caller's own session */
|
|
1001
|
+
current?: boolean;
|
|
1002
|
+
metadata?: {
|
|
1003
|
+
userAgent?: string;
|
|
1004
|
+
remoteAddress?: string;
|
|
1005
|
+
[key: string]: unknown;
|
|
1006
|
+
};
|
|
959
1007
|
}
|
|
960
1008
|
/**
|
|
961
|
-
*
|
|
1009
|
+
* Lists and revokes sign-in sessions. Implemented locally (sessions of this
|
|
1010
|
+
* browser) and by servers (all sessions). Used by `sessions` / `session-kick`.
|
|
962
1011
|
*/
|
|
963
|
-
interface
|
|
964
|
-
/**
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
/**
|
|
978
|
-
|
|
1012
|
+
interface ICliSessionsService {
|
|
1013
|
+
/** All sessions visible to the caller */
|
|
1014
|
+
list(): Promise<ICliSessionInfo[]>;
|
|
1015
|
+
/** Revoke a session by id */
|
|
1016
|
+
revoke(sessionId: string, reason?: string): Promise<void>;
|
|
1017
|
+
/** Revoke every session of a user (optionally keeping one) */
|
|
1018
|
+
revokeUser(userId: string, options?: {
|
|
1019
|
+
exceptSessionId?: string;
|
|
1020
|
+
reason?: string;
|
|
1021
|
+
}): Promise<void>;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/** Represents a user lifecycle event */
|
|
1025
|
+
interface ICliUserEvent {
|
|
1026
|
+
/** The type of event that occurred */
|
|
1027
|
+
type: 'login' | 'logout' | 'login_failed' | 'user_created' | 'user_deleted' | 'user_updated' | 'password_changed' | 'user_switched' | 'user_disabled' | 'user_enabled' | 'group_created' | 'group_updated' | 'group_deleted' | 'group_member_added' | 'group_member_removed' | 'session_revoked' | 'audit_cleared';
|
|
1028
|
+
/** The user involved in the event (for group events: the acting user) */
|
|
1029
|
+
user: ICliUser;
|
|
1030
|
+
/** The acting user's name, when different from `user` (e.g. an admin) */
|
|
1031
|
+
actor?: string;
|
|
1032
|
+
/** When the event occurred */
|
|
1033
|
+
timestamp: number;
|
|
1034
|
+
/** Optional additional details */
|
|
1035
|
+
details?: string;
|
|
1036
|
+
/** `user_updated`: the user's name before a rename (set only when the name changed) */
|
|
1037
|
+
previousName?: string;
|
|
1038
|
+
}
|
|
1039
|
+
/** Service that emits user lifecycle events for plugins to subscribe to */
|
|
1040
|
+
interface ICliUserEventService {
|
|
1041
|
+
/** Observable stream of user events */
|
|
1042
|
+
readonly events$: Observable<ICliUserEvent>;
|
|
1043
|
+
/** Emit a user event */
|
|
1044
|
+
emit(event: ICliUserEvent): void;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Represents a service that manages user sessions in the CLI
|
|
979
1049
|
*/
|
|
980
|
-
interface
|
|
981
|
-
/**
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
/**
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
complete: () => void;
|
|
992
|
-
/**
|
|
993
|
-
* Set the text of the spinner
|
|
994
|
-
* @param text The text to set
|
|
995
|
-
*/
|
|
996
|
-
setText: (text: string) => void;
|
|
1050
|
+
interface ICliUserSessionService {
|
|
1051
|
+
/** Gets the current user session as a reactive stream */
|
|
1052
|
+
getUserSession(): Observable<ICliUserSession | undefined>;
|
|
1053
|
+
/** Sets the current user session */
|
|
1054
|
+
setUserSession(session: ICliUserSession): Promise<void>;
|
|
1055
|
+
/** Clears the current session (logout) */
|
|
1056
|
+
clearSession(): Promise<void>;
|
|
1057
|
+
/** Persists the current session to storage */
|
|
1058
|
+
persistSession(): Promise<void>;
|
|
1059
|
+
/** Restores a session from storage (called on boot) */
|
|
1060
|
+
restoreSession(): Promise<ICliUserSession | undefined>;
|
|
997
1061
|
}
|
|
998
|
-
|
|
1062
|
+
/**
|
|
1063
|
+
* Represents a service that manages users in the CLI
|
|
1064
|
+
*/
|
|
1065
|
+
interface ICliUsersStoreService {
|
|
1066
|
+
/** Gets users with optional filtering and pagination */
|
|
1067
|
+
getUsers(options?: {
|
|
1068
|
+
query?: string;
|
|
1069
|
+
skip?: number;
|
|
1070
|
+
take?: number;
|
|
1071
|
+
}): Observable<ICliUser[]>;
|
|
1072
|
+
/** Creates a new user */
|
|
1073
|
+
createUser(user: CliAddUser): Promise<ICliUser>;
|
|
1074
|
+
/** Gets a user by id, name, or email */
|
|
1075
|
+
getUser(id: string): Observable<ICliUser | undefined>;
|
|
1076
|
+
/** Updates an existing user */
|
|
1077
|
+
updateUser(id: string, updates: CliUpdateUser): Promise<ICliUser>;
|
|
1078
|
+
/** Deletes a user by id */
|
|
1079
|
+
deleteUser(id: string): Promise<void>;
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Represents a service that manages groups in the CLI
|
|
1083
|
+
*/
|
|
1084
|
+
interface ICliGroupsStoreService {
|
|
1085
|
+
/** Gets all groups */
|
|
1086
|
+
getGroups(): Observable<ICliGroup[]>;
|
|
1087
|
+
/** Gets a group by id or name */
|
|
1088
|
+
getGroup(id: string): Observable<ICliGroup | undefined>;
|
|
1089
|
+
/** Creates a new group (role), optionally with permissions */
|
|
1090
|
+
createGroup(name: string, description?: string, permissions?: string[]): Promise<ICliGroup>;
|
|
1091
|
+
/** Updates a group's description and/or permissions (by id or name) */
|
|
1092
|
+
updateGroup(id: string, updates: {
|
|
1093
|
+
description?: string;
|
|
1094
|
+
permissions?: string[];
|
|
1095
|
+
}): Promise<ICliGroup>;
|
|
1096
|
+
/** Adds a user (id or name) to a group (id or name) */
|
|
1097
|
+
addMember(groupId: string, userId: string): Promise<void>;
|
|
1098
|
+
/** Removes a user (id or name) from a group (id or name) */
|
|
1099
|
+
removeMember(groupId: string, userId: string): Promise<void>;
|
|
1100
|
+
/** Deletes a group by id */
|
|
1101
|
+
deleteGroup(id: string): Promise<void>;
|
|
1102
|
+
/** Gets all users that belong to a group */
|
|
1103
|
+
getGroupMembers(groupId: string): Observable<ICliUser[]>;
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Represents a service that handles authentication in the CLI
|
|
1107
|
+
*/
|
|
1108
|
+
interface ICliAuthService {
|
|
999
1109
|
/**
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1110
|
+
* Authenticates a user and returns a session. `password` may be omitted
|
|
1111
|
+
* only when the implementation allows passwordless sign-in.
|
|
1002
1112
|
*/
|
|
1003
|
-
|
|
1113
|
+
login(username: string, password?: string): Promise<ICliUserSession>;
|
|
1114
|
+
/** Ends the current session (the CLI is left signed out) */
|
|
1115
|
+
logout(): Promise<void>;
|
|
1004
1116
|
/**
|
|
1005
|
-
*
|
|
1117
|
+
* Switch to another user (`su`). Requires the target's password unless
|
|
1118
|
+
* the caller may skip it (implementation-defined, e.g. `users:update`).
|
|
1119
|
+
* Goes through the same lockout, events and audit as `login`.
|
|
1006
1120
|
*/
|
|
1007
|
-
|
|
1008
|
-
};
|
|
1009
|
-
interface ICliTextAnimator extends ICliProgressBar {
|
|
1121
|
+
switchUser?(username: string, password?: string): Promise<ICliUserSession>;
|
|
1010
1122
|
/**
|
|
1011
|
-
*
|
|
1012
|
-
* @param
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1123
|
+
* Sets or updates a user's password.
|
|
1124
|
+
* @param currentPassword The user's current password, when changing one's own
|
|
1125
|
+
* password. Server-backed implementations forward it so the server can
|
|
1126
|
+
* re-check it; local implementations may ignore it.
|
|
1015
1127
|
*/
|
|
1016
|
-
|
|
1128
|
+
setPassword(userId: string, password: string, currentPassword?: string): Promise<void>;
|
|
1129
|
+
/** Verifies a password against stored credentials */
|
|
1130
|
+
verifyPassword(userId: string, password: string): Promise<boolean>;
|
|
1131
|
+
/** Hashes a password with a salt using Web Crypto SHA-256 */
|
|
1132
|
+
hashPassword(password: string, salt: string): Promise<string>;
|
|
1133
|
+
/** Validate password against policy. Returns error message or null if valid. */
|
|
1134
|
+
validatePassword?(password: string): string | null;
|
|
1017
1135
|
}
|
|
1018
1136
|
|
|
1019
1137
|
/**
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1022
|
-
* - `true` or `undefined`: allow the command.
|
|
1023
|
-
* - `false`: block it with the generic message `<command>: permission denied`.
|
|
1024
|
-
* - a non-empty `string`: block it and print this message.
|
|
1025
|
-
* - `{ allowed, message }`: explicit form; `message` is used when `allowed` is false.
|
|
1138
|
+
* Token for the CLI user session service.
|
|
1026
1139
|
*/
|
|
1027
|
-
|
|
1028
|
-
allowed: boolean;
|
|
1029
|
-
message?: string;
|
|
1030
|
-
};
|
|
1140
|
+
declare const ICliUserSessionService_TOKEN: CliToken<ICliUserSessionService>;
|
|
1031
1141
|
/**
|
|
1032
|
-
*
|
|
1033
|
-
* all processors and modules, and can block it.
|
|
1034
|
-
*
|
|
1035
|
-
* Use guards for cross-cutting policies such as authentication, permission
|
|
1036
|
-
* checks, feature flags, maintenance windows or rate limiting, instead of
|
|
1037
|
-
* repeating the check inside each processor.
|
|
1038
|
-
*
|
|
1039
|
-
* ## When guards run
|
|
1040
|
-
*
|
|
1041
|
-
* For each command the executor:
|
|
1042
|
-
* 1. parses the input and resolves the processor (and sub-processor);
|
|
1043
|
-
* 2. handles global parameters such as `--help` (help is never guarded);
|
|
1044
|
-
* 3. extracts the positional value into `command.value`;
|
|
1045
|
-
* 4. **runs the guards**;
|
|
1046
|
-
* 5. validates required values/parameters, runs processor hooks and finally
|
|
1047
|
-
* calls `processCommand`.
|
|
1048
|
-
*
|
|
1049
|
-
* Guards run in ascending `priority` (default `0`). For each guard the executor
|
|
1050
|
-
* calls `appliesTo` (if defined) and skips the guard when it returns `false`;
|
|
1051
|
-
* otherwise it awaits `canActivate`. The **first** guard that blocks stops the
|
|
1052
|
-
* chain: its message is written as an error and the command exits with code
|
|
1053
|
-
* `-1`. A guard that throws (in `appliesTo` or `canActivate`) also blocks the
|
|
1054
|
-
* command, so a broken guard fails closed.
|
|
1055
|
-
*
|
|
1056
|
-
* ## Access to the context
|
|
1057
|
-
*
|
|
1058
|
-
* Both `appliesTo` and `canActivate` receive the {@link ICliExecutionContext}
|
|
1059
|
-
* of the command about to run, so a guard can:
|
|
1060
|
-
* - resolve services with `context.services.get(...)` / `getRequired(...)`
|
|
1061
|
-
* (e.g. a policy, feature-flag or permission service registered by any
|
|
1062
|
-
* module) to decide **what** should be guarded and **whether** it may run;
|
|
1063
|
-
* - inspect `context.userSession` for the signed-in user and their groups;
|
|
1064
|
-
* - read the processor's `metadata` (for example `requireAuth` or
|
|
1065
|
-
* `requiredGroups`) and the parsed `command` (`command.value`, `command.args`);
|
|
1066
|
-
* - prompt the user via `context.reader` (e.g. a confirmation guard).
|
|
1067
|
-
*
|
|
1068
|
-
* Guards should not write to the terminal to report a denial; return a message
|
|
1069
|
-
* instead so the executor prints it consistently.
|
|
1070
|
-
*
|
|
1071
|
-
* ## Registering guards
|
|
1072
|
-
*
|
|
1073
|
-
* The preferred way is the module's `guards` array; the boot sequence
|
|
1074
|
-
* registers each entry as a multi-provider under {@link ICliCommandGuard_TOKEN}.
|
|
1075
|
-
* Several modules can contribute guards; all of them run.
|
|
1076
|
-
*
|
|
1077
|
-
* ```ts
|
|
1078
|
-
* const billingModule: ICliModule = {
|
|
1079
|
-
* apiVersion: 2,
|
|
1080
|
-
* name: 'billing',
|
|
1081
|
-
* processors: [new InvoiceProcessor()],
|
|
1082
|
-
* guards: [billingGuard],
|
|
1083
|
-
* };
|
|
1084
|
-
* ```
|
|
1085
|
-
*
|
|
1086
|
-
* Guards can also be added at runtime (e.g. from `onInit`):
|
|
1087
|
-
*
|
|
1088
|
-
* ```ts
|
|
1089
|
-
* context.services.set({ provide: ICliCommandGuard_TOKEN, useValue: myGuard, multi: true });
|
|
1090
|
-
* ```
|
|
1091
|
-
*
|
|
1092
|
-
* ## Example: policy resolved from a service
|
|
1093
|
-
*
|
|
1094
|
-
* ```ts
|
|
1095
|
-
* const featureFlagGuard: ICliCommandGuard = {
|
|
1096
|
-
* name: 'feature-flags',
|
|
1097
|
-
* // Only guard commands that are behind a flag; the flag list comes from a service
|
|
1098
|
-
* appliesTo: (processor, _command, context) =>
|
|
1099
|
-
* context.services.get<FeatureFlags>(FeatureFlags_TOKEN)?.isFlagged(processor.command) ?? false,
|
|
1100
|
-
* canActivate: async (_command, processor, context) => {
|
|
1101
|
-
* const flags = context.services.getRequired<FeatureFlags>(FeatureFlags_TOKEN);
|
|
1102
|
-
* return (await flags.isEnabled(processor.command, context.userSession?.user))
|
|
1103
|
-
* ? true
|
|
1104
|
-
* : `${processor.command}: not available for your account`;
|
|
1105
|
-
* },
|
|
1106
|
-
* };
|
|
1107
|
-
* ```
|
|
1108
|
-
*
|
|
1109
|
-
* ## Without a guard-providing module
|
|
1110
|
-
*
|
|
1111
|
-
* Guards are opt-in. When no guard is registered every command runs as before.
|
|
1112
|
-
* The engine registers three built-in guards that enforce the processor access
|
|
1113
|
-
* metadata (`requireAuth`, `requiredGroups`, `requiredPermissions`); they stay
|
|
1114
|
-
* inactive until an auth module (e.g. `@qodalis/cli-users`) registers an
|
|
1115
|
-
* `ICliAuthorizationService`, so without one that metadata is informational.
|
|
1142
|
+
* Token for the CLI users store service.
|
|
1116
1143
|
*/
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1144
|
+
declare const ICliUsersStoreService_TOKEN: CliToken<ICliUsersStoreService>;
|
|
1145
|
+
/**
|
|
1146
|
+
* Token for the CLI groups store service.
|
|
1147
|
+
*/
|
|
1148
|
+
declare const ICliGroupsStoreService_TOKEN: CliToken<ICliGroupsStoreService>;
|
|
1149
|
+
/**
|
|
1150
|
+
* Token for the CLI auth service.
|
|
1151
|
+
*/
|
|
1152
|
+
declare const ICliAuthService_TOKEN: CliToken<ICliAuthService>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Token for registering completion providers via module services (multi: true).
|
|
1155
|
+
*/
|
|
1156
|
+
declare const ICliCompletionProvider_TOKEN: CliToken<ICliCompletionProvider>;
|
|
1157
|
+
/**
|
|
1158
|
+
* Token for the drag-and-drop service.
|
|
1159
|
+
*/
|
|
1160
|
+
declare const ICliDragDropService_TOKEN: CliToken<ICliDragDropService>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Token for the file transfer service.
|
|
1163
|
+
*/
|
|
1164
|
+
declare const ICliFileTransferService_TOKEN: CliToken<ICliFileTransferService>;
|
|
1165
|
+
/**
|
|
1166
|
+
* Token for the translation service.
|
|
1167
|
+
*/
|
|
1168
|
+
declare const ICliTranslationService_TOKEN: CliToken<ICliTranslationService>;
|
|
1169
|
+
/**
|
|
1170
|
+
* Token for the permission service.
|
|
1171
|
+
*/
|
|
1172
|
+
declare const ICliPermissionService_TOKEN: CliToken<ICliPermissionService>;
|
|
1173
|
+
/**
|
|
1174
|
+
* Token for the file picker provider.
|
|
1175
|
+
*/
|
|
1176
|
+
declare const ICliFilePickerProvider_TOKEN: CliToken<ICliFilePickerProvider>;
|
|
1177
|
+
/**
|
|
1178
|
+
* Token for the HTTP client service.
|
|
1179
|
+
*/
|
|
1180
|
+
declare const ICliHttpClient_TOKEN: CliToken<ICliHttpClient>;
|
|
1181
|
+
/**
|
|
1182
|
+
* Token for the user event service (lifecycle events).
|
|
1183
|
+
*/
|
|
1184
|
+
declare const ICliUserEventService_TOKEN: CliToken<ICliUserEventService>;
|
|
1185
|
+
/**
|
|
1186
|
+
* Token for the audit service (persistent event logging).
|
|
1187
|
+
*/
|
|
1188
|
+
declare const ICliAuditService_TOKEN: CliToken<ICliAuditService>;
|
|
1189
|
+
/**
|
|
1190
|
+
* Token for the authorization service ({@link ICliAuthorizationService}).
|
|
1191
|
+
* Provided by an auth module (e.g. `@qodalis/cli-users`); absent otherwise.
|
|
1192
|
+
*/
|
|
1193
|
+
declare const ICliAuthorizationService_TOKEN: CliToken<ICliAuthorizationService>;
|
|
1194
|
+
/**
|
|
1195
|
+
* Token for the permission registry ({@link ICliPermissionRegistry}).
|
|
1196
|
+
* Always provided by the CLI engine.
|
|
1197
|
+
*/
|
|
1198
|
+
declare const ICliPermissionRegistry_TOKEN: CliToken<ICliPermissionRegistry>;
|
|
1199
|
+
/**
|
|
1200
|
+
* Token for the sessions service ({@link ICliSessionsService}).
|
|
1201
|
+
*/
|
|
1202
|
+
declare const ICliSessionsService_TOKEN: CliToken<ICliSessionsService>;
|
|
1203
|
+
/**
|
|
1204
|
+
* Token for the persistent key-value store used by modules (setup state, etc.).
|
|
1205
|
+
*/
|
|
1206
|
+
declare const ICliKeyValueStore_TOKEN: CliToken<ICliKeyValueStore>;
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Abstract permission service for checking rwx permissions on resources.
|
|
1210
|
+
* The default implementation lives in @qodalis/cli-users; consumers can
|
|
1211
|
+
* replace it via the DI container.
|
|
1212
|
+
*/
|
|
1213
|
+
interface ICliPermissionService {
|
|
1128
1214
|
/**
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1215
|
+
* Check whether a user may perform an action on a resource.
|
|
1216
|
+
* @param user The acting user.
|
|
1217
|
+
* @param action The requested operation.
|
|
1218
|
+
* @param ownership Owner/group of the resource.
|
|
1219
|
+
* @param permissions Permission string (e.g. "rwxr-xr-x").
|
|
1220
|
+
* @returns true if allowed.
|
|
1131
1221
|
*/
|
|
1132
|
-
|
|
1222
|
+
check(user: ICliUser, action: 'read' | 'write' | 'execute', ownership: ICliOwnership, permissions: string): boolean;
|
|
1223
|
+
/** Parse octal (e.g. "755") to a permission string (e.g. "rwxr-xr-x"). */
|
|
1224
|
+
parseOctal(octal: string): string;
|
|
1225
|
+
/** Convert a permission string (e.g. "rwxr-xr-x") to octal (e.g. "755"). */
|
|
1226
|
+
toOctal(permissions: string): string;
|
|
1133
1227
|
}
|
|
1134
|
-
/** DI token for {@link ICliCommandGuard}; register guards as multi-providers. */
|
|
1135
|
-
declare const ICliCommandGuard_TOKEN = "cli-command-guard";
|
|
1136
1228
|
|
|
1137
1229
|
/**
|
|
1138
|
-
*
|
|
1139
|
-
* `groupmod --grant` completion, docs) can show it. Declaring is optional:
|
|
1140
|
-
* any `resource:action` string can be granted and checked.
|
|
1230
|
+
* Represents an option for the readSelect and readSelectInline prompts.
|
|
1141
1231
|
*/
|
|
1142
|
-
interface
|
|
1143
|
-
/**
|
|
1144
|
-
|
|
1145
|
-
/**
|
|
1232
|
+
interface CliSelectOption {
|
|
1233
|
+
/** Display text shown to the user */
|
|
1234
|
+
label: string;
|
|
1235
|
+
/** Value returned when this option is selected */
|
|
1236
|
+
value: string;
|
|
1237
|
+
/** Optional description shown as dimmed italic text after the label */
|
|
1146
1238
|
description?: string;
|
|
1147
|
-
/**
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
interface ICliPermissionRegistry {
|
|
1152
|
-
register(definitions: CliPermissionDefinition[], module?: string): void;
|
|
1153
|
-
list(): CliPermissionDefinition[];
|
|
1154
|
-
get(name: string): CliPermissionDefinition | undefined;
|
|
1155
|
-
}
|
|
1156
|
-
/** The identity checks are made against. */
|
|
1157
|
-
interface ICliPrincipal {
|
|
1158
|
-
/** User id */
|
|
1159
|
-
id: string;
|
|
1160
|
-
/** Login name (used as file owner) */
|
|
1161
|
-
name: string;
|
|
1162
|
-
/** Group (role) names */
|
|
1163
|
-
groups: string[];
|
|
1164
|
-
/** Effective permissions (union of the groups' permissions) */
|
|
1165
|
-
permissions: string[];
|
|
1239
|
+
/** Group name — options sharing the same group are displayed under a group header */
|
|
1240
|
+
group?: string;
|
|
1241
|
+
/** When true, the option is visible but cannot be selected (rendered dimmed) */
|
|
1242
|
+
disabled?: boolean;
|
|
1166
1243
|
}
|
|
1167
|
-
/**
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1244
|
+
/**
|
|
1245
|
+
* Represents an option for the readMultiSelect prompt.
|
|
1246
|
+
*/
|
|
1247
|
+
interface CliMultiSelectOption extends CliSelectOption {
|
|
1248
|
+
/** Whether the option is pre-selected */
|
|
1249
|
+
checked?: boolean;
|
|
1172
1250
|
}
|
|
1173
|
-
type CliAccessAction = 'read' | 'write' | 'execute';
|
|
1174
1251
|
/**
|
|
1175
|
-
*
|
|
1176
|
-
* one in local and in server mode). Extensions should use the helpers
|
|
1177
|
-
* {@link cliAuthorize} / {@link cliCanAccess}, which allow everything when no
|
|
1178
|
-
* authorization service is registered.
|
|
1252
|
+
* Options for readLine input.
|
|
1179
1253
|
*/
|
|
1180
|
-
interface
|
|
1181
|
-
/** The signed-in principal, or undefined when nobody is signed in. */
|
|
1182
|
-
getPrincipal(): ICliPrincipal | undefined;
|
|
1183
|
-
/** Does the current principal hold `permission` (wildcards honoured)? */
|
|
1184
|
-
can(permission: string): boolean;
|
|
1254
|
+
interface CliLineOptions {
|
|
1185
1255
|
/**
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
* Resources without a mode or ownership are allowed.
|
|
1256
|
+
* Pre-filled default value. Shown in the buffer when the prompt opens.
|
|
1257
|
+
* The cursor starts at the end of the default text.
|
|
1189
1258
|
*/
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1259
|
+
default?: string;
|
|
1260
|
+
/**
|
|
1261
|
+
* Validation function called on Enter.
|
|
1262
|
+
* Return an error message string to reject the input and display the error.
|
|
1263
|
+
* Return null to accept the input.
|
|
1264
|
+
*/
|
|
1265
|
+
validate?: (value: string) => string | null;
|
|
1266
|
+
/** Placeholder text shown dimmed when the buffer is empty */
|
|
1267
|
+
placeholder?: string;
|
|
1196
1268
|
}
|
|
1197
|
-
/** True for {@link CliAccessDeniedError} (also across bundle copies). */
|
|
1198
|
-
declare function isCliAccessDeniedError(error: unknown): error is CliAccessDeniedError;
|
|
1199
1269
|
/**
|
|
1200
|
-
*
|
|
1201
|
-
* authorization service is registered (no auth module loaded).
|
|
1202
|
-
*/
|
|
1203
|
-
declare function cliAuthorize(context: Pick<ICliExecutionContext, 'services'>, permission: string): boolean;
|
|
1204
|
-
/**
|
|
1205
|
-
* rwx check for the current principal. Returns `true` when no authorization
|
|
1206
|
-
* service is registered.
|
|
1270
|
+
* Options for readSelect and readSelectInline.
|
|
1207
1271
|
*/
|
|
1208
|
-
|
|
1272
|
+
interface CliSelectOptions {
|
|
1273
|
+
/** Pre-select an option by its value */
|
|
1274
|
+
default?: string;
|
|
1275
|
+
/** Enable type-to-filter. When true, printable keystrokes filter the option list. Default: false. */
|
|
1276
|
+
searchable?: boolean;
|
|
1277
|
+
/** Callback invoked each time the highlighted option changes */
|
|
1278
|
+
onChange?: (value: string) => void;
|
|
1279
|
+
}
|
|
1209
1280
|
/**
|
|
1210
|
-
*
|
|
1211
|
-
* {@link ICliAuthorizationService.canAccess}.
|
|
1281
|
+
* Options for readMultiSelect.
|
|
1212
1282
|
*/
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
userId: string;
|
|
1219
|
-
userName: string;
|
|
1220
|
-
createdAt: number;
|
|
1221
|
-
lastActivity: number;
|
|
1222
|
-
/** When the session expires if idle; undefined when there is no timeout */
|
|
1223
|
-
expiresAt?: number;
|
|
1224
|
-
/** True for the caller's own session */
|
|
1225
|
-
current?: boolean;
|
|
1226
|
-
metadata?: {
|
|
1227
|
-
userAgent?: string;
|
|
1228
|
-
remoteAddress?: string;
|
|
1229
|
-
[key: string]: unknown;
|
|
1230
|
-
};
|
|
1283
|
+
interface CliMultiSelectOptions {
|
|
1284
|
+
/** Enable type-to-filter. When true, printable keystrokes filter the option list. Default: false. */
|
|
1285
|
+
searchable?: boolean;
|
|
1286
|
+
/** Callback invoked each time the set of checked options changes */
|
|
1287
|
+
onChange?: (values: string[]) => void;
|
|
1231
1288
|
}
|
|
1232
1289
|
/**
|
|
1233
|
-
*
|
|
1234
|
-
* browser) and by servers (all sessions). Used by `sessions` / `session-kick`.
|
|
1290
|
+
* Options for readNumber input.
|
|
1235
1291
|
*/
|
|
1236
|
-
interface
|
|
1237
|
-
/**
|
|
1238
|
-
|
|
1239
|
-
/**
|
|
1240
|
-
|
|
1241
|
-
/**
|
|
1242
|
-
|
|
1243
|
-
exceptSessionId?: string;
|
|
1244
|
-
reason?: string;
|
|
1245
|
-
}): Promise<void>;
|
|
1292
|
+
interface CliNumberOptions {
|
|
1293
|
+
/** Minimum allowed value */
|
|
1294
|
+
min?: number;
|
|
1295
|
+
/** Maximum allowed value */
|
|
1296
|
+
max?: number;
|
|
1297
|
+
/** Pre-filled default value */
|
|
1298
|
+
default?: number;
|
|
1246
1299
|
}
|
|
1247
|
-
|
|
1248
1300
|
/**
|
|
1249
|
-
*
|
|
1301
|
+
* Options for readDate input.
|
|
1250
1302
|
*/
|
|
1251
|
-
interface
|
|
1252
|
-
/**
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
/**
|
|
1259
|
-
|
|
1260
|
-
/**
|
|
1261
|
-
|
|
1303
|
+
interface CliDateOptions {
|
|
1304
|
+
/**
|
|
1305
|
+
* Date format string. Supported tokens: YYYY (4-digit year), MM (2-digit month),
|
|
1306
|
+
* DD (2-digit day). Separators can be `-`, `/`, or `.`.
|
|
1307
|
+
* @default 'YYYY-MM-DD'
|
|
1308
|
+
*/
|
|
1309
|
+
format?: string;
|
|
1310
|
+
/** Minimum allowed date in the same format as `format` */
|
|
1311
|
+
min?: string;
|
|
1312
|
+
/** Maximum allowed date in the same format as `format` */
|
|
1313
|
+
max?: string;
|
|
1314
|
+
/** Pre-filled default value */
|
|
1315
|
+
default?: string;
|
|
1262
1316
|
}
|
|
1263
1317
|
/**
|
|
1264
|
-
*
|
|
1318
|
+
* Provides interactive input reading from the terminal.
|
|
1319
|
+
* All methods resolve with `null` when the user aborts (Ctrl+C or Escape).
|
|
1265
1320
|
*/
|
|
1266
|
-
interface
|
|
1267
|
-
/**
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1321
|
+
interface ICliInputReader {
|
|
1322
|
+
/**
|
|
1323
|
+
* Read a line of text input.
|
|
1324
|
+
* @param prompt - The prompt text displayed to the user
|
|
1325
|
+
* @param options - Optional configuration for default value, validation, and placeholder
|
|
1326
|
+
* @returns The entered text, or null if aborted
|
|
1327
|
+
*/
|
|
1328
|
+
readLine(prompt: string, options?: CliLineOptions): Promise<string | null>;
|
|
1329
|
+
/**
|
|
1330
|
+
* Read a password (masked input).
|
|
1331
|
+
* @param prompt - The prompt text displayed to the user
|
|
1332
|
+
* @returns The entered password, or null if aborted
|
|
1333
|
+
*/
|
|
1334
|
+
readPassword(prompt: string): Promise<string | null>;
|
|
1335
|
+
/**
|
|
1336
|
+
* Read a yes/no confirmation.
|
|
1337
|
+
* @param prompt - The prompt text displayed to the user
|
|
1338
|
+
* @param defaultValue - Default value when Enter is pressed without input
|
|
1339
|
+
* @returns true for yes, false for no, or null if aborted
|
|
1340
|
+
*/
|
|
1341
|
+
readConfirm(prompt: string, defaultValue?: boolean): Promise<boolean | null>;
|
|
1342
|
+
/**
|
|
1343
|
+
* Read a selection from a vertical list of options.
|
|
1344
|
+
* @param prompt - The prompt text displayed to the user
|
|
1345
|
+
* @param options - Array of options to choose from
|
|
1346
|
+
* @param selectOptions - Optional configuration for default, search, onChange
|
|
1347
|
+
* @returns The selected option's value, or null if aborted
|
|
1348
|
+
*/
|
|
1349
|
+
readSelect(prompt: string, options: CliSelectOption[], selectOptions?: CliSelectOptions): Promise<string | null>;
|
|
1350
|
+
/**
|
|
1351
|
+
* Read a selection from an inline horizontal list.
|
|
1352
|
+
* @param prompt - The prompt text displayed to the user
|
|
1353
|
+
* @param options - Array of options to choose from
|
|
1354
|
+
* @param selectOptions - Optional configuration for default, search, onChange
|
|
1355
|
+
* @returns The selected option's value, or null if aborted
|
|
1356
|
+
*/
|
|
1357
|
+
readSelectInline(prompt: string, options: CliSelectOption[], selectOptions?: CliSelectOptions): Promise<string | null>;
|
|
1358
|
+
/**
|
|
1359
|
+
* Read multiple selections from a checkbox list.
|
|
1360
|
+
* @param prompt - The prompt text displayed to the user
|
|
1361
|
+
* @param options - Array of options with optional pre-checked state
|
|
1362
|
+
* @param selectOptions - Optional configuration for search, onChange
|
|
1363
|
+
* @returns Array of selected option values, or null if aborted
|
|
1364
|
+
*/
|
|
1365
|
+
readMultiSelect(prompt: string, options: CliMultiSelectOption[], selectOptions?: CliMultiSelectOptions): Promise<string[] | null>;
|
|
1366
|
+
/**
|
|
1367
|
+
* Read a number input.
|
|
1368
|
+
* @param prompt - The prompt text displayed to the user
|
|
1369
|
+
* @param options - Optional configuration for min, max, and default value
|
|
1370
|
+
* @returns The entered number, or null if aborted
|
|
1371
|
+
*/
|
|
1372
|
+
readNumber(prompt: string, options?: CliNumberOptions): Promise<number | null>;
|
|
1373
|
+
/**
|
|
1374
|
+
* Read a date input with format validation.
|
|
1375
|
+
* @param prompt - The prompt text displayed to the user
|
|
1376
|
+
* @param options - Optional configuration for format, min/max range, default
|
|
1377
|
+
* @returns The date string in the specified format, or null if aborted
|
|
1378
|
+
*/
|
|
1379
|
+
readDate(prompt: string, options?: CliDateOptions): Promise<string | null>;
|
|
1380
|
+
/**
|
|
1381
|
+
* Read file(s) via the environment's file picker dialog.
|
|
1382
|
+
* @param prompt - The prompt text displayed to the user
|
|
1383
|
+
* @param options - Optional configuration for multiple, accept filter, directory mode
|
|
1384
|
+
* @returns Array of selected files with content, or null if cancelled/unsupported
|
|
1385
|
+
*/
|
|
1386
|
+
readFile(prompt: string, options?: CliFilePickerOptions): Promise<CliFileResult[] | null>;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
interface ICliProgressBar {
|
|
1390
|
+
/**
|
|
1391
|
+
* Indicates if the progress bar is running
|
|
1392
|
+
*/
|
|
1393
|
+
isRunning: boolean;
|
|
1394
|
+
/**
|
|
1395
|
+
* Show the progress bar
|
|
1396
|
+
*/
|
|
1397
|
+
show: (text?: string) => void;
|
|
1398
|
+
/**
|
|
1399
|
+
* Hide the progress bar
|
|
1400
|
+
*/
|
|
1401
|
+
hide: () => void;
|
|
1281
1402
|
}
|
|
1282
1403
|
/**
|
|
1283
|
-
* Represents a
|
|
1404
|
+
* Represents a spinner for the CLI
|
|
1284
1405
|
*/
|
|
1285
|
-
interface
|
|
1286
|
-
/**
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
createGroup(name: string, description?: string, permissions?: string[]): Promise<ICliGroup>;
|
|
1292
|
-
/** Updates a group's description and/or permissions (by id or name) */
|
|
1293
|
-
updateGroup(id: string, updates: {
|
|
1294
|
-
description?: string;
|
|
1295
|
-
permissions?: string[];
|
|
1296
|
-
}): Promise<ICliGroup>;
|
|
1297
|
-
/** Adds a user (id or name) to a group (id or name) */
|
|
1298
|
-
addMember(groupId: string, userId: string): Promise<void>;
|
|
1299
|
-
/** Removes a user (id or name) from a group (id or name) */
|
|
1300
|
-
removeMember(groupId: string, userId: string): Promise<void>;
|
|
1301
|
-
/** Deletes a group by id */
|
|
1302
|
-
deleteGroup(id: string): Promise<void>;
|
|
1303
|
-
/** Gets all users that belong to a group */
|
|
1304
|
-
getGroupMembers(groupId: string): Observable<ICliUser[]>;
|
|
1406
|
+
interface ICliSpinner extends ICliProgressBar {
|
|
1407
|
+
/**
|
|
1408
|
+
* Set the text of the spinner
|
|
1409
|
+
* @param text The text to set
|
|
1410
|
+
*/
|
|
1411
|
+
setText: (text: string) => void;
|
|
1305
1412
|
}
|
|
1413
|
+
type CliPercentageProgressBarUpdateValueOptions = {
|
|
1414
|
+
/**
|
|
1415
|
+
* The type of update to perform
|
|
1416
|
+
* @default 'replace'
|
|
1417
|
+
*/
|
|
1418
|
+
type?: 'replace' | 'increment';
|
|
1419
|
+
};
|
|
1306
1420
|
/**
|
|
1307
|
-
* Represents a
|
|
1421
|
+
* Represents a progress bar for the CLI
|
|
1308
1422
|
*/
|
|
1309
|
-
interface
|
|
1423
|
+
interface ICliPercentageProgressBar extends ICliProgressBar {
|
|
1310
1424
|
/**
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1425
|
+
* Update the progress of the progress bar.
|
|
1426
|
+
* @param progress The progress value (0–100). Values outside this range are clamped.
|
|
1427
|
+
* @param options Optional: update type ('replace' or 'increment')
|
|
1313
1428
|
*/
|
|
1314
|
-
|
|
1315
|
-
/** Ends the current session (the CLI is left signed out) */
|
|
1316
|
-
logout(): Promise<void>;
|
|
1429
|
+
update: (progress: number, options?: CliPercentageProgressBarUpdateValueOptions) => void;
|
|
1317
1430
|
/**
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
* Goes through the same lockout, events and audit as `login`.
|
|
1431
|
+
* Complete the progress bar
|
|
1432
|
+
* @returns void
|
|
1321
1433
|
*/
|
|
1322
|
-
|
|
1434
|
+
complete: () => void;
|
|
1323
1435
|
/**
|
|
1324
|
-
*
|
|
1325
|
-
* @param
|
|
1326
|
-
* password. Server-backed implementations forward it so the server can
|
|
1327
|
-
* re-check it; local implementations may ignore it.
|
|
1436
|
+
* Set the text of the spinner
|
|
1437
|
+
* @param text The text to set
|
|
1328
1438
|
*/
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
/**
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1439
|
+
setText: (text: string) => void;
|
|
1440
|
+
}
|
|
1441
|
+
type CliTextAnimatorOptions = {
|
|
1442
|
+
/**
|
|
1443
|
+
* The speed of the animation
|
|
1444
|
+
* @default 100
|
|
1445
|
+
*/
|
|
1446
|
+
speed?: number;
|
|
1447
|
+
/**
|
|
1448
|
+
* The text will be removed after typing
|
|
1449
|
+
*/
|
|
1450
|
+
removeAfterTyping?: boolean;
|
|
1451
|
+
};
|
|
1452
|
+
interface ICliTextAnimator extends ICliProgressBar {
|
|
1453
|
+
/**
|
|
1454
|
+
* Show animated text in a typing and erasing effect.
|
|
1455
|
+
* @param text The text to animate
|
|
1456
|
+
* @param options Optional: speed (ms per character), removeAfterTyping
|
|
1457
|
+
* @returns A promise that resolves when the animation completes
|
|
1458
|
+
*/
|
|
1459
|
+
showText: (text: string, options?: CliTextAnimatorOptions) => Promise<void>;
|
|
1460
|
+
/**
|
|
1461
|
+
* Stop the running animation, erase what it wrote and resolve the
|
|
1462
|
+
* `showText` promise. Optional for backward compatibility.
|
|
1463
|
+
*/
|
|
1464
|
+
cancel?: () => void;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* Result of a guard check.
|
|
1469
|
+
*
|
|
1470
|
+
* - `true` or `undefined`: allow the command.
|
|
1471
|
+
* - `false`: block it with the generic message `<command>: permission denied`.
|
|
1472
|
+
* - a non-empty `string`: block it and print this message.
|
|
1473
|
+
* - `{ allowed, message }`: explicit form; `message` is used when `allowed` is false.
|
|
1474
|
+
*/
|
|
1475
|
+
type CliCommandGuardResult = boolean | string | void | {
|
|
1476
|
+
allowed: boolean;
|
|
1477
|
+
message?: string;
|
|
1478
|
+
};
|
|
1479
|
+
/**
|
|
1480
|
+
* A global command guard: a check that runs before **every** command, across
|
|
1481
|
+
* all processors and modules, and can block it.
|
|
1482
|
+
*
|
|
1483
|
+
* Use guards for cross-cutting policies such as authentication, permission
|
|
1484
|
+
* checks, feature flags, maintenance windows or rate limiting, instead of
|
|
1485
|
+
* repeating the check inside each processor.
|
|
1486
|
+
*
|
|
1487
|
+
* ## When guards run
|
|
1488
|
+
*
|
|
1489
|
+
* For each command the executor:
|
|
1490
|
+
* 1. parses the input and resolves the processor (and sub-processor);
|
|
1491
|
+
* 2. handles global parameters such as `--help` (help is never guarded);
|
|
1492
|
+
* 3. extracts the positional value into `command.value`;
|
|
1493
|
+
* 4. **runs the guards**;
|
|
1494
|
+
* 5. validates required values/parameters, runs processor hooks and finally
|
|
1495
|
+
* calls `processCommand`.
|
|
1496
|
+
*
|
|
1497
|
+
* Guards run in ascending `priority` (default `0`). For each guard the executor
|
|
1498
|
+
* calls `appliesTo` (if defined) and skips the guard when it returns `false`;
|
|
1499
|
+
* otherwise it awaits `canActivate`. The **first** guard that blocks stops the
|
|
1500
|
+
* chain: its message is written as an error and the command exits with code
|
|
1501
|
+
* `-1`. A guard that throws (in `appliesTo` or `canActivate`) also blocks the
|
|
1502
|
+
* command, so a broken guard fails closed.
|
|
1503
|
+
*
|
|
1504
|
+
* ## Access to the context
|
|
1505
|
+
*
|
|
1506
|
+
* Both `appliesTo` and `canActivate` receive the {@link ICliExecutionContext}
|
|
1507
|
+
* of the command about to run, so a guard can:
|
|
1508
|
+
* - resolve services with `context.services.get(...)` / `getRequired(...)`
|
|
1509
|
+
* (e.g. a policy, feature-flag or permission service registered by any
|
|
1510
|
+
* module) to decide **what** should be guarded and **whether** it may run;
|
|
1511
|
+
* - inspect `context.userSession` for the signed-in user and their groups;
|
|
1512
|
+
* - read the processor's `metadata` (for example `requireAuth` or
|
|
1513
|
+
* `requiredGroups`) and the parsed `command` (`command.value`, `command.args`);
|
|
1514
|
+
* - prompt the user via `context.reader` (e.g. a confirmation guard).
|
|
1515
|
+
*
|
|
1516
|
+
* Guards should not write to the terminal to report a denial; return a message
|
|
1517
|
+
* instead so the executor prints it consistently.
|
|
1518
|
+
*
|
|
1519
|
+
* ## Registering guards
|
|
1520
|
+
*
|
|
1521
|
+
* The preferred way is the module's `guards` array; the boot sequence
|
|
1522
|
+
* registers each entry as a multi-provider under {@link ICliCommandGuard_TOKEN}.
|
|
1523
|
+
* Several modules can contribute guards; all of them run.
|
|
1524
|
+
*
|
|
1525
|
+
* ```ts
|
|
1526
|
+
* const billingModule: ICliModule = {
|
|
1527
|
+
* apiVersion: 2,
|
|
1528
|
+
* name: 'billing',
|
|
1529
|
+
* processors: [new InvoiceProcessor()],
|
|
1530
|
+
* guards: [billingGuard],
|
|
1531
|
+
* };
|
|
1532
|
+
* ```
|
|
1533
|
+
*
|
|
1534
|
+
* Guards can also be added at runtime (e.g. from `onInit`):
|
|
1535
|
+
*
|
|
1536
|
+
* ```ts
|
|
1537
|
+
* context.services.set({ provide: ICliCommandGuard_TOKEN, useValue: myGuard, multi: true });
|
|
1538
|
+
* ```
|
|
1539
|
+
*
|
|
1540
|
+
* ## Example: policy resolved from a service
|
|
1541
|
+
*
|
|
1542
|
+
* ```ts
|
|
1543
|
+
* const featureFlagGuard: ICliCommandGuard = {
|
|
1544
|
+
* name: 'feature-flags',
|
|
1545
|
+
* // Only guard commands that are behind a flag; the flag list comes from a service
|
|
1546
|
+
* appliesTo: (processor, _command, context) =>
|
|
1547
|
+
* context.services.get<FeatureFlags>(FeatureFlags_TOKEN)?.isFlagged(processor.command) ?? false,
|
|
1548
|
+
* canActivate: async (_command, processor, context) => {
|
|
1549
|
+
* const flags = context.services.getRequired<FeatureFlags>(FeatureFlags_TOKEN);
|
|
1550
|
+
* return (await flags.isEnabled(processor.command, context.userSession?.user))
|
|
1551
|
+
* ? true
|
|
1552
|
+
* : `${processor.command}: not available for your account`;
|
|
1553
|
+
* },
|
|
1554
|
+
* };
|
|
1555
|
+
* ```
|
|
1556
|
+
*
|
|
1557
|
+
* ## Without a guard-providing module
|
|
1558
|
+
*
|
|
1559
|
+
* Guards are opt-in. When no guard is registered every command runs as before.
|
|
1560
|
+
* The engine registers three built-in guards that enforce the processor access
|
|
1561
|
+
* metadata (`requireAuth`, `requiredGroups`, `requiredPermissions`); they stay
|
|
1562
|
+
* inactive until an auth module (e.g. `@qodalis/cli-users`) registers an
|
|
1563
|
+
* `ICliAuthorizationService`, so without one that metadata is informational.
|
|
1564
|
+
*/
|
|
1565
|
+
interface ICliCommandGuard {
|
|
1566
|
+
/** Unique name, shown in diagnostics when the guard throws. */
|
|
1567
|
+
name: string;
|
|
1568
|
+
/** Execution order; lower runs first. Defaults to `0`. */
|
|
1569
|
+
priority?: number;
|
|
1570
|
+
/**
|
|
1571
|
+
* Optional filter deciding whether this guard is relevant for the command.
|
|
1572
|
+
* Return `false` to skip the guard. When omitted the guard applies to
|
|
1573
|
+
* every command. May be async, and may use `context` to resolve services.
|
|
1574
|
+
*/
|
|
1575
|
+
appliesTo?(processor: ICliCommandProcessor, command: CliProcessCommand, context: ICliExecutionContext): boolean | Promise<boolean>;
|
|
1576
|
+
/**
|
|
1577
|
+
* Decide whether the command may run. See {@link CliCommandGuardResult}
|
|
1578
|
+
* for the accepted return values.
|
|
1579
|
+
*/
|
|
1580
|
+
canActivate(command: CliProcessCommand, processor: ICliCommandProcessor, context: ICliExecutionContext): CliCommandGuardResult | Promise<CliCommandGuardResult>;
|
|
1336
1581
|
}
|
|
1582
|
+
/** DI token for {@link ICliCommandGuard}; register guards as multi-providers. */
|
|
1583
|
+
declare const ICliCommandGuard_TOKEN: CliToken<ICliCommandGuard>;
|
|
1337
1584
|
|
|
1338
1585
|
/**
|
|
1339
1586
|
* Represents a serialized snapshot of a CLI engine's state.
|
|
@@ -1496,6 +1743,210 @@ interface ICliBackgroundServiceRegistry {
|
|
|
1496
1743
|
destroyAll(): Promise<void>;
|
|
1497
1744
|
}
|
|
1498
1745
|
|
|
1746
|
+
/**
|
|
1747
|
+
* One event on the CLI event bus.
|
|
1748
|
+
*/
|
|
1749
|
+
interface CliEvent<T = unknown> {
|
|
1750
|
+
/** Namespaced type, e.g. `package:installed` or `todo:added`. */
|
|
1751
|
+
type: string;
|
|
1752
|
+
/** Event payload. */
|
|
1753
|
+
data: T;
|
|
1754
|
+
/** Who emitted it (module or command name), when known. */
|
|
1755
|
+
source?: string;
|
|
1756
|
+
/** When it was emitted (ms since epoch). */
|
|
1757
|
+
timestamp: number;
|
|
1758
|
+
}
|
|
1759
|
+
type CliEventHandler<T = unknown> = (event: CliEvent<T>) => void;
|
|
1760
|
+
/**
|
|
1761
|
+
* Payload types of the known events, keyed by event type. The built-in
|
|
1762
|
+
* events are listed here; plugins add their own with declaration merging:
|
|
1763
|
+
*
|
|
1764
|
+
* ```ts
|
|
1765
|
+
* declare module '@qodalis/cli-core' {
|
|
1766
|
+
* interface CliEventMap {
|
|
1767
|
+
* 'todo:added': { id: number; text: string };
|
|
1768
|
+
* }
|
|
1769
|
+
* }
|
|
1770
|
+
* ```
|
|
1771
|
+
*
|
|
1772
|
+
* Events not listed can still be emitted and received; their payload is
|
|
1773
|
+
* then `unknown`.
|
|
1774
|
+
*/
|
|
1775
|
+
interface CliEventMap {
|
|
1776
|
+
/** Boot finished: modules are set up and the terminal accepts input. */
|
|
1777
|
+
'boot:completed': {
|
|
1778
|
+
durationMs: number;
|
|
1779
|
+
modules: number;
|
|
1780
|
+
commands: number;
|
|
1781
|
+
};
|
|
1782
|
+
/** A command line finished running (typed, or run with `engine.execute`). */
|
|
1783
|
+
'command:executed': {
|
|
1784
|
+
command: string;
|
|
1785
|
+
exitCode: number;
|
|
1786
|
+
durationMs: number;
|
|
1787
|
+
};
|
|
1788
|
+
/** A module (plugin) was booted, at startup or later (e.g. `pkg add`). */
|
|
1789
|
+
'module:loaded': {
|
|
1790
|
+
name: string;
|
|
1791
|
+
version?: string;
|
|
1792
|
+
commands: number;
|
|
1793
|
+
};
|
|
1794
|
+
/** A module was unloaded (e.g. `pkg remove`, or before `pkg update`). */
|
|
1795
|
+
'module:unloaded': {
|
|
1796
|
+
name: string;
|
|
1797
|
+
};
|
|
1798
|
+
/** `pkg add` installed a package. */
|
|
1799
|
+
'package:installed': {
|
|
1800
|
+
name: string;
|
|
1801
|
+
version: string;
|
|
1802
|
+
};
|
|
1803
|
+
/** `pkg update` changed a package's version. */
|
|
1804
|
+
'package:updated': {
|
|
1805
|
+
name: string;
|
|
1806
|
+
version: string;
|
|
1807
|
+
previousVersion: string;
|
|
1808
|
+
};
|
|
1809
|
+
/** `pkg remove` removed a package. */
|
|
1810
|
+
'package:removed': {
|
|
1811
|
+
name: string;
|
|
1812
|
+
version: string;
|
|
1813
|
+
};
|
|
1814
|
+
/** A server connected (at boot, or after a reconnect). */
|
|
1815
|
+
'server:connected': {
|
|
1816
|
+
name: string;
|
|
1817
|
+
url: string;
|
|
1818
|
+
commands: number;
|
|
1819
|
+
reconnected: boolean;
|
|
1820
|
+
};
|
|
1821
|
+
/** A server could not be reached at boot. */
|
|
1822
|
+
'server:unavailable': {
|
|
1823
|
+
name: string;
|
|
1824
|
+
url: string;
|
|
1825
|
+
};
|
|
1826
|
+
/** A connected server went away. */
|
|
1827
|
+
'server:disconnected': {
|
|
1828
|
+
name: string;
|
|
1829
|
+
};
|
|
1830
|
+
/** An event pushed by a server over its event socket. */
|
|
1831
|
+
'server:event': {
|
|
1832
|
+
server: string;
|
|
1833
|
+
type: string;
|
|
1834
|
+
data: unknown;
|
|
1835
|
+
};
|
|
1836
|
+
/** Background service lifecycle (`service:registered`, `service:started`, ...). */
|
|
1837
|
+
'service:registered': {
|
|
1838
|
+
name: string;
|
|
1839
|
+
[key: string]: unknown;
|
|
1840
|
+
};
|
|
1841
|
+
'service:started': {
|
|
1842
|
+
name: string;
|
|
1843
|
+
[key: string]: unknown;
|
|
1844
|
+
};
|
|
1845
|
+
'service:stopped': {
|
|
1846
|
+
name: string;
|
|
1847
|
+
[key: string]: unknown;
|
|
1848
|
+
};
|
|
1849
|
+
'service:completed': {
|
|
1850
|
+
name: string;
|
|
1851
|
+
[key: string]: unknown;
|
|
1852
|
+
};
|
|
1853
|
+
'service:failed': {
|
|
1854
|
+
name: string;
|
|
1855
|
+
error?: string;
|
|
1856
|
+
[key: string]: unknown;
|
|
1857
|
+
};
|
|
1858
|
+
'service:status': {
|
|
1859
|
+
name: string;
|
|
1860
|
+
[key: string]: unknown;
|
|
1861
|
+
};
|
|
1862
|
+
/** A custom event emitted by a background service with `context.emit()`. */
|
|
1863
|
+
'service:event': {
|
|
1864
|
+
service: string;
|
|
1865
|
+
type: string;
|
|
1866
|
+
data: unknown;
|
|
1867
|
+
};
|
|
1868
|
+
/** A setting changed with `configure` (`category` is `system` or a plugin key). */
|
|
1869
|
+
'config:changed': {
|
|
1870
|
+
category: string;
|
|
1871
|
+
key: string;
|
|
1872
|
+
value: unknown;
|
|
1873
|
+
};
|
|
1874
|
+
/** A configuration category was reset to its defaults. */
|
|
1875
|
+
'config:reset': {
|
|
1876
|
+
category: string;
|
|
1877
|
+
};
|
|
1878
|
+
/** The signed-in user changed (sign-in, sign-out, `su`). */
|
|
1879
|
+
'session:changed': {
|
|
1880
|
+
user?: string;
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
/** Event types with a known payload. */
|
|
1884
|
+
type CliEventType = keyof CliEventMap;
|
|
1885
|
+
/** Payload of event `K`: from {@link CliEventMap}, or `unknown`. */
|
|
1886
|
+
type CliEventData<K extends string> = K extends CliEventType ? CliEventMap[K] : unknown;
|
|
1887
|
+
/**
|
|
1888
|
+
* Publish/subscribe bus shared by the system, modules and commands of one
|
|
1889
|
+
* terminal. Handlers run synchronously in subscription order; a failing
|
|
1890
|
+
* handler is logged and does not affect the others or the emitter.
|
|
1891
|
+
*
|
|
1892
|
+
* Patterns: an exact type (`package:installed`), a namespace wildcard
|
|
1893
|
+
* (`package:*`) or `*` for everything.
|
|
1894
|
+
*
|
|
1895
|
+
* Events live in memory: each terminal has its own bus for its lifetime,
|
|
1896
|
+
* with a short recent history, and nothing is persisted.
|
|
1897
|
+
*
|
|
1898
|
+
* Get it from a command or module with `context.events`, or from the
|
|
1899
|
+
* services container with {@link ICliEventBus_TOKEN}.
|
|
1900
|
+
*/
|
|
1901
|
+
interface ICliEventBus {
|
|
1902
|
+
/**
|
|
1903
|
+
* Emit an event to every matching handler.
|
|
1904
|
+
*
|
|
1905
|
+
* ```ts
|
|
1906
|
+
* bus.emit('package:installed', { name, version }); // checked against CliEventMap
|
|
1907
|
+
* bus.emit<TodoAdded>('todo:added', { id, text }); // explicit payload type
|
|
1908
|
+
* bus.emit('todo:refresh'); // custom event, no payload
|
|
1909
|
+
* ```
|
|
1910
|
+
*/
|
|
1911
|
+
emit<K extends CliEventType>(type: K, data: CliEventMap[K], options?: CliEmitOptions): void;
|
|
1912
|
+
emit<T = unknown, K extends string = string>(type: K & CustomEventType<K>, data?: T, options?: CliEmitOptions): void;
|
|
1913
|
+
/**
|
|
1914
|
+
* Handle events matching `pattern`. Returns a function that unsubscribes.
|
|
1915
|
+
*
|
|
1916
|
+
* ```ts
|
|
1917
|
+
* bus.on('package:installed', (e) => e.data.version); // typed from CliEventMap
|
|
1918
|
+
* bus.on<TodoAdded>('todo:added', (e) => e.data.text); // explicit payload type
|
|
1919
|
+
* bus.on('server:*', (e) => console.log(e.type)); // anonymous: data is unknown
|
|
1920
|
+
* ```
|
|
1921
|
+
*/
|
|
1922
|
+
on<K extends CliEventType>(pattern: K, handler: CliEventHandler<CliEventMap[K]>): () => void;
|
|
1923
|
+
on<T = unknown>(pattern: string, handler: CliEventHandler<T>): () => void;
|
|
1924
|
+
/** Like `on`, but only for the next matching event. */
|
|
1925
|
+
once<K extends CliEventType>(pattern: K, handler: CliEventHandler<CliEventMap[K]>): () => void;
|
|
1926
|
+
once<T = unknown>(pattern: string, handler: CliEventHandler<T>): () => void;
|
|
1927
|
+
/**
|
|
1928
|
+
* Recent events matching `pattern`, oldest first. The bus keeps the last
|
|
1929
|
+
* events in memory only: events are not persisted across reloads (state
|
|
1930
|
+
* that must survive a reload belongs in a state store).
|
|
1931
|
+
*/
|
|
1932
|
+
history<K extends CliEventType>(pattern: K, limit?: number): CliEvent<CliEventMap[K]>[];
|
|
1933
|
+
history<T = unknown>(pattern?: string, limit?: number): CliEvent<T>[];
|
|
1934
|
+
/** Matching events as an observable (completes when the bus is disposed). */
|
|
1935
|
+
events$<K extends CliEventType>(pattern: K): Observable<CliEvent<CliEventMap[K]>>;
|
|
1936
|
+
events$<T = unknown>(pattern?: string): Observable<CliEvent<T>>;
|
|
1937
|
+
}
|
|
1938
|
+
interface CliEmitOptions {
|
|
1939
|
+
/** Who emits the event (module or command name). */
|
|
1940
|
+
source?: string;
|
|
1941
|
+
}
|
|
1942
|
+
/**
|
|
1943
|
+
* A type that is not a key of {@link CliEventMap}. Keeps `emit` from accepting
|
|
1944
|
+
* a known event with an unchecked payload.
|
|
1945
|
+
*/
|
|
1946
|
+
type CustomEventType<K extends string> = K extends CliEventType ? never : K;
|
|
1947
|
+
/** Service token of the terminal's {@link ICliEventBus}. */
|
|
1948
|
+
declare const ICliEventBus_TOKEN: CliToken<ICliEventBus>;
|
|
1949
|
+
|
|
1499
1950
|
/**
|
|
1500
1951
|
* Messages sent from the main thread to a background service Worker.
|
|
1501
1952
|
*/
|
|
@@ -1529,38 +1980,6 @@ type CliWorkerOutboundMessage = {
|
|
|
1529
1980
|
stack?: string;
|
|
1530
1981
|
};
|
|
1531
1982
|
|
|
1532
|
-
/**
|
|
1533
|
-
* Represents an entry in a file listing.
|
|
1534
|
-
*/
|
|
1535
|
-
interface ICliFileEntry {
|
|
1536
|
-
name: string;
|
|
1537
|
-
type: 'file' | 'directory';
|
|
1538
|
-
size: number;
|
|
1539
|
-
modified: string;
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
/**
|
|
1543
|
-
* Abstraction for file transfer operations.
|
|
1544
|
-
* Default implementation uses browser-native APIs (file picker, download dialog).
|
|
1545
|
-
* @qodalis/cli-files overrides with virtual FS backed by IndexedDB.
|
|
1546
|
-
*/
|
|
1547
|
-
interface ICliFileTransferService {
|
|
1548
|
-
readFile(path: string): Promise<string | null>;
|
|
1549
|
-
writeFile(path: string, content: string): Promise<void>;
|
|
1550
|
-
listFiles(path: string): Promise<ICliFileEntry[]>;
|
|
1551
|
-
exists(path: string): Promise<boolean>;
|
|
1552
|
-
downloadToBrowser(filename: string, content: string | Blob): void;
|
|
1553
|
-
uploadFromBrowser(accept?: string): Promise<{
|
|
1554
|
-
name: string;
|
|
1555
|
-
content: string;
|
|
1556
|
-
} | null>;
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
interface ICliDragDropService {
|
|
1560
|
-
/** Emits an array of dropped File objects each time files are dropped onto the terminal */
|
|
1561
|
-
readonly onFileDrop: Observable<File[]>;
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
1983
|
/**
|
|
1565
1984
|
* Opaque state value carried between lines during syntax highlighting.
|
|
1566
1985
|
* Encodes context such as "inside a multi-line string" or "inside a block comment"
|
|
@@ -1618,10 +2037,37 @@ declare enum CliLogLevel {
|
|
|
1618
2037
|
WARN = 4,
|
|
1619
2038
|
ERROR = 5
|
|
1620
2039
|
}
|
|
2040
|
+
/**
|
|
2041
|
+
* How the CLI reports its startup.
|
|
2042
|
+
*/
|
|
2043
|
+
interface CliBootOptions {
|
|
2044
|
+
/**
|
|
2045
|
+
* Report each boot step (terminal, services, servers, modules) in the
|
|
2046
|
+
* terminal while the CLI starts. When `false`, a spinner is shown instead.
|
|
2047
|
+
* Users can override it with `configure set system.bootLogs false`.
|
|
2048
|
+
* @default true
|
|
2049
|
+
*/
|
|
2050
|
+
showLogs?: boolean;
|
|
2051
|
+
/**
|
|
2052
|
+
* Keep the boot report on screen after startup instead of clearing it
|
|
2053
|
+
* when the terminal is ready. Warnings and errors are kept either way.
|
|
2054
|
+
* @default false
|
|
2055
|
+
*/
|
|
2056
|
+
keepLogs?: boolean;
|
|
2057
|
+
/**
|
|
2058
|
+
* Steps taking at least this many milliseconds are highlighted as slow.
|
|
2059
|
+
* @default 500
|
|
2060
|
+
*/
|
|
2061
|
+
slowStepMs?: number;
|
|
2062
|
+
}
|
|
1621
2063
|
/**
|
|
1622
2064
|
* Options for the CLI
|
|
1623
2065
|
*/
|
|
1624
2066
|
type CliOptions = Record<string, any> & {
|
|
2067
|
+
/**
|
|
2068
|
+
* How the CLI reports its startup (boot log, spinner).
|
|
2069
|
+
*/
|
|
2070
|
+
boot?: CliBootOptions;
|
|
1625
2071
|
/**
|
|
1626
2072
|
* Custom terminal options
|
|
1627
2073
|
*/
|
|
@@ -1692,6 +2138,13 @@ type CliProcessorMetadata = Record<string, any> & {
|
|
|
1692
2138
|
* Sealed processors can still be extended (wrapped) by processors with `extendsProcessor = true`.
|
|
1693
2139
|
*/
|
|
1694
2140
|
sealed?: boolean;
|
|
2141
|
+
/**
|
|
2142
|
+
* The command's text is code or other literal input (`eval`): the engine
|
|
2143
|
+
* passes the whole line as typed, without operators (`|`, `;`, `&&`,
|
|
2144
|
+
* `>`) or expansion of `$(...)`, `$VAR`, braces and wildcards, so
|
|
2145
|
+
* `eval [1,2].map(x => x * 2)` keeps its `=>`, `*` and `${...}`.
|
|
2146
|
+
*/
|
|
2147
|
+
literalInput?: boolean;
|
|
1695
2148
|
/**
|
|
1696
2149
|
* If true, the processor requires the server to be running
|
|
1697
2150
|
*/
|
|
@@ -1751,7 +2204,45 @@ type CliStateConfiguration = {
|
|
|
1751
2204
|
* @remarks If the store identifier is not set, the processor command name is used
|
|
1752
2205
|
*/
|
|
1753
2206
|
storeName?: string;
|
|
2207
|
+
/**
|
|
2208
|
+
* Save the state after every change, so `persist()` does not have to be
|
|
2209
|
+
* called. Changes made in the same tick are saved together.
|
|
2210
|
+
* @default false
|
|
2211
|
+
*/
|
|
2212
|
+
autoPersist?: boolean;
|
|
2213
|
+
/**
|
|
2214
|
+
* Version of the state's shape. When the saved state has an older
|
|
2215
|
+
* version, `migrate` converts it while it is loaded. Saved state without
|
|
2216
|
+
* a version counts as version 0.
|
|
2217
|
+
*/
|
|
2218
|
+
version?: number;
|
|
2219
|
+
/**
|
|
2220
|
+
* Convert saved state of version `fromVersion` to the current
|
|
2221
|
+
* {@link version}. The result is merged over `initialState`.
|
|
2222
|
+
*/
|
|
2223
|
+
migrate?: (state: CliState, fromVersion: number) => CliState;
|
|
2224
|
+
/**
|
|
2225
|
+
* Apply changes saved by other tabs and terminals of the same browser.
|
|
2226
|
+
* @default true
|
|
2227
|
+
*/
|
|
2228
|
+
syncAcrossTabs?: boolean;
|
|
2229
|
+
/**
|
|
2230
|
+
* Where the state lives:
|
|
2231
|
+
* - `'global'`: saved in the browser and shared by every terminal and tab
|
|
2232
|
+
* (each save merges the keys it changed, so terminals changing
|
|
2233
|
+
* different keys never overwrite each other).
|
|
2234
|
+
* - `'user'`: like `'global'`, but saved separately for each signed-in
|
|
2235
|
+
* user (signed out, the state is shared); it switches when the user
|
|
2236
|
+
* signs in or out.
|
|
2237
|
+
* - `'session'`: this terminal only, in memory; never saved or shared.
|
|
2238
|
+
* @default 'global'
|
|
2239
|
+
*/
|
|
2240
|
+
scope?: CliStateScope;
|
|
1754
2241
|
};
|
|
2242
|
+
/** See {@link CliStateConfiguration.scope}. */
|
|
2243
|
+
type CliStateScope = 'global' | 'user' | 'session';
|
|
2244
|
+
/** Options of a state store (see {@link CliStateConfiguration}). */
|
|
2245
|
+
type CliStateStoreOptions = Pick<CliStateConfiguration, 'autoPersist' | 'version' | 'migrate' | 'syncAcrossTabs' | 'scope'>;
|
|
1755
2246
|
type CliState = Record<string, any>;
|
|
1756
2247
|
/**
|
|
1757
2248
|
* Position of the CLI panel relative to the viewport edge.
|
|
@@ -1894,114 +2385,6 @@ interface CliPanelPaneState {
|
|
|
1894
2385
|
widthPercent: number;
|
|
1895
2386
|
}
|
|
1896
2387
|
|
|
1897
|
-
/**
|
|
1898
|
-
* Options for HTTP client requests.
|
|
1899
|
-
* Extends standard RequestInit with convenience fields.
|
|
1900
|
-
*/
|
|
1901
|
-
interface CliHttpRequestOptions extends Omit<RequestInit, 'method' | 'body'> {
|
|
1902
|
-
/**
|
|
1903
|
-
* Request timeout in milliseconds. When set, the request is automatically
|
|
1904
|
-
* aborted after this duration. Combines with any existing abort signal.
|
|
1905
|
-
*/
|
|
1906
|
-
timeout?: number;
|
|
1907
|
-
}
|
|
1908
|
-
/**
|
|
1909
|
-
* HTTP client for making requests from command processors.
|
|
1910
|
-
*
|
|
1911
|
-
* Automatically merges the command's abort signal so that requests are
|
|
1912
|
-
* cancelled when the user presses Ctrl+C. Provides typed convenience
|
|
1913
|
-
* methods for common HTTP verbs as well as a raw `fetch()` for cases
|
|
1914
|
-
* that need full Response access (streaming, progress, etc.).
|
|
1915
|
-
*
|
|
1916
|
-
* Available on the execution context as `context.http`.
|
|
1917
|
-
*
|
|
1918
|
-
* @example
|
|
1919
|
-
* ```ts
|
|
1920
|
-
* // Typed JSON response
|
|
1921
|
-
* const users = await context.http.get<User[]>('https://api.example.com/users');
|
|
1922
|
-
*
|
|
1923
|
-
* // POST with body
|
|
1924
|
-
* await context.http.post('https://api.example.com/users', { name: 'John' });
|
|
1925
|
-
*
|
|
1926
|
-
* // Raw fetch for streaming
|
|
1927
|
-
* const response = await context.http.fetch('https://example.com/file.zip');
|
|
1928
|
-
* const reader = response.body?.getReader();
|
|
1929
|
-
* ```
|
|
1930
|
-
*/
|
|
1931
|
-
interface ICliHttpClient {
|
|
1932
|
-
/**
|
|
1933
|
-
* Make a raw HTTP request. Returns the full Response object for cases
|
|
1934
|
-
* that need streaming, headers, or status inspection.
|
|
1935
|
-
* The command's abort signal is automatically merged.
|
|
1936
|
-
*/
|
|
1937
|
-
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
1938
|
-
/**
|
|
1939
|
-
* HTTP GET request. Returns the parsed JSON response body.
|
|
1940
|
-
*/
|
|
1941
|
-
get<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
1942
|
-
/**
|
|
1943
|
-
* HTTP POST request. Automatically serializes the body as JSON
|
|
1944
|
-
* (unless body is FormData, Blob, string, or ArrayBuffer).
|
|
1945
|
-
* Returns the parsed JSON response body.
|
|
1946
|
-
*/
|
|
1947
|
-
post<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
1948
|
-
/**
|
|
1949
|
-
* HTTP PUT request. Automatically serializes the body as JSON.
|
|
1950
|
-
* Returns the parsed JSON response body.
|
|
1951
|
-
*/
|
|
1952
|
-
put<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
1953
|
-
/**
|
|
1954
|
-
* HTTP PATCH request. Automatically serializes the body as JSON.
|
|
1955
|
-
* Returns the parsed JSON response body.
|
|
1956
|
-
*/
|
|
1957
|
-
patch<T = any>(url: string, body?: any, options?: CliHttpRequestOptions): Promise<T>;
|
|
1958
|
-
/**
|
|
1959
|
-
* HTTP DELETE request. Returns the parsed JSON response body (if any).
|
|
1960
|
-
*/
|
|
1961
|
-
delete<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
1962
|
-
/**
|
|
1963
|
-
* HTTP HEAD request. Returns the full Response (no body parsing).
|
|
1964
|
-
*/
|
|
1965
|
-
head(url: string, options?: CliHttpRequestOptions): Promise<Response>;
|
|
1966
|
-
/**
|
|
1967
|
-
* HTTP OPTIONS request. Returns the parsed JSON response body.
|
|
1968
|
-
*/
|
|
1969
|
-
options<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
|
|
1970
|
-
}
|
|
1971
|
-
/**
|
|
1972
|
-
* Error thrown by `ICliHttpClient` JSON helpers (`get`, `post`, `put`,
|
|
1973
|
-
* `patch`, `delete`, `options`) when the server responds with a non-2xx status.
|
|
1974
|
-
*
|
|
1975
|
-
* Exposes the HTTP status so callers can react to specific responses
|
|
1976
|
-
* (for example, clearing a stored session token on `401`).
|
|
1977
|
-
*
|
|
1978
|
-
* @example
|
|
1979
|
-
* ```ts
|
|
1980
|
-
* try {
|
|
1981
|
-
* await context.http.get(url);
|
|
1982
|
-
* } catch (e) {
|
|
1983
|
-
* if (e instanceof CliHttpError && e.status === 401) {
|
|
1984
|
-
* // token expired or revoked
|
|
1985
|
-
* }
|
|
1986
|
-
* }
|
|
1987
|
-
* ```
|
|
1988
|
-
*/
|
|
1989
|
-
declare class CliHttpError extends Error {
|
|
1990
|
-
/** HTTP status code of the failed response */
|
|
1991
|
-
readonly status: number;
|
|
1992
|
-
/** HTTP status text of the failed response */
|
|
1993
|
-
readonly statusText: string;
|
|
1994
|
-
/** Parsed JSON error body, when the server returned one */
|
|
1995
|
-
readonly body?: unknown | undefined;
|
|
1996
|
-
constructor(message: string,
|
|
1997
|
-
/** HTTP status code of the failed response */
|
|
1998
|
-
status: number,
|
|
1999
|
-
/** HTTP status text of the failed response */
|
|
2000
|
-
statusText?: string,
|
|
2001
|
-
/** Parsed JSON error body, when the server returned one */
|
|
2002
|
-
body?: unknown | undefined);
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
2388
|
type CliNotificationLevel = 'info' | 'success' | 'warn' | 'error';
|
|
2006
2389
|
interface CliNotification {
|
|
2007
2390
|
level: CliNotificationLevel;
|
|
@@ -2026,64 +2409,6 @@ interface ICliNotifier {
|
|
|
2026
2409
|
readonly change$: Observable<CliNotification | undefined>;
|
|
2027
2410
|
}
|
|
2028
2411
|
|
|
2029
|
-
/** Represents a user lifecycle event */
|
|
2030
|
-
interface ICliUserEvent {
|
|
2031
|
-
/** The type of event that occurred */
|
|
2032
|
-
type: 'login' | 'logout' | 'login_failed' | 'user_created' | 'user_deleted' | 'user_updated' | 'password_changed' | 'user_switched' | 'user_disabled' | 'user_enabled' | 'group_created' | 'group_updated' | 'group_deleted' | 'group_member_added' | 'group_member_removed' | 'session_revoked' | 'audit_cleared';
|
|
2033
|
-
/** The user involved in the event (for group events: the acting user) */
|
|
2034
|
-
user: ICliUser;
|
|
2035
|
-
/** The acting user's name, when different from `user` (e.g. an admin) */
|
|
2036
|
-
actor?: string;
|
|
2037
|
-
/** When the event occurred */
|
|
2038
|
-
timestamp: number;
|
|
2039
|
-
/** Optional additional details */
|
|
2040
|
-
details?: string;
|
|
2041
|
-
/** `user_updated`: the user's name before a rename (set only when the name changed) */
|
|
2042
|
-
previousName?: string;
|
|
2043
|
-
}
|
|
2044
|
-
/** Service that emits user lifecycle events for plugins to subscribe to */
|
|
2045
|
-
interface ICliUserEventService {
|
|
2046
|
-
/** Observable stream of user events */
|
|
2047
|
-
readonly events$: Observable<ICliUserEvent>;
|
|
2048
|
-
/** Emit a user event */
|
|
2049
|
-
emit(event: ICliUserEvent): void;
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
/** A single audit log entry */
|
|
2053
|
-
interface ICliAuditEntry {
|
|
2054
|
-
/** Entry id (server-assigned in server mode) */
|
|
2055
|
-
id?: string;
|
|
2056
|
-
/** When the event occurred */
|
|
2057
|
-
timestamp: number;
|
|
2058
|
-
/** Event type (e.g., 'login', 'logout', 'login_failed') */
|
|
2059
|
-
event: string;
|
|
2060
|
-
/** Username involved */
|
|
2061
|
-
username: string;
|
|
2062
|
-
/** Optional additional details */
|
|
2063
|
-
details?: string;
|
|
2064
|
-
/** Id of the user the entry is about, when known */
|
|
2065
|
-
userId?: string;
|
|
2066
|
-
/** The user who performed the action, when different from `username` */
|
|
2067
|
-
actor?: string;
|
|
2068
|
-
/** Id of the acting user, when different from the subject */
|
|
2069
|
-
actorId?: string;
|
|
2070
|
-
/** Extra data (e.g. remote address) */
|
|
2071
|
-
metadata?: Record<string, unknown>;
|
|
2072
|
-
}
|
|
2073
|
-
/** Service for persistent audit logging */
|
|
2074
|
-
interface ICliAuditService {
|
|
2075
|
-
/** Log an audit entry (timestamp is added automatically) */
|
|
2076
|
-
log(entry: Omit<ICliAuditEntry, 'timestamp'>): Promise<void>;
|
|
2077
|
-
/** Retrieve audit entries with optional filtering */
|
|
2078
|
-
getEntries(options?: {
|
|
2079
|
-
limit?: number;
|
|
2080
|
-
event?: string;
|
|
2081
|
-
username?: string;
|
|
2082
|
-
}): Promise<ICliAuditEntry[]>;
|
|
2083
|
-
/** Clear all audit entries */
|
|
2084
|
-
clear(): Promise<void>;
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
2412
|
/**
|
|
2088
2413
|
* A managed timer handle returned by createInterval/createTimeout.
|
|
2089
2414
|
* Managed timers are automatically cleared when full-screen mode exits
|
|
@@ -2130,6 +2455,16 @@ interface ICliExecutionContext {
|
|
|
2130
2455
|
* The progress bar to use for showing progress
|
|
2131
2456
|
*/
|
|
2132
2457
|
progressBar: ICliPercentageProgressBar;
|
|
2458
|
+
/**
|
|
2459
|
+
* The terminal's event bus: emit and subscribe to events shared by the
|
|
2460
|
+
* system, modules and commands. Optional for backward compatibility.
|
|
2461
|
+
*/
|
|
2462
|
+
readonly events?: ICliEventBus;
|
|
2463
|
+
/**
|
|
2464
|
+
* `true` once the CLI has finished booting (modules set up, terminal
|
|
2465
|
+
* ready). Optional for backward compatibility; `undefined` means unknown.
|
|
2466
|
+
*/
|
|
2467
|
+
readonly isBooted?: boolean;
|
|
2133
2468
|
/**
|
|
2134
2469
|
* A subject that emits when the command is aborted
|
|
2135
2470
|
*/
|
|
@@ -2768,6 +3103,7 @@ interface ICliServiceProvider {
|
|
|
2768
3103
|
* @param service The token (typically a `*_TOKEN` constant) identifying the service
|
|
2769
3104
|
* @returns The service instance cast to `T`, or `undefined` if not registered
|
|
2770
3105
|
*/
|
|
3106
|
+
get<T>(service: CliToken<T>): T | undefined;
|
|
2771
3107
|
get<T = unknown>(service: any): T | undefined;
|
|
2772
3108
|
/**
|
|
2773
3109
|
* Retrieve all registered services for a multi-provider token.
|
|
@@ -2775,6 +3111,7 @@ interface ICliServiceProvider {
|
|
|
2775
3111
|
* @param service The token (typically a `*_TOKEN` constant) identifying the service
|
|
2776
3112
|
* @returns Array of all resolved service instances
|
|
2777
3113
|
*/
|
|
3114
|
+
getAll<T>(service: CliToken<T>): T[];
|
|
2778
3115
|
getAll<T = unknown>(service: any): T[];
|
|
2779
3116
|
/**
|
|
2780
3117
|
* Retrieve a service by its injection token, throwing if not registered.
|
|
@@ -2784,6 +3121,7 @@ interface ICliServiceProvider {
|
|
|
2784
3121
|
* @returns The service instance, cast to `T`
|
|
2785
3122
|
* @throws If no service is registered for the given token
|
|
2786
3123
|
*/
|
|
3124
|
+
getRequired<T>(service: CliToken<T>): T;
|
|
2787
3125
|
getRequired<T = unknown>(service: any): T;
|
|
2788
3126
|
/**
|
|
2789
3127
|
* Check whether a service is registered for the given token.
|
|
@@ -2796,11 +3134,20 @@ interface ICliServiceProvider {
|
|
|
2796
3134
|
* @param definition A single provider or an array of providers to register
|
|
2797
3135
|
*/
|
|
2798
3136
|
set(definition: CliProvider | CliProvider[]): void;
|
|
3137
|
+
/**
|
|
3138
|
+
* Remove a registration. With `provider` (the provider object passed to
|
|
3139
|
+
* `set`, or the registered value), only that registration is removed: for
|
|
3140
|
+
* a single token the previous registration becomes active again, for a
|
|
3141
|
+
* multi token the others remain. Without it, every registration of the
|
|
3142
|
+
* token is removed. Sealed tokens cannot be removed.
|
|
3143
|
+
* @returns Whether something was removed
|
|
3144
|
+
*/
|
|
3145
|
+
remove?(service: any, provider?: unknown): boolean;
|
|
2799
3146
|
}
|
|
2800
3147
|
/** DI token for `ICliServerAuthTokenProvider` (multi-provider) */
|
|
2801
|
-
declare const ICliServerAuthTokenProvider_TOKEN
|
|
3148
|
+
declare const ICliServerAuthTokenProvider_TOKEN: CliToken<ICliServerAuthTokenProvider>;
|
|
2802
3149
|
/** DI token for `ICliServerAuthService` */
|
|
2803
|
-
declare const ICliServerAuthService_TOKEN
|
|
3150
|
+
declare const ICliServerAuthService_TOKEN: CliToken<ICliServerAuthService>;
|
|
2804
3151
|
/**
|
|
2805
3152
|
* Integrators implement this interface to supply auth credentials
|
|
2806
3153
|
* for server requests. Multiple providers can be registered — the
|
|
@@ -2863,7 +3210,7 @@ interface ICliServerManager {
|
|
|
2863
3210
|
preferredServer?(): string | null;
|
|
2864
3211
|
}
|
|
2865
3212
|
/** Token for {@link ICliServerManager} */
|
|
2866
|
-
declare const ICliServerManager_TOKEN
|
|
3213
|
+
declare const ICliServerManager_TOKEN: CliToken<ICliServerManager>;
|
|
2867
3214
|
/**
|
|
2868
3215
|
* Internal service that resolves auth headers for a server by merging:
|
|
2869
3216
|
* 1. Static/dynamic headers from `CliServerConfig.headers`
|
|
@@ -3001,6 +3348,22 @@ type CliServerCapabilities = {
|
|
|
3001
3348
|
streaming?: boolean;
|
|
3002
3349
|
};
|
|
3003
3350
|
|
|
3351
|
+
/**
|
|
3352
|
+
* A DI token that carries the type of the service it identifies, so
|
|
3353
|
+
* `services.get(TOKEN)` is typed without a type argument:
|
|
3354
|
+
*
|
|
3355
|
+
* ```ts
|
|
3356
|
+
* export const ITodoStore_TOKEN = createCliToken<ITodoStore>('todo-store');
|
|
3357
|
+
* const store = context.services.get(ITodoStore_TOKEN); // ITodoStore | undefined
|
|
3358
|
+
* ```
|
|
3359
|
+
*
|
|
3360
|
+
* At runtime it is the plain string, so it works anywhere a string token does.
|
|
3361
|
+
*/
|
|
3362
|
+
type CliToken<T> = string & {
|
|
3363
|
+
readonly __cliTokenType?: T;
|
|
3364
|
+
};
|
|
3365
|
+
/** Create a typed {@link CliToken}. */
|
|
3366
|
+
declare function createCliToken<T>(name: string): CliToken<T>;
|
|
3004
3367
|
type MultiServices = {
|
|
3005
3368
|
/**
|
|
3006
3369
|
* When true, injector returns an array of instances. This is useful to allow multiple
|
|
@@ -3017,10 +3380,15 @@ type CliTypeProvider = MultiServices & {
|
|
|
3017
3380
|
deps?: any[];
|
|
3018
3381
|
};
|
|
3019
3382
|
type CliFactoryProvider = MultiServices & {
|
|
3020
|
-
useFactory:
|
|
3383
|
+
useFactory: (...args: any[]) => any;
|
|
3021
3384
|
/** DI tokens resolved from the container and passed as factory arguments. */
|
|
3022
3385
|
deps?: any[];
|
|
3023
3386
|
};
|
|
3387
|
+
/**
|
|
3388
|
+
* Service registration. `useFactory` and `useClass` providers are created
|
|
3389
|
+
* lazily, on the first `get()` of their token (or of a token depending on
|
|
3390
|
+
* them), so their `deps` may be registered after them.
|
|
3391
|
+
*/
|
|
3024
3392
|
type CliProvider = {
|
|
3025
3393
|
provide: any;
|
|
3026
3394
|
/** When true, this token is sealed after registration and cannot be overwritten. */
|
|
@@ -3135,6 +3503,9 @@ declare const enums: {
|
|
|
3135
3503
|
declare class CliModuleRegistry {
|
|
3136
3504
|
private readonly modules;
|
|
3137
3505
|
private readonly bootHandlers;
|
|
3506
|
+
private readonly unregisterHandlers;
|
|
3507
|
+
/** Registrations whose boot handlers are still running. */
|
|
3508
|
+
private readonly inFlight;
|
|
3138
3509
|
/** Optional warning callback — set by the engine to route through ICliLogger */
|
|
3139
3510
|
onWarn?: (message: string) => void;
|
|
3140
3511
|
/**
|
|
@@ -3147,6 +3518,23 @@ declare class CliModuleRegistry {
|
|
|
3147
3518
|
* skipped with a warning — this ensures only compatible frontend plugins load.
|
|
3148
3519
|
*/
|
|
3149
3520
|
register(module: ICliModule): Promise<void>;
|
|
3521
|
+
/**
|
|
3522
|
+
* Resolve once every registration in progress (including ones started
|
|
3523
|
+
* meanwhile, e.g. a plugin loading another) has finished booting.
|
|
3524
|
+
*/
|
|
3525
|
+
whenIdle(): Promise<void>;
|
|
3526
|
+
private registerInternal;
|
|
3527
|
+
/**
|
|
3528
|
+
* Register a handler that is called when a module is unregistered,
|
|
3529
|
+
* e.g. so its processors can be removed.
|
|
3530
|
+
*/
|
|
3531
|
+
onModuleUnregister(handler: (module: ICliModule) => void): void;
|
|
3532
|
+
/**
|
|
3533
|
+
* Unregister a module and notify all unregister handlers. A module
|
|
3534
|
+
* registered again afterwards (e.g. a newer version) boots again.
|
|
3535
|
+
* Returns the removed module, or `undefined` when it was not registered.
|
|
3536
|
+
*/
|
|
3537
|
+
unregister(name: string): ICliModule | undefined;
|
|
3150
3538
|
/**
|
|
3151
3539
|
* Get a module by name.
|
|
3152
3540
|
*/
|
|
@@ -3286,7 +3674,10 @@ declare class ServerVersionNegotiator {
|
|
|
3286
3674
|
* Returns the negotiated API version and the base path for all subsequent calls,
|
|
3287
3675
|
* or null if the server is unreachable or incompatible.
|
|
3288
3676
|
*/
|
|
3289
|
-
static discover(baseUrl: string, headers?: CliHeadersProvider
|
|
3677
|
+
static discover(baseUrl: string, headers?: CliHeadersProvider, options?: {
|
|
3678
|
+
/** Rethrow when the server cannot be reached (instead of `null`, "no discovery") */
|
|
3679
|
+
rethrowNetworkErrors?: boolean;
|
|
3680
|
+
}): Promise<{
|
|
3290
3681
|
apiVersion: number;
|
|
3291
3682
|
basePath: string;
|
|
3292
3683
|
} | null>;
|
|
@@ -3462,6 +3853,45 @@ declare const cliAccessMetadataGuards: ICliCommandGuard[];
|
|
|
3462
3853
|
*/
|
|
3463
3854
|
declare function cliDefaultServer(context: Pick<ICliExecutionContext, 'services' | 'options'>): CliServerConfig | undefined;
|
|
3464
3855
|
|
|
3856
|
+
/** A help row: the left column and its description. */
|
|
3857
|
+
type CliHelpRow = readonly [string, string];
|
|
3858
|
+
/** Write a `📋 Usage:` block with aligned, highlighted commands. */
|
|
3859
|
+
declare function writeUsage(context: ICliExecutionContext, rows: readonly CliHelpRow[]): void;
|
|
3860
|
+
/** Write a `📝 Examples:` block with aligned `# comments`. */
|
|
3861
|
+
declare function writeExamples(context: ICliExecutionContext, rows: readonly CliHelpRow[]): void;
|
|
3862
|
+
/**
|
|
3863
|
+
* Write a paragraph wrapped at word boundaries to the terminal width (at
|
|
3864
|
+
* most 100 columns), so long help text never breaks inside a word.
|
|
3865
|
+
*/
|
|
3866
|
+
declare function writeWrapped(context: ICliExecutionContext, text: string, indent?: number): void;
|
|
3867
|
+
/** `💡 Use <command> to <action>` hint. */
|
|
3868
|
+
declare function writeHint(context: ICliExecutionContext, command: string, action: string): void;
|
|
3869
|
+
|
|
3870
|
+
/**
|
|
3871
|
+
* Split text into arguments like a POSIX shell: spaces separate words,
|
|
3872
|
+
* quotes are removed (`"a b"` is one word), single quotes keep everything
|
|
3873
|
+
* literally, and a backslash escapes the next character outside quotes
|
|
3874
|
+
* (`my\ file`) or `"`, `\`, `$` and `` ` `` inside double quotes. A quote
|
|
3875
|
+
* without a closing one is ordinary text (`it's`).
|
|
3876
|
+
*/
|
|
3877
|
+
declare function splitShellWords(text: string): string[];
|
|
3878
|
+
/**
|
|
3879
|
+
* The arguments as a shell's echo prints them: {@link splitShellWords}
|
|
3880
|
+
* joined by one space. Inside double quotes, a backslash before other
|
|
3881
|
+
* characters stays (`"a\nb"`) for echo's escape step.
|
|
3882
|
+
*/
|
|
3883
|
+
declare function joinShellWords(text: string): string;
|
|
3884
|
+
/** Quote a value so {@link splitShellWords} reads it back as one word. */
|
|
3885
|
+
declare function quoteShellWord(value: string): string;
|
|
3886
|
+
|
|
3887
|
+
/**
|
|
3888
|
+
* Text given as one free-form argument (JSON, code, a query) without one
|
|
3889
|
+
* pair of quotes wrapping all of it: `'{"a": 1}'` -> `{"a": 1}`, and
|
|
3890
|
+
* `"say \"hi\""` -> `say "hi"`. Anything else is kept as typed, so quotes
|
|
3891
|
+
* and backslashes inside the text are never touched.
|
|
3892
|
+
*/
|
|
3893
|
+
declare function unquoteRawArgument(text: string): string;
|
|
3894
|
+
|
|
3465
3895
|
/**
|
|
3466
3896
|
* Retrieve a parameter's value from the parsed arguments, checking aliases.
|
|
3467
3897
|
* @param p The parameter descriptor
|
|
@@ -3614,7 +4044,7 @@ interface CliThemeInfo {
|
|
|
3614
4044
|
|
|
3615
4045
|
declare const DefaultThemeInfos: Record<string, CliThemeInfo>;
|
|
3616
4046
|
|
|
3617
|
-
declare const LIBRARY_VERSION = "2.0.0-beta.
|
|
4047
|
+
declare const LIBRARY_VERSION = "2.0.0-beta.18";
|
|
3618
4048
|
declare const API_VERSION = 2;
|
|
3619
4049
|
|
|
3620
4050
|
/**
|
|
@@ -3675,4 +4105,5 @@ declare class BrowserFileTransferService implements ICliFileTransferService {
|
|
|
3675
4105
|
private _pickFile;
|
|
3676
4106
|
}
|
|
3677
4107
|
|
|
3678
|
-
export { API_VERSION, BrowserFileTransferService, CANCELLATION_ERROR_MESSAGE, CLI_CONFIGURE_STORE_NAME, CancellablePromise,
|
|
4108
|
+
export { API_VERSION, BrowserFileTransferService, CANCELLATION_ERROR_MESSAGE, CLI_CONFIGURE_STORE_NAME, CancellablePromise, CliAccessDeniedError, CliBackgroundColor, CliForegroundColor, CliHttpError, CliIcon, CliLogLevel, CliModuleRegistry, CliServerPermissions, CliUsersPermissions, DEFAULT_DIR_PERMISSIONS, DEFAULT_FILE_PERMISSIONS, DefaultLibraryAuthor, DefaultThemeInfos, DefaultThemes, ICliAuditService_TOKEN, ICliAuthService_TOKEN, ICliAuthorizationService_TOKEN, ICliCommandGuard_TOKEN, ICliCompletionProvider_TOKEN, ICliDragDropService_TOKEN, ICliEventBus_TOKEN, ICliFilePickerProvider_TOKEN, ICliFileTransferService_TOKEN, ICliGroupsStoreService_TOKEN, ICliHttpClient_TOKEN, ICliKeyValueStore_TOKEN, ICliPermissionRegistry_TOKEN, ICliPermissionService_TOKEN, ICliServerAuthService_TOKEN, ICliServerAuthTokenProvider_TOKEN, ICliServerManager_TOKEN, ICliSessionsService_TOKEN, ICliTranslationService_TOKEN, ICliUserEventService_TOKEN, ICliUserSessionService_TOKEN, ICliUsersStoreService_TOKEN, LIBRARY_VERSION, ObjectDescriber, ServerVersionNegotiator, appendQueryParams, bootCliModule, bootUmdModule, buildAuthenticatedWebSocketUrl, clearTerminalLine, cliAccessMetadataGuards, cliAuthorize, cliCanAccess, cliDefaultServer, cliEvaluateAccess, cliHasPermission, cliMergePermissions, cliMissingPermissions, cliPermissionMatches, cliRequireAuthGuard, cliRequiredGroupsGuard, cliRequiredPermissionsGuard, colorFirstWord, colorizeJson, compareVersions, constants, createCliToken, createWorkerService, delay, derivePanelThemeStyles, enums, formatJson, getConfigValue, getParameterValue, getPluginConfigValue, getRightOfWord, highlightTextWithBg, initializeBrowserEnvironment, isCliAccessDeniedError, joinShellWords, loadPanelPosition, nextPanelPosition, quoteShellWord, resolveConfigurationCategories, resolveHeaders, resolveServerHeaders, resolveServerWebSocketUrl, satisfiesMinVersion, satisfiesVersionRange, savePanelPosition, splitShellWords, stripAnsi, toQueryString, truncateToWidth, unquoteRawArgument, utils, visibleLength, writeExamples, writeHint, writeUsage, writeWrapped };
|
|
4109
|
+
export type { CliAccessAction, CliAddUser, CliBackgroundServiceStatus, CliBackgroundServiceType, CliBootOptions, CliCommandGuardResult, CliDateOptions, CliEmitOptions, CliEngineSnapshot, CliEvent, CliEventData, CliEventHandler, CliEventMap, CliEventType, CliFactoryProvider, CliFilePickerOptions, CliFileResult, CliFullScreenOptions, CliHeadersProvider, CliHelpRow, CliHttpRequestOptions, CliLineOptions, CliMultiSelectOption, CliMultiSelectOptions, CliNotification, CliNotificationLevel, CliNumberOptions, CliOptions, CliPackageSource, CliPanelConfig, CliPanelHideAlignment, CliPanelPaneState, CliPanelPosition, CliPanelState, CliPanelTabState, CliPercentageProgressBarUpdateValueOptions, CliPermissionDefinition, CliProcessCommand, CliProcessorMetadata, CliProvider, CliSelectOption, CliSelectOptions, CliServerCapabilities, CliServerCommandDescriptor, CliServerConfig, CliServerOutput, CliServerResponse, CliServiceEventHandler, CliServiceExecutionMode, CliServiceLogLevel, CliState, CliStateConfiguration, CliStateScope, CliStateStoreOptions, CliTableOptions, CliTextAnimatorOptions, CliTheme, CliThemeCategory, CliThemeInfo, CliToken, CliTypeProvider, CliUpdateUser, CliValueProvider, CliWorkerInboundMessage, CliWorkerOutboundMessage, CustomEventType, DefaultThemesType, ICliAuditEntry, ICliAuditService, ICliAuthService, ICliAuthorizationService, ICliBackgroundService, ICliBackgroundServiceInfo, ICliBackgroundServiceRegistry, ICliClipboard, ICliCommandAuthor, ICliCommandChildProcessor, ICliCommandExecutorService, ICliCommandGuard, ICliCommandParameterDescriptor, ICliCommandProcessor, ICliCommandProcessorRegistry, ICliCompletionContext, ICliCompletionProvider, ICliConfigurableModule, ICliConfigurationOption, ICliDragDropService, ICliEventBus, ICliExecutionContext, ICliExecutionProcess, ICliFileEntry, ICliFilePickerProvider, ICliFileTransferService, ICliGlobalParameterHandler, ICliGroup, ICliGroupsStoreService, ICliHttpClient, ICliInputReader, ICliKeyValueStore, ICliLogger, ICliManagedInterval, ICliManagedTimer, ICliModule, ICliNotifier, ICliOwnership, ICliPanelRef, ICliPercentageProgressBar, ICliPermissionRegistry, ICliPermissionService, ICliPingServerService, ICliPrincipal, ICliProcessEntry, ICliProcessRegisterOptions, ICliProcessRegistry, ICliProcessorHook, ICliProgressBar, ICliProtectedResource, ICliServerAuthService, ICliServerAuthTokenProvider, ICliServerManager, ICliServiceContext, ICliServiceEvent, ICliServiceLogEntry, ICliServiceProvider, ICliSessionInfo, ICliSessionsService, ICliSpinner, ICliStateStore, ICliTerminalWriter, ICliTextAnimator, ICliTranslationService, ICliUmdModule, ICliUser, ICliUserCredentials, ICliUserEvent, ICliUserEventService, ICliUserSession, ICliUserSessionService, ICliUsersStoreService, ISyntaxHighlightRule, ISyntaxHighlighter, ISyntaxTheme, LineState, Package, ServerVersionInfo, WorkerServiceContext };
|