@franzzemen/brokenstock-shell 0.0.28 → 0.0.30

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, makeEnvironmentProviders, signal, computed, Injectable, inject, input, Directive, isDevMode, effect, untracked, HostListener, ViewChild, ChangeDetectionStrategy, Component, NgZone, viewChild, afterNextRender } from '@angular/core';
3
3
  import * as i2$1 from '@angular/router';
4
- import { Router, RouterLink, RouterLinkActive, RouterOutlet, ActivatedRoute } from '@angular/router';
4
+ import { Router, RouterLink, ActivatedRoute, RouterLinkActive, RouterOutlet } from '@angular/router';
5
5
  import { HttpHeader, BEARER_TOKEN_REGEX, USERNAME_REGEX, PASSWORD_REGEX } from '@franzzemen/utility';
6
6
  import { validateCredentials } from '@franzzemen/identity';
7
7
  import { HttpClient } from '@angular/common/http';
@@ -11,7 +11,8 @@ import { NG_VALIDATORS, FormsModule } from '@angular/forms';
11
11
  import { Marked } from 'marked';
12
12
  import { gfmHeadingId } from 'marked-gfm-heading-id';
13
13
  import fm from 'front-matter';
14
- import { NgClass, DOCUMENT, DatePipe } from '@angular/common';
14
+ import { NgClass, CommonModule, DOCUMENT, DatePipe } from '@angular/common';
15
+ import { Title, Meta } from '@angular/platform-browser';
15
16
  import { z } from 'zod/v4';
16
17
  import * as i1 from '@angular/material/icon';
17
18
  import { MatIconModule } from '@angular/material/icon';
@@ -1236,6 +1237,375 @@ var faqAuthoringPanel = /*#__PURE__*/Object.freeze({
1236
1237
  FaqAuthoringPanel: FaqAuthoringPanel
1237
1238
  });
1238
1239
 
1240
+ /**
1241
+ * Canonical public base URL (no trailing slash) used for OpenGraph,
1242
+ * Twitter, JSON-LD canonical URLs, and sitemap entries on the
1243
+ * public FAQ pages. Default empty string — falls back to relative
1244
+ * `og:url` etc. when unset, which is fine for previewing but
1245
+ * suboptimal for production SEO. Consumer apps should override.
1246
+ */
1247
+ const FAQ_PUBLIC_SITE_BASE_URL = new InjectionToken('FAQ_PUBLIC_SITE_BASE_URL', { providedIn: 'root', factory: () => '' });
1248
+ const FAQ_PUBLIC_PUBLISHER = new InjectionToken('FAQ_PUBLIC_PUBLISHER', { providedIn: 'root', factory: () => ({ name: '' }) });
1249
+
1250
+ /**
1251
+ * Public, SEO-targeted FAQ index. Prerendered at build time on the
1252
+ * consumer side (e.g. /help in broken-stock). Lists every manifest
1253
+ * entry where `audience === 'public' && seoReady === true`, grouped
1254
+ * by category and ordered by `order`.
1255
+ *
1256
+ * SEO (E17): sets <title>, meta description, OG, and Twitter tags.
1257
+ * JSON-LD (E18): emits a schema.org CollectionPage referencing
1258
+ * each child entry as an ItemList.
1259
+ */
1260
+ class PublicFaqIndex {
1261
+ constructor() {
1262
+ this.loader = inject(FAQ_CONTENT_LOADER);
1263
+ this.title = inject(Title);
1264
+ this.meta = inject(Meta);
1265
+ this.siteBase = inject(FAQ_PUBLIC_SITE_BASE_URL);
1266
+ this.publisher = inject(FAQ_PUBLIC_PUBLISHER);
1267
+ this._entries = signal([], ...(ngDevMode ? [{ debugName: "_entries" }] : /* istanbul ignore next */ []));
1268
+ this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
1269
+ this.visibleEntries = computed(() => this._entries().filter((e) => e.audience === 'public' && e.seoReady), ...(ngDevMode ? [{ debugName: "visibleEntries" }] : /* istanbul ignore next */ []));
1270
+ this.groups = computed(() => {
1271
+ const visible = this.visibleEntries();
1272
+ const byCategory = new Map();
1273
+ for (const entry of visible) {
1274
+ const list = byCategory.get(entry.category) ?? [];
1275
+ list.push(entry);
1276
+ byCategory.set(entry.category, list);
1277
+ }
1278
+ const groups = [];
1279
+ for (const [category, entries] of byCategory) {
1280
+ entries.sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
1281
+ groups.push({ category, entries });
1282
+ }
1283
+ groups.sort((a, b) => a.category.localeCompare(b.category));
1284
+ return groups;
1285
+ }, ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
1286
+ this.jsonLd = computed(() => {
1287
+ const entries = this.visibleEntries();
1288
+ if (entries.length === 0)
1289
+ return null;
1290
+ const base = this.siteBase.replace(/\/+$/, '');
1291
+ const indexUrl = `${base}/help`;
1292
+ const ld = {
1293
+ '@context': 'https://schema.org',
1294
+ '@type': 'CollectionPage',
1295
+ name: 'Brokenstock Help',
1296
+ url: indexUrl,
1297
+ mainEntity: {
1298
+ '@type': 'ItemList',
1299
+ itemListElement: entries.map((entry, idx) => ({
1300
+ '@type': 'ListItem',
1301
+ position: idx + 1,
1302
+ url: `${base}/help/${entry.file}`,
1303
+ name: entry.title,
1304
+ })),
1305
+ },
1306
+ };
1307
+ if (this.publisher.name) {
1308
+ const pub = {
1309
+ '@type': 'Organization',
1310
+ name: this.publisher.name,
1311
+ };
1312
+ if (this.publisher.url)
1313
+ pub['url'] = this.publisher.url;
1314
+ if (this.publisher.logo)
1315
+ pub['logo'] = this.publisher.logo;
1316
+ ld['publisher'] = pub;
1317
+ }
1318
+ return serializeJsonLd$1(ld);
1319
+ }, ...(ngDevMode ? [{ debugName: "jsonLd" }] : /* istanbul ignore next */ []));
1320
+ }
1321
+ async ngOnInit() {
1322
+ try {
1323
+ const manifest = await this.loader.loadManifest();
1324
+ this._entries.set(manifest.entries);
1325
+ this.applyMeta();
1326
+ }
1327
+ finally {
1328
+ this.loading.set(false);
1329
+ }
1330
+ }
1331
+ applyMeta() {
1332
+ const base = this.siteBase.replace(/\/+$/, '');
1333
+ const url = `${base}/help`;
1334
+ const description = 'Documentation and walkthroughs for the Brokenstock trade-journal platform.';
1335
+ this.title.setTitle('Help — Brokenstock');
1336
+ this.meta.updateTag({ name: 'description', content: description });
1337
+ this.meta.updateTag({ property: 'og:type', content: 'website' });
1338
+ this.meta.updateTag({ property: 'og:title', content: 'Help — Brokenstock' });
1339
+ this.meta.updateTag({ property: 'og:description', content: description });
1340
+ this.meta.updateTag({ property: 'og:url', content: url });
1341
+ if (this.publisher.name) {
1342
+ this.meta.updateTag({ property: 'og:site_name', content: this.publisher.name });
1343
+ }
1344
+ this.meta.updateTag({ name: 'twitter:card', content: 'summary' });
1345
+ this.meta.updateTag({ name: 'twitter:title', content: 'Help — Brokenstock' });
1346
+ this.meta.updateTag({ name: 'twitter:description', content: description });
1347
+ }
1348
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1349
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: PublicFaqIndex, isStandalone: true, selector: "public-faq-index", ngImport: i0, template: `
1350
+ <article class="public-faq-index">
1351
+ <header>
1352
+ <h1>Brokenstock Help</h1>
1353
+ <p class="lead">Documentation and walkthroughs for the Brokenstock trade-journal platform.</p>
1354
+ </header>
1355
+ @if (loading()) {
1356
+ <p>Loading…</p>
1357
+ } @else if (groups().length === 0) {
1358
+ <p>No help pages are published yet.</p>
1359
+ } @else {
1360
+ @for (group of groups(); track group.category) {
1361
+ <section>
1362
+ <h2>{{ group.category }}</h2>
1363
+ <ul>
1364
+ @for (entry of group.entries; track entry.key) {
1365
+ <li>
1366
+ <a [routerLink]="['/help', entry.file]">{{ entry.title }}</a>
1367
+ @if (entry.description) {
1368
+ <span class="desc"> — {{ entry.description }}</span>
1369
+ }
1370
+ </li>
1371
+ }
1372
+ </ul>
1373
+ </section>
1374
+ }
1375
+ }
1376
+ @if (jsonLd(); as ld) {
1377
+ <script type="application/ld+json">{{ ld }}</script>
1378
+ }
1379
+ </article>
1380
+ `, isInline: true, styles: [":host{display:block}.public-faq-index{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#555;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid #eee;padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}a{color:#1565c0;text-decoration:none;font-weight:500}a:hover{text-decoration:underline}.desc{color:#666;font-weight:400}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
1381
+ }
1382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqIndex, decorators: [{
1383
+ type: Component,
1384
+ args: [{ selector: 'public-faq-index', standalone: true, imports: [CommonModule, RouterLink], template: `
1385
+ <article class="public-faq-index">
1386
+ <header>
1387
+ <h1>Brokenstock Help</h1>
1388
+ <p class="lead">Documentation and walkthroughs for the Brokenstock trade-journal platform.</p>
1389
+ </header>
1390
+ @if (loading()) {
1391
+ <p>Loading…</p>
1392
+ } @else if (groups().length === 0) {
1393
+ <p>No help pages are published yet.</p>
1394
+ } @else {
1395
+ @for (group of groups(); track group.category) {
1396
+ <section>
1397
+ <h2>{{ group.category }}</h2>
1398
+ <ul>
1399
+ @for (entry of group.entries; track entry.key) {
1400
+ <li>
1401
+ <a [routerLink]="['/help', entry.file]">{{ entry.title }}</a>
1402
+ @if (entry.description) {
1403
+ <span class="desc"> — {{ entry.description }}</span>
1404
+ }
1405
+ </li>
1406
+ }
1407
+ </ul>
1408
+ </section>
1409
+ }
1410
+ }
1411
+ @if (jsonLd(); as ld) {
1412
+ <script type="application/ld+json">{{ ld }}</script>
1413
+ }
1414
+ </article>
1415
+ `, styles: [":host{display:block}.public-faq-index{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#555;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid #eee;padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}a{color:#1565c0;text-decoration:none;font-weight:500}a:hover{text-decoration:underline}.desc{color:#666;font-weight:400}\n"] }]
1416
+ }] });
1417
+ function serializeJsonLd$1(obj) {
1418
+ return JSON.stringify(obj).replace(/</g, '\\u003c');
1419
+ }
1420
+
1421
+ /**
1422
+ * Public, SEO-targeted FAQ page. Prerendered at build time per
1423
+ * qualifying manifest entry (e.g. /help/landing, /help/trade/segments).
1424
+ *
1425
+ * The route is `help/**` so multi-segment file paths work; this
1426
+ * component reads the wildcard path off `ActivatedRoute.url`.
1427
+ *
1428
+ * SEO (E17): sets <title>, meta description, OpenGraph and Twitter
1429
+ * Card tags using Angular's Title + Meta services (SSR-compatible).
1430
+ * JSON-LD (E18): emits a schema.org Article (or BlogPosting) object
1431
+ * via an inline <script type="application/ld+json"> element. The
1432
+ * raw JSON has `<` escaped to `<` so a stray `</script>` inside
1433
+ * data won't break the surrounding tag.
1434
+ */
1435
+ class PublicFaqPage {
1436
+ constructor() {
1437
+ this.route = inject(ActivatedRoute);
1438
+ this.loader = inject(FAQ_CONTENT_LOADER);
1439
+ this.renderer = inject(FaqMarkdownRendererService);
1440
+ this.title = inject(Title);
1441
+ this.meta = inject(Meta);
1442
+ this.siteBase = inject(FAQ_PUBLIC_SITE_BASE_URL);
1443
+ this.publisher = inject(FAQ_PUBLIC_PUBLISHER);
1444
+ this.entry = signal(null, ...(ngDevMode ? [{ debugName: "entry" }] : /* istanbul ignore next */ []));
1445
+ this.body = signal('', ...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
1446
+ this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
1447
+ this.renderedHtml = computed(() => {
1448
+ const entry = this.entry();
1449
+ const body = this.body();
1450
+ if (!entry || !body)
1451
+ return '';
1452
+ return this.renderer.render(body, {
1453
+ context: 'page',
1454
+ imagePrefix: entry.imagePrefix
1455
+ ? `/assets/faq/${entry.imagePrefix}`
1456
+ : undefined,
1457
+ });
1458
+ }, ...(ngDevMode ? [{ debugName: "renderedHtml" }] : /* istanbul ignore next */ []));
1459
+ this.jsonLd = computed(() => {
1460
+ const entry = this.entry();
1461
+ if (!entry)
1462
+ return null;
1463
+ const url = this.canonicalUrl(entry);
1464
+ const ld = {
1465
+ '@context': 'https://schema.org',
1466
+ '@type': 'Article',
1467
+ headline: entry.title,
1468
+ url,
1469
+ mainEntityOfPage: url,
1470
+ };
1471
+ if (entry.description)
1472
+ ld['description'] = entry.description;
1473
+ if (this.publisher.name) {
1474
+ const pub = {
1475
+ '@type': 'Organization',
1476
+ name: this.publisher.name,
1477
+ };
1478
+ if (this.publisher.url)
1479
+ pub['url'] = this.publisher.url;
1480
+ if (this.publisher.logo)
1481
+ pub['logo'] = this.publisher.logo;
1482
+ ld['publisher'] = pub;
1483
+ ld['author'] = pub;
1484
+ }
1485
+ return serializeJsonLd(ld);
1486
+ }, ...(ngDevMode ? [{ debugName: "jsonLd" }] : /* istanbul ignore next */ []));
1487
+ }
1488
+ async ngOnInit() {
1489
+ try {
1490
+ const segments = this.route.snapshot.url.map((s) => s.path);
1491
+ const filePath = segments.join('/');
1492
+ if (!filePath) {
1493
+ this.applyNotFoundMeta();
1494
+ return;
1495
+ }
1496
+ const manifest = await this.loader.loadManifest();
1497
+ const match = manifest.entries.find((e) => e.file === filePath && e.audience === 'public' && e.seoReady);
1498
+ if (!match) {
1499
+ this.applyNotFoundMeta();
1500
+ return;
1501
+ }
1502
+ const content = await this.loader.loadContent(match.key);
1503
+ if (content === null) {
1504
+ this.applyNotFoundMeta();
1505
+ return;
1506
+ }
1507
+ const parsed = this.renderer.parse(content);
1508
+ this.entry.set(match);
1509
+ this.body.set(parsed.body);
1510
+ this.applyMeta(match);
1511
+ }
1512
+ finally {
1513
+ this.loading.set(false);
1514
+ }
1515
+ }
1516
+ applyMeta(entry) {
1517
+ const url = this.canonicalUrl(entry);
1518
+ const description = entry.description ?? '';
1519
+ const title = `${entry.title} — Help`;
1520
+ this.title.setTitle(title);
1521
+ this.meta.updateTag({ name: 'description', content: description });
1522
+ this.meta.updateTag({ property: 'og:type', content: 'article' });
1523
+ this.meta.updateTag({ property: 'og:title', content: entry.title });
1524
+ this.meta.updateTag({ property: 'og:description', content: description });
1525
+ this.meta.updateTag({ property: 'og:url', content: url });
1526
+ if (this.publisher.name) {
1527
+ this.meta.updateTag({ property: 'og:site_name', content: this.publisher.name });
1528
+ }
1529
+ this.meta.updateTag({ name: 'twitter:card', content: 'summary' });
1530
+ this.meta.updateTag({ name: 'twitter:title', content: entry.title });
1531
+ this.meta.updateTag({ name: 'twitter:description', content: description });
1532
+ }
1533
+ applyNotFoundMeta() {
1534
+ this.title.setTitle('Page not found — Help');
1535
+ this.meta.updateTag({ name: 'robots', content: 'noindex' });
1536
+ }
1537
+ canonicalUrl(entry) {
1538
+ const base = this.siteBase.replace(/\/+$/, '');
1539
+ return `${base}/help/${entry.file}`;
1540
+ }
1541
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqPage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1542
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: PublicFaqPage, isStandalone: true, selector: "public-faq-page", ngImport: i0, template: `
1543
+ <article class="public-faq-page">
1544
+ <nav class="crumbs">
1545
+ <a routerLink="/help">← Help</a>
1546
+ </nav>
1547
+ @if (loading()) {
1548
+ <p>Loading…</p>
1549
+ } @else if (!entry()) {
1550
+ <header>
1551
+ <h1>Page not found</h1>
1552
+ <p>That help page doesn't exist or isn't published. Try the <a routerLink="/help">help index</a>.</p>
1553
+ </header>
1554
+ } @else {
1555
+ <header>
1556
+ <h1>{{ entry()!.title }}</h1>
1557
+ @if (entry()!.description) {
1558
+ <p class="lead">{{ entry()!.description }}</p>
1559
+ }
1560
+ </header>
1561
+ <div class="body" [innerHTML]="renderedHtml()"></div>
1562
+ @if (jsonLd(); as ld) {
1563
+ <script type="application/ld+json">{{ ld }}</script>
1564
+ }
1565
+ }
1566
+ </article>
1567
+ `, isInline: true, styles: [":host{display:block}.public-faq-page{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6}.crumbs{margin-bottom:1.5rem;font-size:.9rem}.crumbs a{color:#1565c0;text-decoration:none}.crumbs a:hover{text-decoration:underline}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#555;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#1565c0}.body img{max-width:100%;height:auto}.body pre{background:#f6f8fa;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#f6f8fa;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
1568
+ }
1569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: PublicFaqPage, decorators: [{
1570
+ type: Component,
1571
+ args: [{ selector: 'public-faq-page', standalone: true, imports: [CommonModule, RouterLink], template: `
1572
+ <article class="public-faq-page">
1573
+ <nav class="crumbs">
1574
+ <a routerLink="/help">← Help</a>
1575
+ </nav>
1576
+ @if (loading()) {
1577
+ <p>Loading…</p>
1578
+ } @else if (!entry()) {
1579
+ <header>
1580
+ <h1>Page not found</h1>
1581
+ <p>That help page doesn't exist or isn't published. Try the <a routerLink="/help">help index</a>.</p>
1582
+ </header>
1583
+ } @else {
1584
+ <header>
1585
+ <h1>{{ entry()!.title }}</h1>
1586
+ @if (entry()!.description) {
1587
+ <p class="lead">{{ entry()!.description }}</p>
1588
+ }
1589
+ </header>
1590
+ <div class="body" [innerHTML]="renderedHtml()"></div>
1591
+ @if (jsonLd(); as ld) {
1592
+ <script type="application/ld+json">{{ ld }}</script>
1593
+ }
1594
+ }
1595
+ </article>
1596
+ `, styles: [":host{display:block}.public-faq-page{max-width:860px;margin:0 auto;padding:2rem 1.25rem 4rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6}.crumbs{margin-bottom:1.5rem;font-size:.9rem}.crumbs a{color:#1565c0;text-decoration:none}.crumbs a:hover{text-decoration:underline}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#555;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#1565c0}.body img{max-width:100%;height:auto}.body pre{background:#f6f8fa;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#f6f8fa;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}\n"] }]
1597
+ }] });
1598
+ /**
1599
+ * Serializes a JSON-LD object for safe inclusion in a
1600
+ * `<script type="application/ld+json">` element. Escapes `<` so a
1601
+ * stray `</script>` inside any string field cannot break out of the
1602
+ * script tag. (Browsers and crawlers parse the resulting `<`
1603
+ * back to `<` per JSON spec.)
1604
+ */
1605
+ function serializeJsonLd(obj) {
1606
+ return JSON.stringify(obj).replace(/</g, '\\u003c');
1607
+ }
1608
+
1239
1609
  class ThemeService {
1240
1610
  constructor() {
1241
1611
  this.mode = signal('dark', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
@@ -2048,5 +2418,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
2048
2418
  * Generated bundle index. Do not edit.
2049
2419
  */
2050
2420
 
2051
- export { AuthenticationService, CLEAR_USAGE, CommandRegistryService, CommandService, CommandTerminal, ConfirmDialog, FAQ_CONTENT_LOADER, FAQ_DEV_EDITOR, FAQ_DEV_MODE, FAQ_DEV_WORKSPACE_ROOT, FaqAuthoringPanel, FaqHistoryService, FaqMarkdownRendererService, FaqModal, FaqService, HELP_USAGE, HttpFaqContentLoader, KeyboardShortcutService, Login, MainContent, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
2421
+ 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, RegexValidatorDirective, SHELL_APP_NAME, SHELL_AUTH_URLS, SHELL_COMMANDS, SHELL_MENU_ITEMS, SHELL_POST_LOGIN_ROUTE, Shell, SideMenu, StatusBar, TerminalFocusService, ThemeService, ThinkingService, audienceAllowed, authGuard, authInterceptor, buildFallbackChain, guestGuard, provideShellConfig, tokenize };
2052
2422
  //# sourceMappingURL=franzzemen-brokenstock-shell.mjs.map