@ethlete/query-devtools 1.0.0-next.1 → 1.0.0-next.11

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 CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@ethlete/query-devtools",
3
- "version": "1.0.0-next.1",
3
+ "version": "1.0.0-next.11",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
7
  "@analogjs/vitest-angular": "2.6.3",
8
- "@angular/common": "22.0.7",
9
- "@angular/compiler": "22.0.7",
10
- "@angular/core": "22.0.7",
8
+ "@angular/common": "22.1.6",
9
+ "@angular/compiler": "22.1.6",
10
+ "@angular/core": "22.1.6",
11
11
  "@ethlete/components": "^1.0.0-next.42",
12
12
  "@ethlete/core": "^5.0.0-beta.11",
13
13
  "@ethlete/query": "^6.0.0-beta.8",
@@ -5,6 +5,9 @@ import * as _angular_core from '@angular/core';
5
5
  * first asked for, then downloads `<et-query-devtools>` as its own chunk and hands over. Use it instead
6
6
  * of `<et-query-devtools>` to keep the panel out of the bundle an application ships to its users.
7
7
  *
8
+ * Without `provideQueryDevtools()` it renders nothing at all - no toggle, no shortcut, and the panel
9
+ * chunk is never requested - so it can be left mounted in a production build.
10
+ *
8
11
  * Everything else is identical - the same toggle, the same `Ctrl/Cmd + Alt + Q` shortcut, and a panel
9
12
  * that was open when the tab last stored its state comes back open without a click.
10
13
  *
@@ -16,10 +19,15 @@ import * as _angular_core from '@angular/core';
16
19
  declare class QueryDevtoolsLazyComponent {
17
20
  private document;
18
21
  /**
19
- * Whether the panel was already open in this tab. It has to be answered before the panel exists, which
20
- * is why the stored view state is read here rather than asked of the panel.
22
+ * Whether `provideQueryDevtools()` is in the application. Everything else here is gated on it - the
23
+ * stored view state read, the shortcut listener and the template - so a build that ships the shell
24
+ * without the provider renders nothing and can never load the panel.
25
+ */
26
+ protected enabled: boolean;
27
+ /**
28
+ * Whether the panel is wanted. Whether it was already open has to be answered before the panel exists,
29
+ * which is why the stored view state is read here rather than asked of the panel.
21
30
  */
22
- private restoredOpen;
23
31
  protected load: _angular_core.WritableSignal<boolean>;
24
32
  /** A restored panel opens because it was open; one that was clicked open has to be told to. */
25
33
  protected openOnLoad: _angular_core.WritableSignal<boolean>;
@@ -12,6 +12,10 @@ declare const queryDevtoolsShortcutLabel: () => "⌘⌥Q" | "Ctrl+Alt+Q";
12
12
  * host application's global CSS (Tailwind resets, button styles, …) can never touch it and its own
13
13
  * styles can never leak out. Uses px (not rem) internally so it doesn't depend on the host's root
14
14
  * font-size; theme accent colour is read from an inherited custom property with a fallback.
15
+ *
16
+ * Mounted on its own - without `<et-query-devtools-lazy>` or `<et-query-devtools>` - it declares no
17
+ * devtools UI, so the floating API env and session pills take themselves off the page once the
18
+ * application settles. Call `setQueryDevtoolsUiMounted(true)` to keep them.
15
19
  */
16
20
  declare class QueryDevtoolsToggleComponent {
17
21
  tampered: _angular_core.InputSignal<boolean>;
@@ -1,7 +1,7 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { Signal, WritableSignal, OnInit } from '@angular/core';
3
3
  import * as _ethlete_query from '@ethlete/query';
4
- import { JsonPath, QueryDevtoolsOverridesRecorder, QueryRefreshCause, QueryRepositoryEntryDestroyedCause, Query, QueryRepositoryCacheEntry, HttpRequestRetryState, HttpRequestLoadingProgressState, QueryDevtoolsStats, QueryDevtoolsStatsHandle, QueryDevtoolsEntry, QueryRepository, QueryClient, QueryKeyLockState, QueryDevtoolsFeature, QueryDevtoolsFault, AnyQueryStack, AnyPagedQueryStack, QuerySequence, AnyBearerAuthProvider, WebSocketDevtoolsHandle, QueryDevtoolsFormHandle, QuerySequenceStatus, AnyQuerySnapshot, QueryDevtoolsRun, QueryDevtoolsRunError, WebSocketDevtoolsMessage, QueryDevtoolsStorageScope } from '@ethlete/query';
4
+ import { JsonPath, QueryDevtoolsOverridesRecorder, QueryRefreshCause, QueryRepositoryEntryDestroyedCause, Query, QueryRepositoryCacheEntry, HttpRequestRetryState, HttpRequestLoadingProgressState, QueryDevtoolsStats, QueryDevtoolsStatsHandle, QueryDevtoolsEntry, AnyQueryBatchItemResult, QueryRepository, QueryClient, QueryKeyLockState, QueryDevtoolsFeature, QueryDevtoolsFault, AnyQueryStack, AnyPagedQueryStack, QuerySequence, AnyQueryBatch, AnyBearerAuthProvider, WebSocketDevtoolsHandle, QueryDevtoolsFormHandle, QuerySequenceStatus, AnyQuerySnapshot, QueryDevtoolsRun, QueryDevtoolsRunError, WebSocketDevtoolsMessage, QueryDevtoolsStorageScope, QueryDevtoolsApiEnvSwitch } from '@ethlete/query';
5
5
  import { ResizeEdge, DragMoveEvent, ResizeMoveEvent } from '@ethlete/core';
6
6
 
7
7
  type AboutRow = {
@@ -19,6 +19,8 @@ type AboutGroup = {
19
19
  declare class QueryDevtoolsAboutComponent {
20
20
  protected readonly groups: AboutGroup[];
21
21
  protected copied: _angular_core.WritableSignal<boolean>;
22
+ private copiedReset$;
23
+ constructor();
22
24
  protected copy(): void;
23
25
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<QueryDevtoolsAboutComponent, never>;
24
26
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<QueryDevtoolsAboutComponent, "et-query-devtools-about", never, {}, {}, never, never, true, never>;
@@ -82,7 +84,10 @@ declare class QueryDevtoolsJsonComponent {
82
84
  private shapePath;
83
85
  protected annotation: _angular_core.Signal<string | null>;
84
86
  protected annotationTitle: _angular_core.Signal<string>;
85
- /** A `Date` or a `File` is object-typed but has nothing to expand into, so it renders as a leaf. */
87
+ /**
88
+ * A `Date` is object-typed but has nothing to expand into, so it renders as a leaf. A resolved
89
+ * header provider is the other way round: a function that does expand.
90
+ */
86
91
  protected isContainer: _angular_core.Signal<boolean>;
87
92
  /** The entries this node covers: the container's own, or just the window a chunk stands for. */
88
93
  ownEntries: _angular_core.Signal<JsonEntry[]>;
@@ -93,7 +98,7 @@ declare class QueryDevtoolsJsonComponent {
93
98
  private togglePath;
94
99
  private defaultExpanded;
95
100
  private localExpanded;
96
- protected expanded: _angular_core.Signal<boolean>;
101
+ private expanded;
97
102
  /** Only slices that actually contain a match unfold while searching, so a filter stays cheap. */
98
103
  private chunkHasHit;
99
104
  protected effectiveExpanded: _angular_core.Signal<boolean>;
@@ -202,7 +207,7 @@ type QueryDevtoolsSelection = {
202
207
  * to count, so the badge/overflow logic would push it behind **More** - it is reached from the header's
203
208
  * gear instead.
204
209
  */
205
- type DevtoolsTab = 'queries' | 'stacks' | 'sequences' | 'forms' | 'auth' | 'ws' | 'cache' | 'locks' | 'timeline' | 'events' | 'faults' | 'mocks' | 'about' | 'settings';
210
+ type DevtoolsTab = 'queries' | 'stacks' | 'sequences' | 'batches' | 'forms' | 'auth' | 'ws' | 'cache' | 'locks' | 'timeline' | 'events' | 'faults' | 'mocks' | 'about' | 'settings';
206
211
  /**
207
212
  * The sections of the query detail drawer. The head and its actions stay pinned above them - the detail
208
213
  * holds more than fits a column, and everything below the actions is reading material.
@@ -261,6 +266,20 @@ type QueryLink = {
261
266
  clientBaseUrl: string;
262
267
  stats?: QueryDevtoolsStatsHandle;
263
268
  };
269
+ /** One settled item of a query batch, with the route the args it was sent with resolve to. */
270
+ type BatchItemRow = {
271
+ result: AnyQueryBatchItemResult;
272
+ segments: RouteSegment[];
273
+ };
274
+ /**
275
+ * A batch's settled items as its card lists them. Capped, and `hidden` says by how much - a bulk run
276
+ * settles more items than a list can hold, and a truncated one must not read as the whole run.
277
+ */
278
+ type BatchItemView = {
279
+ rows: BatchItemRow[];
280
+ total: number;
281
+ hidden: number;
282
+ };
264
283
  /**
265
284
  * Query stats plus the numbers the panel derives from them rather than storing: an execution that never
266
285
  * reached the network was answered from the cache, and the averages come from the running totals.
@@ -391,6 +410,7 @@ type QueryDevtoolsHost = {
391
410
  queryEntries: Signal<QueryDevtoolsEntry[]>;
392
411
  stackEntries: Signal<QueryDevtoolsEntry[]>;
393
412
  sequenceEntries: Signal<QueryDevtoolsEntry[]>;
413
+ batchEntries: Signal<QueryDevtoolsEntry[]>;
394
414
  formEntries: Signal<QueryDevtoolsEntry[]>;
395
415
  authEntries: Signal<QueryDevtoolsEntry[]>;
396
416
  wsEntries: Signal<QueryDevtoolsEntry[]>;
@@ -450,6 +470,7 @@ type QueryDevtoolsHost = {
450
470
  asStack(entry: QueryDevtoolsEntry): AnyQueryStack;
451
471
  asPagedStack(entry: QueryDevtoolsEntry): AnyPagedQueryStack;
452
472
  asSequence(entry: QueryDevtoolsEntry): QuerySequence<unknown[]>;
473
+ asBatch(entry: QueryDevtoolsEntry): AnyQueryBatch;
453
474
  asAuth(entry: QueryDevtoolsEntry): AnyBearerAuthProvider;
454
475
  asWs(entry: QueryDevtoolsEntry): WebSocketDevtoolsHandle;
455
476
  asForm(entry: QueryDevtoolsEntry): QueryDevtoolsFormHandle;
@@ -475,6 +496,11 @@ type QueryDevtoolsHost = {
475
496
  requestUrl(query: AnyQuery): string | null;
476
497
  requestPath(url: string): string;
477
498
  queryArgs(query: AnyQuery): unknown;
499
+ /**
500
+ * The headers the query's last run sent, or - before it has run - the ones its args and its client
501
+ * resolve to now. `null` when there are none, or while a header provider cannot resolve yet.
502
+ */
503
+ requestHeaders(query: AnyQuery): Record<string, string> | null;
478
504
  routeSegments(entry: QueryDevtoolsEntry | undefined, query: AnyQuery): RouteSegment[];
479
505
  queryActivity(entry: QueryDevtoolsEntry): QueryActivity;
480
506
  linkActivity(link: QueryLink): QueryActivity;
@@ -492,6 +518,30 @@ type QueryDevtoolsHost = {
492
518
  /** Whether a sequence step's in/out detail (`<entryId>:<stepIndex>`) is expanded - persisted. */
493
519
  isStepExpanded(entryId: string, index: number): boolean;
494
520
  toggleStep(entryId: string, index: number): void;
521
+ /** A batch's route with its path params left as `:name` - a batch fills them in per item, not once. */
522
+ batchRouteSegments(entry: QueryDevtoolsEntry): RouteSegment[];
523
+ /**
524
+ * The batch entry that created a query, or `null` for a query no batch did. What lets the Queries list
525
+ * fold a bulk run's items under one row instead of listing whatever it has in flight.
526
+ */
527
+ batchOf(entry: QueryDevtoolsEntry): QueryDevtoolsEntry | null;
528
+ /**
529
+ * The item queries a batch has in flight. Only those: a batch destroys each item's query the moment
530
+ * that item settles, so a settled item is read from {@link batchItems} instead.
531
+ */
532
+ queriesForBatch(entry: QueryDevtoolsEntry): QueryLink[];
533
+ /** A batch's settled items, failures first and capped - see {@link BatchItemView}. */
534
+ batchItems(entry: QueryDevtoolsEntry): BatchItemView;
535
+ /**
536
+ * The registry entry of one of a batch's items, or `null` once it has fallen out of the batch's capped
537
+ * tombstone tail - which is what makes an item row openable only while its query is still kept.
538
+ */
539
+ batchItemQueryId(entry: QueryDevtoolsEntry, index: number): string | null;
540
+ /** An item's throughput line (`12.4 items/s · ~8s left`), or `null` before there is a rate to show. */
541
+ batchThroughput(batch: AnyQueryBatch): string | null;
542
+ /** Whether a batch item's args/response detail (`<entryId>:<itemIndex>`) is expanded - persisted. */
543
+ isBatchItemExpanded(entryId: string, index: number): boolean;
544
+ toggleBatchItem(entryId: string, index: number): void;
495
545
  /** Keys of the Queries-list groups of identical rows the user opened - persisted. */
496
546
  expandedQueryGroups: Signal<ReadonlySet<string>>;
497
547
  toggleQueryGroup(key: string): void;
@@ -632,6 +682,16 @@ type QueryDevtoolsHost = {
632
682
  entry: QueryDevtoolsEntry;
633
683
  query: AnyQuery;
634
684
  } | null>;
685
+ batchSelectedQueryId: WritableSignal<string | null>;
686
+ batchSelectedQuery: Signal<{
687
+ entry: QueryDevtoolsEntry;
688
+ query: AnyQuery;
689
+ } | null>;
690
+ eventSelectedQueryId: WritableSignal<string | null>;
691
+ eventSelectedQuery: Signal<{
692
+ entry: QueryDevtoolsEntry;
693
+ query: AnyQuery;
694
+ } | null>;
635
695
  formSelectedQueryId: WritableSignal<string | null>;
636
696
  formSelectedQuery: Signal<{
637
697
  entry: QueryDevtoolsEntry;
@@ -661,6 +721,12 @@ type QueryDevtoolsHost = {
661
721
  entry: QueryDevtoolsEntry;
662
722
  query: AnyQuery;
663
723
  } | null>;
724
+ /**
725
+ * The type annotations of each seeded mock body, by mock id. A mock only stores the *name* it was
726
+ * seeded from, and a body seeded from an inline schema has none, so this is the only thing that can
727
+ * label such a body - and it has to outlive the Mocks tab being switched away from.
728
+ */
729
+ seededTypes: WritableSignal<Record<string, ReadonlyMap<string, string>>>;
664
730
  paneAxis: Signal<PaneAxis>;
665
731
  listWidth: Signal<number | null>;
666
732
  drawerWidth: Signal<number | null>;
@@ -673,7 +739,7 @@ type QueryDevtoolsHost = {
673
739
  resetPaneSize(pane: PaneTarget): void;
674
740
  };
675
741
 
676
- type ScopeKey = 'viewState' | 'pins' | 'overrides' | 'mocks' | 'armedMocks' | 'armedFaults';
742
+ type ScopeKey = 'viewState' | 'pins' | 'overrides' | 'mocks' | 'armedMocks' | 'armedFaults' | 'authSessions';
677
743
  type ScopeRow = {
678
744
  key: ScopeKey;
679
745
  label: string;
@@ -702,6 +768,7 @@ type LimitRow = {
702
768
  * otherwise hold as constants, and the toggles their own tabs also carry.
703
769
  */
704
770
  declare class QueryDevtoolsSettingsComponent {
771
+ private document;
705
772
  protected host: QueryDevtoolsHost;
706
773
  protected readonly SCOPE_ROWS: ScopeRow[];
707
774
  protected readonly SCOPES: {
@@ -716,14 +783,36 @@ declare class QueryDevtoolsSettingsComponent {
716
783
  /** What queries actually retain, which is the application's value unless this panel raised it. */
717
784
  protected responseHistory: _angular_core.Signal<number>;
718
785
  protected mockCount: _angular_core.Signal<number>;
786
+ protected sessionCount: _angular_core.Signal<number>;
719
787
  protected armedMockCount: _angular_core.Signal<number>;
720
788
  protected armedFaultCount: _angular_core.Signal<number>;
789
+ /** The same keys the Events tab's own picker offers - see {@link queryDevtoolsEventClients}. */
790
+ protected eventClients: _angular_core.Signal<string[]>;
721
791
  protected resetConfirming: _angular_core.WritableSignal<boolean>;
792
+ protected readonly FORGET_SESSIONS: () => void;
793
+ /** The backends the application declared, or an empty list - the card renders only for a declared one. */
794
+ protected apiEnvs: _angular_core.Signal<QueryDevtoolsApiEnvSwitch[]>;
795
+ /** The env id (or typed URL) a switch's key holds, or `null` while the application picks for itself. */
796
+ protected apiEnvValue(apiSwitch: QueryDevtoolsApiEnvSwitch): string | null;
797
+ /** The env a switch falls back to with nothing stored, described for the default button. */
798
+ protected apiEnvFallback(apiSwitch: QueryDevtoolsApiEnvSwitch): {
799
+ label: string;
800
+ production: boolean;
801
+ };
802
+ /** Whether the pick in force - the stored env, or the fallback behind an unwritten key - is production. */
803
+ protected apiEnvIsProduction(apiSwitch: QueryDevtoolsApiEnvSwitch): boolean;
804
+ /** A stored value no declared env carries, which is a URL somebody typed in below. */
805
+ protected apiEnvCustomUrl(apiSwitch: QueryDevtoolsApiEnvSwitch): string;
806
+ /** Writes the application's own key and reloads - it is read before Angular boots, so nothing else can. */
807
+ protected pickApiEnv(apiSwitch: QueryDevtoolsApiEnvSwitch, value: string | null): void;
808
+ protected setCustomApiUrl(apiSwitch: QueryDevtoolsApiEnvSwitch, value: string): void;
722
809
  protected settings(): _ethlete_query.QueryDevtoolsSettings;
723
810
  protected scopeOf(key: ScopeKey): QueryDevtoolsStorageScope;
724
811
  protected limitOf(key: LimitKey): number;
725
812
  /** What the picked scope means beyond where the state is kept, or `null` while it means nothing extra. */
726
813
  protected warningFor(row: ScopeRow, scope: QueryDevtoolsStorageScope): string | null;
814
+ /** Why one scope is not on offer for a row, for the button's title, or `null` while it is. */
815
+ protected unavailableReason(row: ScopeRow, scope: QueryDevtoolsStorageScope): "Unavailable outside a development build: live access and refresh tokens, and the credentials you typed in, must not outlive this tab on a deployed origin. Session keeps the vault for as long as the tab." | null;
727
816
  protected setScope(key: ScopeKey, scope: QueryDevtoolsStorageScope): void;
728
817
  protected setLimit(key: LimitKey, value: string): void;
729
818
  protected setResponseHistory(value: string): void;
@@ -761,21 +850,6 @@ type FloatRect = {
761
850
  width: number;
762
851
  height: number;
763
852
  };
764
- /**
765
- * A drag in progress: the panel's docked edge, the floating panel being moved or resized, or the
766
- * divider between a two-pane tab's panes.
767
- */
768
- type ResizeDrag = {
769
- /** The document the pointer moves in - a popped-out panel lives in a window of its own. */
770
- doc: Document;
771
- } & ({
772
- kind: 'panel';
773
- } | {
774
- kind: 'pane';
775
- pane: PaneTarget;
776
- axis: PaneAxis;
777
- container: HTMLElement;
778
- });
779
853
  type PersistedState = {
780
854
  open?: boolean;
781
855
  height?: number;
@@ -785,12 +859,19 @@ type PersistedState = {
785
859
  listHeight?: number | null;
786
860
  drawerHeight?: number | null;
787
861
  dock?: DevtoolsDock;
862
+ reservesSpace?: boolean;
788
863
  floatRect?: FloatRect;
789
864
  floatParked?: boolean;
790
865
  activeTab?: DevtoolsTab;
791
866
  detailTab?: DetailTab;
792
867
  selectedClientName?: string | null;
793
868
  selectedQueryId?: string | null;
869
+ stackSelectedQueryId?: string | null;
870
+ sequenceSelectedQueryId?: string | null;
871
+ batchSelectedQueryId?: string | null;
872
+ eventSelectedQueryId?: string | null;
873
+ formSelectedQueryId?: string | null;
874
+ timelineSelectedQueryId?: string | null;
794
875
  selectedFormId?: string | null;
795
876
  inspectFilterIds?: string[] | null;
796
877
  queryFilter?: string;
@@ -803,6 +884,7 @@ type PersistedState = {
803
884
  socketFilter?: string;
804
885
  jsonSearch?: string;
805
886
  expandedSteps?: string[];
887
+ expandedBatchItems?: string[];
806
888
  expandedQueryGroups?: string[];
807
889
  jsonExpanded?: string[];
808
890
  jsonCollapsed?: string[];
@@ -875,6 +957,9 @@ declare class QueryDevtoolsComponent implements OnInit {
875
957
  } | {
876
958
  id: "sequences";
877
959
  label: string;
960
+ } | {
961
+ id: "batches";
962
+ label: string;
878
963
  } | {
879
964
  id: "forms";
880
965
  label: string;
@@ -956,7 +1041,7 @@ declare class QueryDevtoolsComponent implements OnInit {
956
1041
  protected drawerWidth: WritableSignal<number | null>;
957
1042
  protected listHeight: WritableSignal<number | null>;
958
1043
  protected drawerHeight: WritableSignal<number | null>;
959
- protected drag: WritableSignal<ResizeDrag | null>;
1044
+ private drag;
960
1045
  protected resizing: _angular_core.Signal<boolean>;
961
1046
  /** Which edge the panel is docked to, or `float` for a window of its own inside the page. */
962
1047
  protected dock: WritableSignal<DevtoolsDock>;
@@ -992,6 +1077,11 @@ declare class QueryDevtoolsComponent implements OnInit {
992
1077
  readonly label: "Pop out";
993
1078
  readonly hint: "Move the panel into a window of its own - the same live panel, on your other screen";
994
1079
  }>;
1080
+ /**
1081
+ * Whether a docked panel takes its size out of the page instead of covering it - so the last rows of a
1082
+ * long page can still be scrolled to. Only docks can: a float sits wherever it was dragged.
1083
+ */
1084
+ protected reservesSpace: WritableSignal<boolean>;
995
1085
  /** Where the floating panel sits and how big it is. Kept while docked, so a return to float restores it. */
996
1086
  private floatRect;
997
1087
  /** The rect a resize gesture started from, or `null` outside one. */
@@ -1029,14 +1119,36 @@ declare class QueryDevtoolsComponent implements OnInit {
1029
1119
  /** The floating panel's offset from the viewport's top-left, or `null` while it is docked. */
1030
1120
  protected panelInsetBlock: _angular_core.Signal<number | null>;
1031
1121
  protected panelInsetInline: _angular_core.Signal<number | null>;
1122
+ /**
1123
+ * The panel's rendered size, not its dragged one - the stylesheet clamps a dock (`min-block-size`,
1124
+ * `max-block-size: 90vh`) and it is the clamped size the page has to give up.
1125
+ */
1126
+ private panelSize;
1127
+ /** Which padding a docked panel asks of the page and how much, or `null` when it asks for none. */
1128
+ private pageReservation;
1129
+ /**
1130
+ * The viewport edge a docked panel covers, reserved for overlays whatever {@link reservesSpace} says:
1131
+ * page content can be scrolled out from under the panel, a dialog or a menu cannot. A dock edge is
1132
+ * logical, so which physical edge a side dock covers flips in RTL - read from the panel, since the
1133
+ * writing direction cannot change under a dock switch.
1134
+ */
1135
+ private overlayReservation;
1032
1136
  /** Which section of the query detail is showing. Shared by the Queries tab and both drawers. */
1033
1137
  detailTab: WritableSignal<DetailTab>;
1034
1138
  selectedClientName: WritableSignal<string | null>;
1035
1139
  selectedQueryId: WritableSignal<string | null>;
1036
1140
  /** The form whose detail the Forms tab has expanded. */
1037
1141
  selectedFormId: WritableSignal<string | null>;
1142
+ /**
1143
+ * The type annotations of each seeded mock body, by mock id. It lives here rather than on the Mocks
1144
+ * tab because a tab is destroyed the moment another one is selected, and a body seeded from an inline
1145
+ * schema has no `schemaName` to recover its labels from.
1146
+ */
1147
+ seededTypes: WritableSignal<Record<string, ReadonlyMap<string, string>>>;
1038
1148
  stackSelectedQueryId: WritableSignal<string | null>;
1039
1149
  sequenceSelectedQueryId: WritableSignal<string | null>;
1150
+ batchSelectedQueryId: WritableSignal<string | null>;
1151
+ eventSelectedQueryId: WritableSignal<string | null>;
1040
1152
  formSelectedQueryId: WritableSignal<string | null>;
1041
1153
  timelineSelectedQueryId: WritableSignal<string | null>;
1042
1154
  /** Free-text narrowing of the Queries list. Every whitespace-separated term has to match. */
@@ -1082,6 +1194,8 @@ declare class QueryDevtoolsComponent implements OnInit {
1082
1194
  private socketEmitError;
1083
1195
  /** Keys (`<entryId>:<stepIndex>`) of the sequence steps whose in/out detail is expanded. */
1084
1196
  private expandedSteps;
1197
+ /** Keys (`<entryId>:<itemIndex>`) of the batch items whose args/response detail is expanded. */
1198
+ private expandedBatchItems;
1085
1199
  /** Keys of the Queries-list groups the user opened - the tab is rebuilt on every switch back. */
1086
1200
  expandedQueryGroups: WritableSignal<ReadonlySet<string>>;
1087
1201
  /** Shared value-explorer search term. */
@@ -1122,7 +1236,12 @@ declare class QueryDevtoolsComponent implements OnInit {
1122
1236
  copiedGql: WritableSignal<boolean>;
1123
1237
  copiedRoute: WritableSignal<boolean>;
1124
1238
  private copiedReset$;
1125
- /** 1-second tick driving the cache freshness countdowns. */
1239
+ /**
1240
+ * 1-second tick driving the cache freshness countdowns. Gated the way the locks poll is: an ungated
1241
+ * `interval` is a periodic macrotask zone.js counts forever, so a mounted panel would tick the host
1242
+ * application once a second and keep `ApplicationRef.whenStable()` from ever resolving. Every reader
1243
+ * sits inside `@if (open())`, so there is nothing to drive while the panel is shut or the tab hidden.
1244
+ */
1126
1245
  private clock;
1127
1246
  /**
1128
1247
  * The probe lock behind every Locks row's "this tab" answer, and the last snapshot read through it.
@@ -1135,7 +1254,8 @@ declare class QueryDevtoolsComponent implements OnInit {
1135
1254
  lockRows: _angular_core.Signal<DevtoolsLockRow[] | null>;
1136
1255
  /** "Inspect" mode: hover the live UI to find the query that a component created. */
1137
1256
  protected inspectActive: WritableSignal<boolean>;
1138
- protected inspectHover: WritableSignal<{
1257
+ /** @internal */
1258
+ inspectHover: WritableSignal<{
1139
1259
  rect: DOMRect;
1140
1260
  entries: QueryDevtoolsEntry[];
1141
1261
  } | null>;
@@ -1155,12 +1275,17 @@ declare class QueryDevtoolsComponent implements OnInit {
1155
1275
  protected panelTampered: _angular_core.Signal<boolean>;
1156
1276
  stackEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1157
1277
  sequenceEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1278
+ batchEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1158
1279
  formEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1159
1280
  authEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1160
1281
  wsEntries: _angular_core.Signal<QueryDevtoolsEntry[]>;
1161
1282
  /** Unique client names present across queries and auth providers, for the Queries-tab picker. */
1162
1283
  clientNames: _angular_core.Signal<string[]>;
1163
- /** Unique repositories (with their client name + base URL) used by the Cache and Events tabs. */
1284
+ /**
1285
+ * Unique repositories (with their client name + base URL) used by the Cache and Events tabs. A
1286
+ * tombstone keeps its `meta.repository`, so a destroyed client would otherwise keep its Cache card
1287
+ * and its **Evict all** long after its injector died.
1288
+ */
1164
1289
  private repositories;
1165
1290
  /**
1166
1291
  * Every client the Faults tab can arm, with the fault it currently carries. Clients with nothing armed
@@ -1212,6 +1337,9 @@ declare class QueryDevtoolsComponent implements OnInit {
1212
1337
  } | {
1213
1338
  id: "sequences";
1214
1339
  label: string;
1340
+ } | {
1341
+ id: "batches";
1342
+ label: string;
1215
1343
  } | {
1216
1344
  id: "forms";
1217
1345
  label: string;
@@ -1253,6 +1381,9 @@ declare class QueryDevtoolsComponent implements OnInit {
1253
1381
  } | {
1254
1382
  id: "sequences";
1255
1383
  label: string;
1384
+ } | {
1385
+ id: "batches";
1386
+ label: string;
1256
1387
  } | {
1257
1388
  id: "forms";
1258
1389
  label: string;
@@ -1296,6 +1427,14 @@ declare class QueryDevtoolsComponent implements OnInit {
1296
1427
  entry: QueryDevtoolsEntry;
1297
1428
  query: AnyQuery;
1298
1429
  } | null>;
1430
+ batchSelectedQuery: _angular_core.Signal<{
1431
+ entry: QueryDevtoolsEntry;
1432
+ query: AnyQuery;
1433
+ } | null>;
1434
+ eventSelectedQuery: _angular_core.Signal<{
1435
+ entry: QueryDevtoolsEntry;
1436
+ query: AnyQuery;
1437
+ } | null>;
1299
1438
  formSelectedQuery: _angular_core.Signal<{
1300
1439
  entry: QueryDevtoolsEntry;
1301
1440
  query: AnyQuery;
@@ -1422,7 +1561,20 @@ declare class QueryDevtoolsComponent implements OnInit {
1422
1561
  * query) never writes them to its own `args` signal - only the `withArgs` feature does - so the args
1423
1562
  * its current request was built from stand in.
1424
1563
  */
1425
- queryArgs(query: AnyQuery): Omit<any, "response"> | null;
1564
+ queryArgs(query: AnyQuery): Omit<any, "response" | "rawResponse"> | null;
1565
+ /**
1566
+ * The headers a query's request carries, as a plain `name: value` record, or `null` for a query that
1567
+ * has none the panel can read. The set the last run sent, so it stays readable after the token it
1568
+ * used was replaced; for a query that has not run, what its current args and its client resolve to
1569
+ * now. `null` while a header provider throws - a secure query's needs an access token.
1570
+ *
1571
+ * The args tree cannot answer this on its own: a `withArgs` query reads its args from the feature's
1572
+ * source, which the secure `Authorization` provider is never written back to, and client-level
1573
+ * headers are merged in per execution rather than being part of the args at all.
1574
+ */
1575
+ requestHeaders(query: AnyQuery): {
1576
+ [k: string]: string;
1577
+ } | null;
1426
1578
  queryStatus(query: AnyQuery): QueryStatus;
1427
1579
  /**
1428
1580
  * A request in flight is already refreshing, so reporting it as stale on top of `loading` is noise -
@@ -1460,7 +1612,7 @@ declare class QueryDevtoolsComponent implements OnInit {
1460
1612
  * What a run's status dot and timeline bar colour by. `pending` reuses the panel's loading colour;
1461
1613
  * `aborted` matches no rule and so falls back to the neutral one.
1462
1614
  */
1463
- runStatus(run: QueryDevtoolsRun): "error" | "loading" | "success" | "aborted";
1615
+ runStatus(run: QueryDevtoolsRun): "loading" | "success" | "error" | "aborted";
1464
1616
  /**
1465
1617
  * Whether a run can be an end of the diff: it still holds its body, and so does some other run of the
1466
1618
  * same query. Deliberately not "an *older* run" - a free pair means the oldest body held is pickable
@@ -1553,8 +1705,8 @@ declare class QueryDevtoolsComponent implements OnInit {
1553
1705
  * holds, the event log, the cache totals and anything armed in the Faults tab. Unlike **Copy report**
1554
1706
  * this is not scoped to one query - it is the attachment for a bug report about a screen.
1555
1707
  *
1556
- * Deliberately unfiltered: a report is read by someone who was not there, and a dump that silently
1557
- * left out the client you were not looking at is worse than no dump.
1708
+ * Deliberately unfiltered apart from credentials: a report is read by someone who was not there, and a
1709
+ * dump that silently left out the client you were not looking at is worse than no dump.
1558
1710
  */
1559
1711
  protected downloadSession(): void;
1560
1712
  openResponseEditor(query: AnyQuery): void;
@@ -1598,6 +1750,7 @@ declare class QueryDevtoolsComponent implements OnInit {
1598
1750
  asStack(entry: QueryDevtoolsEntry): AnyQueryStack;
1599
1751
  asPagedStack(entry: QueryDevtoolsEntry): AnyPagedQueryStack;
1600
1752
  asSequence(entry: QueryDevtoolsEntry): QuerySequence<unknown[]>;
1753
+ asBatch(entry: QueryDevtoolsEntry): AnyQueryBatch;
1601
1754
  asAuth(entry: QueryDevtoolsEntry): AnyBearerAuthProvider;
1602
1755
  asWs(entry: QueryDevtoolsEntry): WebSocketDevtoolsHandle;
1603
1756
  /**
@@ -1662,6 +1815,19 @@ declare class QueryDevtoolsComponent implements OnInit {
1662
1815
  expandQueryGroup(key: string): void;
1663
1816
  isStepExpanded(entryId: string, index: number): boolean;
1664
1817
  toggleStep(entryId: string, index: number): void;
1818
+ /** A batch's route with its path params left as `:name` - a batch fills them in per item, not once. */
1819
+ batchRouteSegments(entry: QueryDevtoolsEntry): RouteSegment[];
1820
+ batchOf(entry: QueryDevtoolsEntry): QueryDevtoolsEntry | null;
1821
+ queriesForBatch(entry: QueryDevtoolsEntry): QueryLink[];
1822
+ /**
1823
+ * The registry entry of one of a batch's items, or `null` once it has fallen out of the batch's capped
1824
+ * tombstone tail - which is what makes an item row openable only while its query is still kept.
1825
+ */
1826
+ batchItemQueryId(entry: QueryDevtoolsEntry, index: number): string | null;
1827
+ batchItems(entry: QueryDevtoolsEntry): BatchItemView;
1828
+ batchThroughput(batch: AnyQueryBatch): string | null;
1829
+ isBatchItemExpanded(entryId: string, index: number): boolean;
1830
+ toggleBatchItem(entryId: string, index: number): void;
1665
1831
  /** Dedents a GraphQL document (template-literal indentation) for readable display. */
1666
1832
  gqlDocument(doc: string): string;
1667
1833
  featureLabel(type: string): string;
@@ -1687,6 +1853,18 @@ declare class QueryDevtoolsComponent implements OnInit {
1687
1853
  content: string;
1688
1854
  type: string;
1689
1855
  }): void;
1856
+ /**
1857
+ * The headers an execution of this request would resolve to now: the client's with the per-request
1858
+ * ones merged on top, providers called. `undefined` when a provider throws, which for a secure query
1859
+ * means no access token is available yet.
1860
+ */
1861
+ private resolvedHeaders;
1862
+ /**
1863
+ * The same route rendered from a set of args rather than from a query, which is what a batch item leaves
1864
+ * behind: the batch destroys its query the moment the item settles.
1865
+ */
1866
+ private argsRouteSegments;
1867
+ private renderRoute;
1690
1868
  /**
1691
1869
  * Takes - or gives back - the lock whose name only this tab can have produced. Its `clientId` in the
1692
1870
  * snapshot is what tells this tab's rows from another tab's: `LockInfo` carries no tab identity, and
@@ -1774,11 +1952,18 @@ declare class QueryDevtoolsComponent implements OnInit {
1774
1952
  */
1775
1953
  private insomniaHeaders;
1776
1954
  private sessionClients;
1955
+ /**
1956
+ * A bearer auth provider's login and token-refresh queries are ordinary registered queries, so the
1957
+ * export has to be told which ones they are before it can leave their bodies out. The provider's own
1958
+ * entry lists them by client, method and route, which is what a query entry is matched on.
1959
+ */
1960
+ private sessionAuthQueryKeys;
1777
1961
  /** Every registered entry, described by whatever its kind carries. */
1778
1962
  private sessionEntries;
1779
1963
  private sessionQuery;
1780
1964
  private sessionActivity;
1781
1965
  private sessionSequence;
1966
+ private sessionBatch;
1782
1967
  private sessionForm;
1783
1968
  /**
1784
1969
  * An auth provider without its tokens. A session report is a file that gets attached to a ticket, and
@@ -1830,7 +2015,7 @@ declare class QueryDevtoolsComponent implements OnInit {
1830
2015
  declare const QUERY_DEVTOOLS_IMPORTS: readonly [typeof QueryDevtoolsComponent];
1831
2016
 
1832
2017
  /** The version of `@ethlete/query-devtools` this build was cut from. */
1833
- declare const QUERY_DEVTOOLS_VERSION = "1.0.0-next.1";
2018
+ declare const QUERY_DEVTOOLS_VERSION = "1.0.0-next.11";
1834
2019
 
1835
2020
  export { QUERY_DEVTOOLS_IMPORTS, QUERY_DEVTOOLS_VERSION, QueryDevtoolsAboutComponent, QueryDevtoolsComponent, QueryDevtoolsJsonComponent, QueryDevtoolsJsonStylesComponent, QueryDevtoolsSettingsComponent, QueryDevtoolsTimelineStylesComponent, clampFloatToPeek, kindOf, resizedFloatRect, settledFloatRect };
1836
2021
  export type { JsonKind };