@dudousxd/nestjs-telescope-ui 1.1.0 → 1.2.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @dudousxd/nestjs-telescope-ui
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`0ba0c24`](https://github.com/DavideCarvalho/nestjs-telescope/commit/0ba0c24ac68c34ad75fe51775dc7089e308c3126) - Three dashboard improvements:
8
+
9
+ - **Criticality-first Overview.** The Overview is reorganized so operational triage sits above the fold: a focused stat row (Requests, **Error rate** = exceptions ÷ requests over the window — red above 5%, Failed jobs, and **Slow requests** = routes over their p99 budget), then Recent failures, a newly-mounted **N+1 query hotspots** card, Slowest, and a **Queues needing attention** card that lists only queues with failed jobs or a large pending backlog (and says "All queues healthy" when clean). Trends and Telescope self-health (throughput, by-type, server, health, retention) move below. All figures derive from data already served by `/pulse` and `/queues` — no new endpoints.
10
+ - **Watcher-driven navigation.** The sidebar Watchers list renders only types whose watcher is registered (from `meta.watchers`); `request` and `exception` always show, direct URLs to hidden types still work, and everything shows while `meta` is loading (no flash of hidden nav).
11
+ - **Dedicated User filter.** The entries filter bar gains a User combobox over the `user:` tag namespace (bare ids + counts); selecting one applies the `tag=user:<id>` filter but renders as a `User: <id>` chip, and a `user:` tag arriving via `?tag=` (the entries-table pivot links) is recognized and shown in the User control instead of the generic tag chip.
12
+
3
13
  ## 1.1.0
4
14
 
5
15
  ### Minor Changes
@@ -37,4 +37,21 @@ export declare function resolveEntryQuery(typeId: string): {
37
37
  type?: string;
38
38
  tag?: string;
39
39
  };
40
+ /**
41
+ * Which nav/tab type ids to show given the server's registered watcher list.
42
+ *
43
+ * `/api/meta.watchers` carries EntryType strings (e.g. `['request',
44
+ * 'exception', 'query', 'job', 'redis']`) — the `type` field of each
45
+ * registered watcher, see the core registrar. We hide a type only when meta
46
+ * POSITIVELY says its watcher is absent:
47
+ * - `watchers === undefined` → meta hasn't loaded or is from an older server
48
+ * that predates the field; show everything (no flash-of-hidden-nav, and old
49
+ * servers keep working).
50
+ * - otherwise → show a type when it's always-visible, its id is in the watcher
51
+ * set, or its backing query type is (so `schedule` follows `job`).
52
+ *
53
+ * Pure and order-preserving (keeps the canonical `ENTRY_TYPES` order) so it's
54
+ * trivially unit-testable.
55
+ */
56
+ export declare function visibleEntryTypes(types: readonly EntryTypeDef[], watchers: readonly string[] | undefined): EntryTypeDef[];
40
57
  //# sourceMappingURL=entry-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-types.d.ts","sourceRoot":"","sources":["../../../src/react/components/entry-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,eAAO,MAAM,WAAW,EAAE,YAAY,EAmBrC,CAAC;AAQF,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAEjF"}
1
+ {"version":3,"file":"entry-types.d.ts","sourceRoot":"","sources":["../../../src/react/components/entry-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,eAAO,MAAM,WAAW,EAAE,YAAY,EAmBrC,CAAC;AAQF,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAEjF;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACtC,YAAY,EAAE,CAUhB"}
@@ -41,4 +41,45 @@ export function isKnownType(typeId) {
41
41
  export function resolveEntryQuery(typeId) {
42
42
  return BY_ID[typeId]?.query ?? { type: typeId };
43
43
  }
44
+ /**
45
+ * Entry types that are ALWAYS captured regardless of which watchers a host
46
+ * registers, so their nav items must always show. `request` and `exception`
47
+ * are wired unconditionally by the core registrar (see
48
+ * `telescope-watcher-registrar.service.ts`, which seeds `[Request, Exception]`
49
+ * before appending registered watchers), so `/api/meta.watchers` always lists
50
+ * them — but we hard-code them here too so the nav stays correct even if a
51
+ * future server drops them from the list. `schedule` rides on the `job`
52
+ * watcher (scheduled runs are tagged `job` entries), so it's visible whenever
53
+ * `job` is.
54
+ */
55
+ const ALWAYS_VISIBLE_TYPE_IDS = new Set(['request', 'exception']);
56
+ /**
57
+ * Which nav/tab type ids to show given the server's registered watcher list.
58
+ *
59
+ * `/api/meta.watchers` carries EntryType strings (e.g. `['request',
60
+ * 'exception', 'query', 'job', 'redis']`) — the `type` field of each
61
+ * registered watcher, see the core registrar. We hide a type only when meta
62
+ * POSITIVELY says its watcher is absent:
63
+ * - `watchers === undefined` → meta hasn't loaded or is from an older server
64
+ * that predates the field; show everything (no flash-of-hidden-nav, and old
65
+ * servers keep working).
66
+ * - otherwise → show a type when it's always-visible, its id is in the watcher
67
+ * set, or its backing query type is (so `schedule` follows `job`).
68
+ *
69
+ * Pure and order-preserving (keeps the canonical `ENTRY_TYPES` order) so it's
70
+ * trivially unit-testable.
71
+ */
72
+ export function visibleEntryTypes(types, watchers) {
73
+ if (watchers === undefined)
74
+ return [...types];
75
+ const registered = new Set(watchers);
76
+ return types.filter((type) => {
77
+ if (ALWAYS_VISIBLE_TYPE_IDS.has(type.id))
78
+ return true;
79
+ // A type with a `query` override (e.g. schedule → job) is backed by that
80
+ // query type's watcher, not its own id.
81
+ const backingType = type.query?.type ?? type.id;
82
+ return registered.has(type.id) || registered.has(backingType);
83
+ });
84
+ }
44
85
  //# sourceMappingURL=entry-types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-types.js","sourceRoot":"","sources":["../../../src/react/components/entry-types.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,WAAW,GAAmB;IACzC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,gBAAgB,EAAE;IAC3D,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE;IACpD,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE;IAC3D,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE;IAClD,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE;IACjD,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE;IACnD;QACE,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,UAAU;QACjB,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE;KACxC;IACD,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,EAAE;IAChE,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE;IACrD,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,EAAE;IACtD,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE;IAChD,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE;IACpD,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE;CACpD,CAAC;AAEF,MAAM,YAAY,GAAG,aAAa,CAAC;AAEnC,MAAM,KAAK,GAAiC,MAAM,CAAC,WAAW,CAC5D,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAC3C,CAAC;AAEF,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC;AAC5C,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC;AACxC,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,IAAI,KAAK,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"entry-types.js","sourceRoot":"","sources":["../../../src/react/components/entry-types.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,24 @@
1
1
  interface TagAutocompleteProps {
2
2
  /** Applies the chosen tag as the active entries filter (same effect as the old input). */
3
3
  onSelect: (tag: string) => void;
4
+ /**
5
+ * Fixed prefix the search is locked to (e.g. `user:` for the User filter).
6
+ * Both the `GET /tags` query and the suggestion ranking prepend it, and it's
7
+ * stripped from what the user types and from each suggestion's display so the
8
+ * control reads as ids, not raw tags. Defaults to `''` — the generic tag
9
+ * filter unchanged.
10
+ */
11
+ prefix?: string;
12
+ /** Placeholder for the input. Defaults to the generic tag prompt. */
13
+ placeholder?: string;
14
+ /** Accessible label for the input. Defaults to `Filter by tag`. */
15
+ ariaLabel?: string;
4
16
  }
5
17
  /**
6
18
  * Tag filter rendered as an accessible combobox: typing queries `GET /tags?prefix=`
7
19
  * and surfaces matching tags with their entry counts. Selecting one applies it as the
8
20
  * active `tag` filter and closes the list. Empty input shows no dropdown.
9
21
  */
10
- export declare function TagAutocomplete({ onSelect }: TagAutocompleteProps): JSX.Element;
22
+ export declare function TagAutocomplete({ onSelect, prefix, placeholder, ariaLabel, }: TagAutocompleteProps): JSX.Element;
11
23
  export {};
12
24
  //# sourceMappingURL=tag-autocomplete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tag-autocomplete.d.ts","sourceRoot":"","sources":["../../../src/react/components/tag-autocomplete.tsx"],"names":[],"mappings":"AAOA,UAAU,oBAAoB;IAC5B,0FAA0F;IAC1F,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAYD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CAiH/E"}
1
+ {"version":3,"file":"tag-autocomplete.d.ts","sourceRoot":"","sources":["../../../src/react/components/tag-autocomplete.tsx"],"names":[],"mappings":"AAOA,UAAU,oBAAoB;IAC5B,0FAA0F;IAC1F,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,MAAW,EACX,WAA8B,EAC9B,SAA2B,GAC5B,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CA4HpC"}
@@ -17,16 +17,24 @@ function rankSuggestions(tags, prefix) {
17
17
  * and surfaces matching tags with their entry counts. Selecting one applies it as the
18
18
  * active `tag` filter and closes the list. Empty input shows no dropdown.
19
19
  */
20
- export function TagAutocomplete({ onSelect }) {
20
+ export function TagAutocomplete({ onSelect, prefix = '', placeholder = 'Filter by tag…', ariaLabel = 'Filter by tag', }) {
21
21
  const [input, setInput] = useState('');
22
22
  const [open, setOpen] = useState(false);
23
23
  const [highlight, setHighlight] = useState(0);
24
24
  const containerRef = useRef(null);
25
25
  const listboxId = useId();
26
26
  const trimmed = input.trim();
27
- const { data } = useTags(trimmed);
28
- const suggestions = trimmed === '' ? [] : rankSuggestions(data ?? [], trimmed);
27
+ // The full tag the user is narrowing to — `user:` + `42` etc. The input shows
28
+ // only the stripped portion (the id), but the query and ranking work against
29
+ // the real, prefixed tag namespace so counts and matches stay correct.
30
+ const fullQuery = `${prefix}${trimmed}`;
31
+ const { data } = useTags(fullQuery);
32
+ const suggestions = trimmed === '' ? [] : rankSuggestions(data ?? [], fullQuery);
29
33
  const showList = open && suggestions.length > 0;
34
+ /** What we show in the row / input for a tag — the prefix stripped off. */
35
+ function displayOf(tag) {
36
+ return prefix !== '' && tag.startsWith(prefix) ? tag.slice(prefix.length) : tag;
37
+ }
30
38
  // Clamp the highlight whenever the suggestion set shrinks.
31
39
  useEffect(() => {
32
40
  setHighlight((current) => (current >= suggestions.length ? 0 : current));
@@ -41,9 +49,11 @@ export function TagAutocomplete({ onSelect }) {
41
49
  document.addEventListener('mousedown', onPointerDown);
42
50
  return () => document.removeEventListener('mousedown', onPointerDown);
43
51
  }, []);
52
+ // `tag` is always the full, prefixed tag the filter applies; the input mirrors
53
+ // the stripped display so a User filter never shows the `user:` plumbing.
44
54
  function choose(tag) {
45
55
  onSelect(tag);
46
- setInput(tag);
56
+ setInput(displayOf(tag));
47
57
  setOpen(false);
48
58
  }
49
59
  function onKeyDown(event) {
@@ -53,7 +63,7 @@ export function TagAutocomplete({ onSelect }) {
53
63
  }
54
64
  if (!showList) {
55
65
  if (event.key === 'Enter' && trimmed !== '')
56
- choose(trimmed);
66
+ choose(fullQuery);
57
67
  return;
58
68
  }
59
69
  if (event.key === 'ArrowDown') {
@@ -70,14 +80,14 @@ export function TagAutocomplete({ onSelect }) {
70
80
  if (picked)
71
81
  choose(picked.tag);
72
82
  else if (trimmed !== '')
73
- choose(trimmed);
83
+ choose(fullQuery);
74
84
  }
75
85
  }
76
86
  const activeId = showList ? `${listboxId}-option-${highlight}` : undefined;
77
87
  return (_jsxs("div", { ref: containerRef, className: "relative", children: [_jsx("input", { type: "text", value: input, onChange: (event) => {
78
88
  setInput(event.target.value);
79
89
  setOpen(true);
80
- }, onFocus: () => setOpen(true), onKeyDown: onKeyDown, placeholder: "Filter by tag\u2026", "aria-label": "Filter by tag", role: "combobox", "aria-expanded": showList, "aria-controls": listboxId, "aria-autocomplete": "list", ...(activeId ? { 'aria-activedescendant': activeId } : {}), className: "rounded border border-zinc-800 bg-zinc-950 px-2 py-1 text-xs text-zinc-200 placeholder:text-zinc-600 focus:border-emerald-500 focus:outline-none" }), showList ? (_jsx("div", { id: listboxId,
90
+ }, onFocus: () => setOpen(true), onKeyDown: onKeyDown, placeholder: placeholder, "aria-label": ariaLabel, role: "combobox", "aria-expanded": showList, "aria-controls": listboxId, "aria-autocomplete": "list", ...(activeId ? { 'aria-activedescendant': activeId } : {}), className: "rounded border border-zinc-800 bg-zinc-950 px-2 py-1 text-xs text-zinc-200 placeholder:text-zinc-600 focus:border-emerald-500 focus:outline-none" }), showList ? (_jsx("div", { id: listboxId,
81
91
  // biome-ignore lint/a11y/useSemanticElements: a <select> can't render styled tag+count option rows; ARIA combobox listbox pattern
82
92
  role: "listbox", "aria-label": "Tag suggestions", tabIndex: -1, className: "absolute left-0 top-full z-10 mt-1 max-h-64 w-48 overflow-auto rounded border border-zinc-800 bg-zinc-950 py-1 shadow-lg", children: suggestions.map((suggestion, index) => (_jsxs("div", { id: `${listboxId}-option-${index}`,
83
93
  // biome-ignore lint/a11y/useSemanticElements: <option> can't host the styled tag+count layout; ARIA combobox option pattern
@@ -85,6 +95,6 @@ export function TagAutocomplete({ onSelect }) {
85
95
  // mousedown (not click) so the input's blur doesn't close the list first
86
96
  event.preventDefault();
87
97
  choose(suggestion.tag);
88
- }, onMouseEnter: () => setHighlight(index), className: `flex cursor-pointer items-center justify-between gap-3 px-2 py-1 text-xs ${index === highlight ? 'bg-zinc-800 text-zinc-100' : 'text-zinc-300'}`, children: [_jsx("span", { className: "truncate", children: suggestion.tag }), _jsx("span", { className: "shrink-0 text-zinc-500", children: suggestion.count })] }, suggestion.tag))) })) : null] }));
98
+ }, onMouseEnter: () => setHighlight(index), className: `flex cursor-pointer items-center justify-between gap-3 px-2 py-1 text-xs ${index === highlight ? 'bg-zinc-800 text-zinc-100' : 'text-zinc-300'}`, children: [_jsx("span", { className: "truncate", children: displayOf(suggestion.tag) }), _jsx("span", { className: "shrink-0 text-zinc-500", children: suggestion.count })] }, suggestion.tag))) })) : null] }));
89
99
  }
90
100
  //# sourceMappingURL=tag-autocomplete.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tag-autocomplete.js","sourceRoot":"","sources":["../../../src/react/components/tag-autocomplete.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tag-autocomplete.js","sourceRoot":"","sources":["../../../src/react/components/tag-autocomplete.tsx"],"names":[],"mappings":"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"}
@@ -11,4 +11,19 @@ export declare function findUserTag(tags: readonly string[]): string | null;
11
11
  export declare function userTagId(userTag: string): string;
12
12
  /** Hash-router href to the all-types entries list filtered by a `user:<id>` tag. */
13
13
  export declare function buildUserActivityHref(userTag: string): string;
14
+ /** The fixed prefix the dedicated User filter narrows the tag search to. */
15
+ export declare const USER_TAG_FILTER_PREFIX = "user:";
16
+ /**
17
+ * True when `tag` is a populated `user:<id>` tag — i.e. the active tag filter is
18
+ * really a user pivot and should render in the User control, not the generic
19
+ * tag chip. A bare `user:` (no id) is NOT a user filter.
20
+ */
21
+ export declare function isUserTag(tag: string): boolean;
22
+ /**
23
+ * Prepends the `user:` prefix to a raw user id to form the underlying tag the
24
+ * entries query filters by. Idempotent: an already-prefixed value passes
25
+ * through unchanged, so the autocomplete (which surfaces full `user:<id>` tags)
26
+ * and a hand-typed bare id both resolve to the same tag.
27
+ */
28
+ export declare function toUserTag(idOrTag: string): string;
14
29
  //# sourceMappingURL=user-tag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-tag.d.ts","sourceRoot":"","sources":["../../../src/react/components/user-tag.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAKlE;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D"}
1
+ {"version":3,"file":"user-tag.d.ts","sourceRoot":"","sources":["../../../src/react/components/user-tag.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAKlE;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,UAAkB,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -22,4 +22,23 @@ export function userTagId(userTag) {
22
22
  export function buildUserActivityHref(userTag) {
23
23
  return `#/entries?tag=${encodeURIComponent(userTag)}`;
24
24
  }
25
+ /** The fixed prefix the dedicated User filter narrows the tag search to. */
26
+ export const USER_TAG_FILTER_PREFIX = USER_TAG_PREFIX;
27
+ /**
28
+ * True when `tag` is a populated `user:<id>` tag — i.e. the active tag filter is
29
+ * really a user pivot and should render in the User control, not the generic
30
+ * tag chip. A bare `user:` (no id) is NOT a user filter.
31
+ */
32
+ export function isUserTag(tag) {
33
+ return tag.startsWith(USER_TAG_PREFIX) && tag.length > USER_TAG_PREFIX.length;
34
+ }
35
+ /**
36
+ * Prepends the `user:` prefix to a raw user id to form the underlying tag the
37
+ * entries query filters by. Idempotent: an already-prefixed value passes
38
+ * through unchanged, so the autocomplete (which surfaces full `user:<id>` tags)
39
+ * and a hand-typed bare id both resolve to the same tag.
40
+ */
41
+ export function toUserTag(idOrTag) {
42
+ return idOrTag.startsWith(USER_TAG_PREFIX) ? idOrTag : `${USER_TAG_PREFIX}${idOrTag}`;
43
+ }
25
44
  //# sourceMappingURL=user-tag.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-tag.js","sourceRoot":"","sources":["../../../src/react/components/user-tag.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,IAAuB;IACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"user-tag.js","sourceRoot":"","sources":["../../../src/react/components/user-tag.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,IAAuB;IACjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AAEtD;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;AAChF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,GAAG,OAAO,EAAE,CAAC;AACxF,CAAC"}
@@ -1,7 +1,6 @@
1
1
  export * from './telescope-context.js';
2
2
  export * from './use-telescope-queries.js';
3
3
  export * from './components/entry-types.js';
4
- export * from './components/type-tabs.js';
5
4
  export * from './components/entries-table.js';
6
5
  export * from './components/user-tag.js';
7
6
  export * from './components/batch-timeline.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
@@ -1,7 +1,6 @@
1
1
  export * from './telescope-context.js';
2
2
  export * from './use-telescope-queries.js';
3
3
  export * from './components/entry-types.js';
4
- export * from './components/type-tabs.js';
5
4
  export * from './components/entries-table.js';
6
5
  export * from './components/user-tag.js';
7
6
  export * from './components/batch-timeline.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}