@franzzemen/brokenstock-shell 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -32,6 +32,23 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
|
32
32
|
import * as i1$2 from '@angular/material/dialog';
|
|
33
33
|
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Does `url` fall inside any of `patterns`? Query string and fragment are
|
|
37
|
+
* stripped; a pattern matches when the path equals it or continues past it at
|
|
38
|
+
* a `/`; a `:param` segment matches any one non-empty segment. Same rule as
|
|
39
|
+
* the lexicon's `matchesRoute`, tested there and here.
|
|
40
|
+
*/
|
|
41
|
+
function matchesRoute(url, patterns) {
|
|
42
|
+
const path = url.split('?')[0].split('#')[0].replace(/\/+$/, '') || '/';
|
|
43
|
+
const segments = path.split('/');
|
|
44
|
+
return patterns.some(pattern => {
|
|
45
|
+
const want = pattern.replace(/\/+$/, '').split('/');
|
|
46
|
+
if (want.length > segments.length)
|
|
47
|
+
return false;
|
|
48
|
+
return want.every((w, i) => (w.startsWith(':') ? segments[i].length > 0 : w === segments[i]));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
35
52
|
const SHELL_APP_NAME = new InjectionToken('SHELL_APP_NAME');
|
|
36
53
|
const SHELL_MENU_ITEMS = new InjectionToken('SHELL_MENU_ITEMS');
|
|
37
54
|
const SHELL_AUTH_URLS = new InjectionToken('SHELL_AUTH_URLS');
|
|
@@ -2557,6 +2574,7 @@ class FaqCommand {
|
|
|
2557
2574
|
this.description = 'Open the in-app FAQ help system';
|
|
2558
2575
|
this.usage = FAQ_USAGE;
|
|
2559
2576
|
this.requiresAuth = false;
|
|
2577
|
+
this.scope = 'global';
|
|
2560
2578
|
this.argsSchema = z.array(z.string()).max(50);
|
|
2561
2579
|
}
|
|
2562
2580
|
execute(args) {
|
|
@@ -2716,6 +2734,7 @@ class CommandService {
|
|
|
2716
2734
|
...(ngDevMode ? [{ debugName: "helpOverlay" }] : /* istanbul ignore next */ []));
|
|
2717
2735
|
this.authService = inject(AuthenticationService);
|
|
2718
2736
|
this.registry = inject(CommandRegistryService);
|
|
2737
|
+
this.router = inject(Router);
|
|
2719
2738
|
this.lastResult = computed(() => {
|
|
2720
2739
|
const h = this.history();
|
|
2721
2740
|
return h.length > 0 ? h[h.length - 1].result : null;
|
|
@@ -2845,9 +2864,12 @@ class CommandService {
|
|
|
2845
2864
|
' help — List available commands',
|
|
2846
2865
|
// Unavailable commands stay listed, annotated. Removing them would make
|
|
2847
2866
|
// the CLI look broken rather than gated.
|
|
2867
|
+
// A command scoped to another screen stays listed too, with its screen
|
|
2868
|
+
// named rather than hidden (trades-tree.prd.md D31): hiding it would
|
|
2869
|
+
// read as a broken CLI.
|
|
2848
2870
|
...registered.map(c => {
|
|
2849
2871
|
const availability = c.isAvailable?.();
|
|
2850
|
-
const suffix = availability && !availability.ok ? ` [unavailable — ${availability.reason}]` :
|
|
2872
|
+
const suffix = availability && !availability.ok ? ` [unavailable — ${availability.reason}]` : this.#scopeSuffix(c.scope);
|
|
2851
2873
|
return ` ${c.name} — ${c.description}${suffix}`;
|
|
2852
2874
|
}),
|
|
2853
2875
|
];
|
|
@@ -2894,7 +2916,23 @@ class CommandService {
|
|
|
2894
2916
|
return notLoggedIn();
|
|
2895
2917
|
}
|
|
2896
2918
|
if (hasHelp) {
|
|
2897
|
-
|
|
2919
|
+
// `help <command>` is normalised to `<command> help` above, so this is
|
|
2920
|
+
// the one place a command's usage is shown; the screen it works on goes
|
|
2921
|
+
// here (D31).
|
|
2922
|
+
return { success: true, message: def.usage + this.#whereNote(def.scope), timestamp: new Date(), isHelp: true };
|
|
2923
|
+
}
|
|
2924
|
+
// Screen gate (trades-tree.prd.md D30). A command bound to state only one
|
|
2925
|
+
// screen sets is refused off that screen with the screen named, the way
|
|
2926
|
+
// `tab` always did on its own. A command that navigates to its screen is
|
|
2927
|
+
// never refused here — declaring its routes is what lets `help` say where
|
|
2928
|
+
// it lives, and taking the user there is the handler's job (D32).
|
|
2929
|
+
if (def.scope !== 'global' && def.scope.elsewhere === 'refuse' && !matchesRoute(this.router.url, def.scope.routes)) {
|
|
2930
|
+
return {
|
|
2931
|
+
success: false,
|
|
2932
|
+
message: `'${command}' works on ${def.scope.screen}.`,
|
|
2933
|
+
severity: 'error',
|
|
2934
|
+
timestamp: new Date(),
|
|
2935
|
+
};
|
|
2898
2936
|
}
|
|
2899
2937
|
// Readiness gate. Deliberately ahead of argument validation: "you can't use
|
|
2900
2938
|
// this yet, here's why" is more useful than a complaint about the arguments
|
|
@@ -2926,7 +2964,17 @@ class CommandService {
|
|
|
2926
2964
|
// user decides whether it's worth unlocking. The gate is noted, not enforced.
|
|
2927
2965
|
const availability = def.isAvailable?.();
|
|
2928
2966
|
const note = availability && !availability.ok ? `\n\nCurrently unavailable — ${availability.reason}` : '';
|
|
2929
|
-
return { success: true, message: def.usage + note, timestamp: new Date(), isHelp: true };
|
|
2967
|
+
return { success: true, message: def.usage + this.#whereNote(def.scope) + note, timestamp: new Date(), isHelp: true };
|
|
2968
|
+
}
|
|
2969
|
+
/** "Works on the Trades screen." — appended to a scoped command's usage. */
|
|
2970
|
+
#whereNote(scope) {
|
|
2971
|
+
return scope === 'global' ? '' : `\n\nWorks on ${scope.screen}.`;
|
|
2972
|
+
}
|
|
2973
|
+
/** `help`'s annotation for a command scoped to a screen other than the current one. */
|
|
2974
|
+
#scopeSuffix(scope) {
|
|
2975
|
+
if (scope === 'global' || matchesRoute(this.router.url, scope.routes))
|
|
2976
|
+
return '';
|
|
2977
|
+
return ` [${scope.screen}]`;
|
|
2930
2978
|
}
|
|
2931
2979
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: CommandService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2932
2980
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: CommandService, providedIn: 'root' }); }
|
|
@@ -3463,5 +3511,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
|
|
|
3463
3511
|
* Generated bundle index. Do not edit.
|
|
3464
3512
|
*/
|
|
3465
3513
|
|
|
3466
|
-
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FAQ_PUBLIC_PUBLISHER, FAQ_PUBLIC_SITE_BASE_URL, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, PublicFaqIndex, PublicFaqPage, PublicFaqToc, RegexValidatorDirective, SESSION_TOKEN_KEY, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, SHELL_SHARED_SESSION, SessionTokenStore, Shell, SideMenu, StatusBar, TerminalFocusService, TerminalVisibilityService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, decideRenewal, guestGuard, provideShellConfig, tokenize };
|
|
3514
|
+
export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FAQ_PUBLIC_PUBLISHER, FAQ_PUBLIC_SITE_BASE_URL, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, PublicFaqIndex, PublicFaqPage, PublicFaqToc, RegexValidatorDirective, SESSION_TOKEN_KEY, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, SHELL_SHARED_SESSION, SessionTokenStore, Shell, SideMenu, StatusBar, TerminalFocusService, TerminalVisibilityService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, decideRenewal, guestGuard, matchesRoute, provideShellConfig, tokenize };
|
|
3467
3515
|
//# sourceMappingURL=franzzemen-brokenstock-shell.mjs.map
|