http-request-manager 18.12.4 → 18.12.9

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 { inject, Injectable, APP_ID, Inject, InjectionToken, isDevMode, signal, effect, computed, Injector, Optional, EventEmitter, Input, Output, ViewEncapsulation, Component, NgModule, ViewChild } from '@angular/core';
3
3
  import { ComponentStore } from '@ngrx/component-store';
4
- import { map, catchError, filter, tap, finalize, takeWhile, retry, startWith, mergeMap, takeUntil, concatMap, toArray, withLatestFrom, switchMap, delay, take, scan, distinctUntilChanged } from 'rxjs/operators';
4
+ import { map, catchError, filter, finalize, tap, scan, takeWhile, retry, startWith, mergeMap, takeUntil, concatMap, toArray, withLatestFrom, switchMap, take, distinctUntilChanged } from 'rxjs/operators';
5
5
  import { HttpClient, HttpHeaders, HttpEventType, HttpHeaderResponse, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
6
6
  import * as CryptoJS from 'crypto-js';
7
7
  import { from, BehaviorSubject, EMPTY, throwError, defer, interval, timer, Subject, of, Observable, merge, Subscription, take as take$1, catchError as catchError$1, map as map$1, tap as tap$1, switchMap as switchMap$1, startWith as startWith$1, distinctUntilChanged as distinctUntilChanged$1, combineLatest, filter as filter$1, takeUntil as takeUntil$1, ReplaySubject } from 'rxjs';
@@ -884,6 +884,7 @@ class StreamingProcessor {
884
884
  this.contentType = '';
885
885
  this.maxBufferSize = 10 * 1024 * 1024; // 10MB limit
886
886
  this.lastParsedLength = 0; // Track parsed position to avoid duplicates
887
+ this.lastParsedLineEnd = 0; // Track end of last-parsed complete line for NDJSON incremental parsing
887
888
  this.streamConfig = config || { streamType: StreamType.AI_STREAMING };
888
889
  }
889
890
  /**
@@ -906,18 +907,26 @@ class StreamingProcessor {
906
907
  return null;
907
908
  case HttpEventType.DownloadProgress:
908
909
  if (event.partialText) {
909
- this.appendToBuffer(event.partialText);
910
+ // partialText is cumulative, so replace the buffer instead of appending
911
+ this.buffer = event.partialText;
910
912
  const parsedData = this.parseBuffer();
911
- // Only return NEW items since last parse (progressive updates)
912
- const newItems = parsedData.slice(this.lastParsedLength);
913
- // received = cumulative total for display, newItems.length = new this chunk
914
- const received = newItems.length; // Changed from lastParsedLength
915
- this.lastParsedLength = parsedData.length;
913
+ // For NDJSON incremental parsing, parsedData already contains only new items.
914
+ // For other formats, parsedData is cumulative so slice from lastParsedLength.
915
+ const isIncremental = this.streamConfig.streamType === StreamType.NDJSON;
916
+ const newItems = isIncremental ? parsedData : parsedData.slice(this.lastParsedLength);
917
+ // received = cumulative total for progress display
918
+ const received = isIncremental
919
+ ? this.lastParsedLength + parsedData.length
920
+ : parsedData.length;
921
+ this.lastParsedLength = received;
922
+ // Return null when no new items — prevents empty array emissions
923
+ if (newItems.length === 0) {
924
+ return null;
925
+ }
916
926
  const total = this.totalFromHeader;
917
927
  const percent = total
918
928
  ? Math.min(100, Math.round((received / total) * 100))
919
929
  : 0;
920
- // console.log('[STREAM] progress:', percent, 'received:', received, 'total:', total, 'bufferLen:', this.buffer.length, 'parsedCount:', parsedData.length);
921
930
  const progress = {
922
931
  received,
923
932
  total,
@@ -925,19 +934,24 @@ class StreamingProcessor {
925
934
  stage: 'streaming'
926
935
  };
927
936
  return {
928
- data: newItems.length > 0 ? newItems : [],
937
+ data: newItems,
929
938
  progress
930
939
  };
931
940
  }
932
941
  return null;
933
942
  case HttpEventType.Response:
934
943
  if (event.body) {
935
- this.appendToBuffer(event.body);
944
+ // event.body is the complete response, replace the buffer
945
+ this.buffer = event.body;
936
946
  const parsedData = this.parseBuffer();
937
- // Only return items not already returned via progress events
938
- const remaining = parsedData.slice(this.lastParsedLength);
939
- this.lastParsedLength = parsedData.length;
940
- const received = parsedData.length;
947
+ // For NDJSON incremental parsing, parsedData already contains only new items.
948
+ // For other formats, parsedData is cumulative so slice from lastParsedLength.
949
+ const isIncremental = this.streamConfig.streamType === StreamType.NDJSON;
950
+ const remaining = isIncremental ? parsedData : parsedData.slice(this.lastParsedLength);
951
+ const received = isIncremental
952
+ ? this.lastParsedLength + parsedData.length
953
+ : parsedData.length;
954
+ this.lastParsedLength = received;
941
955
  const total = this.totalFromHeader;
942
956
  const percent = total
943
957
  ? Math.min(100, Math.round((received / total) * 100))
@@ -966,23 +980,40 @@ class StreamingProcessor {
966
980
  // Implement sliding window if buffer gets too large
967
981
  if (this.buffer.length > this.maxBufferSize) {
968
982
  this.buffer = this.buffer.slice(-this.maxBufferSize / 2);
983
+ this.lastParsedLineEnd = 0;
984
+ this.lastParsedLength = 0;
969
985
  }
970
986
  }
971
987
  /**
972
- * Parse current buffer content
988
+ * Parse current buffer content.
989
+ *
990
+ * Per-record parsing failures are already handled by the inner parsers
991
+ * (`safeJsonParse`, `parseNdjson`, `parseEventStream`, `extractJsonObjects`),
992
+ * which skip malformed records and return what was successfully parsed.
993
+ * No outer try/catch — wrapping these calls in `catch { return []; }`
994
+ * would discard every successfully-parsed record in the buffer whenever a
995
+ * single unexpected error bubbles up, instead of omitting the bad record.
973
996
  */
974
997
  parseBuffer() {
975
998
  if (!this.buffer.trim()) {
976
999
  return [];
977
1000
  }
978
- try {
979
- const result = parseStreamData(this.buffer, this.contentType, this.streamConfig);
1001
+ if (this.streamConfig.streamType === StreamType.NDJSON) {
1002
+ // For NDJSON, only parse complete lines since the last parse.
1003
+ // Find the last newline in the buffer — everything after it is an incomplete line.
1004
+ const lastNewlineIndex = this.buffer.lastIndexOf('\n');
1005
+ if (lastNewlineIndex === -1) {
1006
+ // No complete lines yet
1007
+ return [];
1008
+ }
1009
+ // Parse only the content from lastParsedLineEnd up to (and including) the last newline
1010
+ const bufferToParse = this.buffer.substring(this.lastParsedLineEnd, lastNewlineIndex + 1);
1011
+ this.lastParsedLineEnd = lastNewlineIndex + 1;
1012
+ const result = parseStreamData(bufferToParse, this.contentType, this.streamConfig);
980
1013
  return result;
981
1014
  }
982
- catch (error) {
983
- console.warn('Failed to parse streaming data:', error);
984
- return [];
985
- }
1015
+ const result = parseStreamData(this.buffer, this.contentType, this.streamConfig);
1016
+ return result;
986
1017
  }
987
1018
  /**
988
1019
  * Reset processor state
@@ -991,6 +1022,7 @@ class StreamingProcessor {
991
1022
  this.buffer = '';
992
1023
  this.contentType = '';
993
1024
  this.lastParsedLength = 0;
1025
+ this.lastParsedLineEnd = 0;
994
1026
  this.totalFromHeader = undefined;
995
1027
  }
996
1028
  /**
@@ -2891,7 +2923,9 @@ class RequestService extends WebsocketService {
2891
2923
  observe: 'events',
2892
2924
  responseType: 'text',
2893
2925
  reportProgress: true
2894
- }).pipe(tap(data => console.log('STREAM DATA', data)), requestStreaming({
2926
+ }).pipe(
2927
+ // tap(data => console.log('STREAM DATA', data)),
2928
+ requestStreaming({
2895
2929
  streamType: options.streamType || StreamType.AI_STREAMING,
2896
2930
  totalHeader: options.totalHeader
2897
2931
  }), this.requestStreaming(options), finalize(() => {
@@ -2981,19 +3015,19 @@ class RequestService extends WebsocketService {
2981
3015
  requestStreaming(options) {
2982
3016
  return (source$) => {
2983
3017
  return source$.pipe(tap(output => {
2984
- // Update progress from stream output
2985
3018
  this.progress.next(output.progress.percent);
2986
3019
  this.streamProgress.next(output.progress);
2987
- }), map(output => {
2988
- const data = output.data;
2989
- if (!data || (Array.isArray(data) && data.length === 0)) {
2990
- return data;
2991
- }
3020
+ }), scan((acc, output) => {
3021
+ // Accumulate data from each emission
3022
+ const newData = output.data;
2992
3023
  if (options?.adapter) {
2993
- return data.map((item) => options.adapter(item));
3024
+ const adaptedData = newData.map((item) => options.adapter(item));
3025
+ return [...acc, ...adaptedData];
2994
3026
  }
2995
- return data;
2996
- }));
3027
+ else {
3028
+ return [...acc, ...newData];
3029
+ }
3030
+ }, []));
2997
3031
  };
2998
3032
  }
2999
3033
  downloadFileRequest(options) {
@@ -4170,7 +4204,7 @@ class HTTPManagerService extends RequestService {
4170
4204
  }
4171
4205
  handleSequentialError(request, error, index, options) {
4172
4206
  if (options.logErrors !== false) {
4173
- console.error(`Batch request ${index} failed:`, error);
4207
+ // console.error(`Batch request ${index} failed:`, error);
4174
4208
  }
4175
4209
  if (options.stopOnError) {
4176
4210
  return throwError(() => error);
@@ -4182,7 +4216,7 @@ class HTTPManagerService extends RequestService {
4182
4216
  }
4183
4217
  handleParallelError(request, error, index, options) {
4184
4218
  if (options.logErrors !== false) {
4185
- console.error(`Batch request ${index} failed:`, error);
4219
+ // console.error(`Batch request ${index} failed:`, error);
4186
4220
  }
4187
4221
  if (options.ignoreErrors) {
4188
4222
  return of(undefined);
@@ -4277,17 +4311,17 @@ class RequestSignalsService extends WebsocketService {
4277
4311
  * - Streams are protected - non-stream requests wait for active streams
4278
4312
  */
4279
4313
  queueRequest(request$, method, isStream = false) {
4280
- console.log(`[Queue] ${method} queued (isStream=${isStream})`, {
4281
- activeMethod: this.activeMethod,
4282
- activeStreamMethod: this.activeStreamMethod,
4283
- queueLength: this.requestQueue.length
4284
- });
4314
+ // console.log(`[Queue] ${method} queued (isStream=${isStream})`, {
4315
+ // activeMethod: this.activeMethod,
4316
+ // activeStreamMethod: this.activeStreamMethod,
4317
+ // queueLength: this.requestQueue.length
4318
+ // });
4285
4319
  return new Observable((observer) => {
4286
- console.log(`[Queue] ${method} observer created, checking conditions...`, {
4287
- activeMethod: this.activeMethod,
4288
- activeStreamMethod: this.activeStreamMethod,
4289
- isStream
4290
- });
4320
+ // console.log(`[Queue] ${method} observer created, checking conditions...`, {
4321
+ // activeMethod: this.activeMethod,
4322
+ // activeStreamMethod: this.activeStreamMethod,
4323
+ // isStream
4324
+ // });
4291
4325
  const queuedRequest = {
4292
4326
  observable: request$,
4293
4327
  resolve: (value) => observer.next(value),
@@ -4297,7 +4331,7 @@ class RequestSignalsService extends WebsocketService {
4297
4331
  };
4298
4332
  // If a stream is currently active, non-stream requests must wait
4299
4333
  if (this.activeStreamMethod && !isStream) {
4300
- console.log(`[Queue] ${method} queued (1), waiting for stream ${this.activeStreamMethod}`);
4334
+ // console.log(`[Queue] ${method} queued (1), waiting for stream ${this.activeStreamMethod}`);
4301
4335
  this.requestQueue.push(queuedRequest);
4302
4336
  return () => {
4303
4337
  const idx = this.requestQueue.findIndex(q => q === queuedRequest);
@@ -4307,7 +4341,7 @@ class RequestSignalsService extends WebsocketService {
4307
4341
  }
4308
4342
  // If a request is already running, queue this one (FIFO)
4309
4343
  if (this.activeMethod) {
4310
- console.log(`[Queue] ${method} queued (2), waiting for ${this.activeMethod}`);
4344
+ // console.log(`[Queue] ${method} queued (2), waiting for ${this.activeMethod}`);
4311
4345
  this.requestQueue.push(queuedRequest);
4312
4346
  return () => {
4313
4347
  const idx = this.requestQueue.findIndex(q => q === queuedRequest);
@@ -4316,7 +4350,7 @@ class RequestSignalsService extends WebsocketService {
4316
4350
  };
4317
4351
  }
4318
4352
  // No active request - start immediately
4319
- console.log(`[Queue] ${method} starting immediately`);
4353
+ // console.log(`[Queue] ${method} starting immediately`);
4320
4354
  this.startRequest(queuedRequest, observer);
4321
4355
  return () => {
4322
4356
  const idx = this.requestQueue.findIndex(q => q === queuedRequest);
@@ -4334,23 +4368,23 @@ class RequestSignalsService extends WebsocketService {
4334
4368
  this.activeStreamMethod = queuedRequest.method;
4335
4369
  }
4336
4370
  this._activeRequestCount.update(c => c + 1);
4337
- console.log(`[Queue] Starting ${queuedRequest.method}${queuedRequest.isStream ? ' (STREAM)' : ''}`, {
4338
- activeMethod: this.activeMethod,
4339
- activeStreamMethod: this.activeStreamMethod,
4340
- queueLength: this.requestQueue.length
4341
- });
4371
+ // console.log(`[Queue] Starting ${queuedRequest.method}${queuedRequest.isStream ? ' (STREAM)' : ''}`, {
4372
+ // activeMethod: this.activeMethod,
4373
+ // activeStreamMethod: this.activeStreamMethod,
4374
+ // queueLength: this.requestQueue.length
4375
+ // });
4342
4376
  const sub = queuedRequest.observable.subscribe({
4343
4377
  next: (value) => {
4344
- console.log(`[Queue] ${queuedRequest.method} received value, isStream=${queuedRequest.isStream}`);
4378
+ // console.log(`[Queue] ${queuedRequest.method} received value, isStream=${queuedRequest.isStream}`);
4345
4379
  observer.next(value);
4346
4380
  },
4347
4381
  error: (error) => {
4348
- console.log(`[Queue] ${queuedRequest.method} error:`, error);
4382
+ // console.log(`[Queue] ${queuedRequest.method} error:`, error);
4349
4383
  observer.error(error);
4350
4384
  this.cleanupAndProcessNext(queuedRequest.method, !!queuedRequest.isStream);
4351
4385
  },
4352
4386
  complete: () => {
4353
- console.log(`[Queue] ${queuedRequest.method} complete, isStream=${queuedRequest.isStream}`);
4387
+ // console.log(`[Queue] ${queuedRequest.method} complete, isStream=${queuedRequest.isStream}`);
4354
4388
  observer.complete();
4355
4389
  this.cleanupAndProcessNext(queuedRequest.method, !!queuedRequest.isStream);
4356
4390
  }
@@ -4361,35 +4395,29 @@ class RequestSignalsService extends WebsocketService {
4361
4395
  * Clean up completed request and process next in queue
4362
4396
  */
4363
4397
  cleanupAndProcessNext(method, wasStream) {
4364
- console.log(`[Queue] cleanupAndProcessNext called: method=${method}, wasStream=${wasStream}`, {
4365
- activeMethod: this.activeMethod,
4366
- activeStreamMethod: this.activeStreamMethod,
4367
- queueLength: this.requestQueue.length
4368
- });
4398
+ // console.log(`[Queue] cleanupAndProcessNext called: method=${method}, wasStream=${wasStream}`, {
4399
+ // activeMethod: this.activeMethod,
4400
+ // activeStreamMethod: this.activeStreamMethod,
4401
+ // queueLength: this.requestQueue.length
4402
+ // });
4369
4403
  this.activeRequests.delete(method);
4370
4404
  this.activeMethod = null;
4371
4405
  if (wasStream) {
4372
4406
  this.activeStreamMethod = null;
4373
4407
  }
4374
- this._activeRequestCount.update(c => {
4375
- const newCount = Math.max(0, c - 1);
4376
- if (newCount === 0) {
4377
- this.progress.set(0);
4378
- }
4379
- return newCount;
4380
- });
4381
- console.log(`[Queue] After cleanup:`, {
4382
- activeMethod: this.activeMethod,
4383
- activeStreamMethod: this.activeStreamMethod,
4384
- queueLength: this.requestQueue.length
4385
- });
4408
+ this._activeRequestCount.update(c => Math.max(0, c - 1));
4409
+ // console.log(`[Queue] After cleanup:`, {
4410
+ // activeMethod: this.activeMethod,
4411
+ // activeStreamMethod: this.activeStreamMethod,
4412
+ // queueLength: this.requestQueue.length
4413
+ // });
4386
4414
  // Process next request in queue
4387
4415
  if (this.requestQueue.length > 0) {
4388
4416
  const next = this.requestQueue.shift();
4389
- console.log(`[Queue] Processing next from queue: ${next.method}`, {
4390
- isStream: next.isStream,
4391
- queueLength: this.requestQueue.length
4392
- });
4417
+ // console.log(`[Queue] Processing next from queue: ${next.method}`, {
4418
+ // isStream: next.isStream,
4419
+ // queueLength: this.requestQueue.length
4420
+ // });
4393
4421
  this.startRequest(next, {
4394
4422
  next: (value) => next.resolve(value),
4395
4423
  error: (error) => next.reject(error),
@@ -6344,9 +6372,9 @@ class HTTPManagerStateService extends ComponentStore {
6344
6372
  this.utils = inject(UtilsService);
6345
6373
  this.logger = inject(LoggerService);
6346
6374
  this.error$ = this.httpManagerService.error$;
6347
- this.isPending$ = this.httpManagerService.isPending$.pipe(delay(1));
6348
- this.progress$ = this.httpManagerService.progress$.pipe(delay(1));
6349
- this.streamProgress$ = this.httpManagerService.streamProgress$.pipe(delay(1));
6375
+ this.isPending$ = this.httpManagerService.isPending$;
6376
+ this.progress$ = this.httpManagerService.progress$;
6377
+ this.streamProgress$ = this.httpManagerService.streamProgress$;
6350
6378
  this.operationSuccess = new BehaviorSubject(null);
6351
6379
  this.operationSuccess$ = this.operationSuccess.asObservable();
6352
6380
  // PAGINATION
@@ -6673,10 +6701,10 @@ class HTTPManagerStateService extends ComponentStore {
6673
6701
  return state;
6674
6702
  if (this.dataType === DataType.ARRAY) {
6675
6703
  const dataArray = Array.isArray(data) ? data : [data];
6676
- const stateDataSample = (state.data.length > 0) ? Object.keys(state.data[0]) : [];
6677
- const newDataSample = (dataArray.length > 0) ? Object.keys(dataArray[0]) : [];
6678
- const isSame = (state.data.length === 0) ? false : stateDataSample.every((value, index) => value === newDataSample[index]);
6679
- const updatedData = (!isSame && dataArray.length !== 0) ? this.updateArrayState([], dataArray) : this.updateArrayState(state.data, dataArray);
6704
+ // Non-streaming path: merge incoming records with existing state.
6705
+ // Streaming responses go through `setStreamData$` instead, which always
6706
+ // replaces with the fully-accumulated array from the streaming operator.
6707
+ const updatedData = this.updateArrayState(state.data, dataArray);
6680
6708
  return { ...state, data: updatedData, dataObject: null };
6681
6709
  }
6682
6710
  else {
@@ -6684,6 +6712,18 @@ class HTTPManagerStateService extends ComponentStore {
6684
6712
  return { ...state, data: [], dataObject: dataObject };
6685
6713
  }
6686
6714
  });
6715
+ /**
6716
+ * Streaming-only updater: replaces `data` with the incoming array.
6717
+ *
6718
+ * The streaming operator (`requestStreaming`) accumulates records via `scan`,
6719
+ * so each emission is the full accumulated dataset. Replace, don't merge.
6720
+ */
6721
+ this.setStreamData$ = this.updater((state, data) => {
6722
+ if (!data)
6723
+ return state;
6724
+ const dataArray = Array.isArray(data) ? data : [data];
6725
+ return { ...state, data: dataArray, dataObject: null };
6726
+ });
6687
6727
  this.addData$ = this.updater((state, data) => {
6688
6728
  if (this.dataType === DataType.ARRAY) {
6689
6729
  const exists = state.data.some(item => item.id === data.id);
@@ -6928,32 +6968,27 @@ class HTTPManagerStateService extends ComponentStore {
6928
6968
  }
6929
6969
  }));
6930
6970
  })));
6931
- this.fetchStream = (options) => this.effect(() => of(options).pipe(filter(() => !this.activeStream$.value), // Block if stream already active
6932
- tap(() => {
6933
- console.log('[DEBUG] fetchStream called');
6971
+ this.fetchStream = this.effect((options$) => options$.pipe(tap((options) => {
6972
+ if (this.activeStream$.value) {
6973
+ console.warn('[fetchStream] Stream already active, skipping');
6974
+ return;
6975
+ }
6934
6976
  this.httpManagerService.isPending.next(true);
6935
6977
  this.activeStream$.next(true); // Mark stream as active
6978
+ // Reset streamed-response tracker so a new stream starts clean
6979
+ this.streamedResponse = [];
6936
6980
  }), concatMap((options) => {
6937
6981
  const requestOptions = this.updateRequestOptions(options?.headers);
6938
6982
  requestOptions.stream = true;
6939
- console.log('[DEBUG] Making streaming request:', requestOptions);
6940
6983
  return this.httpManagerService.getRequest(requestOptions, options?.path)
6941
6984
  .pipe(tap((res) => {
6942
- // console.log('[DEBUG] Streaming response received:', res)
6943
- // Always update state with streaming data
6944
- if (res && res.length > 0) {
6945
- // console.log('[DEBUG] Updating state with streaming data:', res)
6946
- this.setData$(res);
6985
+ // Streaming operator emits the fully-accumulated array on every chunk.
6986
+ // Always replace state don't merge — to keep table in sync as records append.
6987
+ if (res && Array.isArray(res) && res.length > 0) {
6988
+ this.setStreamData$(res);
6947
6989
  this.streamedResponse = res;
6948
6990
  }
6949
- else {
6950
- // console.log('[DEBUG] No streaming data or empty array:', res)
6951
- }
6952
- }), map((res) => {
6953
- // console.log('[DEBUG] Returning data to subscribers:', res)
6954
- return res; // Return the data so subscribers can receive it
6955
- }), catchError((error) => {
6956
- // console.error('[DEBUG] Streaming error:', error)
6991
+ }), map((res) => res), catchError((error) => {
6957
6992
  this.httpManagerService.isPending.next(false);
6958
6993
  return of([]);
6959
6994
  }), finalize(() => this.activeStream$.next(false)) // Mark stream as complete
@@ -8467,7 +8502,7 @@ class RequestManagerBasicDemoComponent {
8467
8502
  // Update displayed columns when data changes
8468
8503
  updateDisplayedColumns(data) {
8469
8504
  this.displayedColumns = this.getColumnsFromData(data);
8470
- console.log('[DEMO] Updated columns:', this.displayedColumns);
8505
+ // console.log('[DEMO] Updated columns:', this.displayedColumns)
8471
8506
  }
8472
8507
  // Helper to check if value is an object
8473
8508
  isObject(value) {
@@ -8727,7 +8762,7 @@ class RequestManagerBasicDemoComponent {
8727
8762
  this.requestParams.GET = reqParams.apiOptions;
8728
8763
  this.STREAM$ = this.httpManagerService.getRequest(reqParams.apiOptions, reqParams.path)
8729
8764
  .pipe(tap((data) => {
8730
- console.log("API STREAM response", data);
8765
+ // console.log("API STREAM response", data)
8731
8766
  if (data && data.length > 0) {
8732
8767
  this.updateDisplayedColumns(data);
8733
8768
  }
@@ -8860,7 +8895,7 @@ class StateManagerDemoService extends HTTPManagerStateService {
8860
8895
  auth: "sample-auth-token"
8861
8896
  };
8862
8897
  console.log('[DEMO SERVICE] Calling fetchStream with headers:', headers);
8863
- this.fetchStream();
8898
+ this.fetchStream({ headers });
8864
8899
  }
8865
8900
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StateManagerDemoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8866
8901
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StateManagerDemoService }); }
@@ -8894,7 +8929,7 @@ class RequestManagerStateDemoComponent {
8894
8929
  // Update displayed columns when data changes
8895
8930
  updateDisplayedColumns(data) {
8896
8931
  this.displayedColumns = this.getColumnsFromData(data);
8897
- console.log('[STATE DEMO] Updated columns:', this.displayedColumns);
8932
+ // console.log('[STATE DEMO] Updated columns:', this.displayedColumns)
8898
8933
  }
8899
8934
  // Helper to check if value is an object
8900
8935
  isObject(value) {
@@ -8974,7 +9009,7 @@ class RequestManagerStateDemoComponent {
8974
9009
  this.POST$ = new BehaviorSubject(null);
8975
9010
  this.PUT$ = new BehaviorSubject(null);
8976
9011
  this.DELETE$ = new BehaviorSubject(null);
8977
- this.STREAM = new BehaviorSubject(null);
9012
+ this.STREAM = new BehaviorSubject([]);
8978
9013
  this.STREAM$ = this.STREAM.asObservable();
8979
9014
  this.STREAM_AI = new BehaviorSubject([]);
8980
9015
  this.STREAM_AI$ = this.STREAM_AI.asObservable()
@@ -9032,7 +9067,7 @@ class RequestManagerStateDemoComponent {
9032
9067
  this.stateManagerDemoService.data$.pipe(tap$1((data) => console.log("API STREAM_AI response", data)));
9033
9068
  this.error$.pipe(tap$1((data) => {
9034
9069
  debugger;
9035
- console.log("API STREAM response", data);
9070
+ // console.log("API STREAM response", data)
9036
9071
  }), catchError$1(error => {
9037
9072
  return throwError(() => this.errorHandling(error, 'STREAM'));
9038
9073
  }));
@@ -9042,26 +9077,26 @@ class RequestManagerStateDemoComponent {
9042
9077
  });
9043
9078
  this.stateManagerDemoService.data$
9044
9079
  .pipe(tap$1((data) => {
9045
- console.log('[COMPONENT] State data received:', data);
9080
+ // console.log('[COMPONENT] State data received:', data)
9046
9081
  switch (this.requestType) {
9047
9082
  case 'GET':
9048
- console.log('[COMPONENT] Updating GET$ with data:', data);
9083
+ // console.log('[COMPONENT] Updating GET$ with data:', data)
9049
9084
  this.GET$.next(data);
9050
9085
  break;
9051
9086
  case 'PUT':
9052
- console.log('[COMPONENT] Updating PUT$ with data:', data);
9087
+ // console.log('[COMPONENT] Updating PUT$ with data:', data)
9053
9088
  this.PUT$.next(data);
9054
9089
  break;
9055
9090
  case 'POST':
9056
- console.log('[COMPONENT] Updating POST$ with data:', data);
9091
+ // console.log('[COMPONENT] Updating POST$ with data:', data)
9057
9092
  this.POST$.next(data);
9058
9093
  break;
9059
9094
  case 'DELETE':
9060
- console.log('[COMPONENT] Updating DELETE$ with data:', data);
9095
+ // console.log('[COMPONENT] Updating DELETE$ with data:', data)
9061
9096
  this.DELETE$.next(data);
9062
9097
  break;
9063
9098
  case 'STREAM':
9064
- console.log('[COMPONENT] Updating STREAM$ with data:', data);
9099
+ // console.log('[COMPONENT] Updating STREAM$ with data:', data)
9065
9100
  this.STREAM.next(data);
9066
9101
  // Update table columns dynamically based on streaming data
9067
9102
  if (data && Array.isArray(data) && data.length > 0) {
@@ -9069,11 +9104,11 @@ class RequestManagerStateDemoComponent {
9069
9104
  }
9070
9105
  break;
9071
9106
  case 'STREAM_AI':
9072
- console.log('[COMPONENT] Updating STREAM_AI$ with data:', data);
9107
+ // console.log('[COMPONENT] Updating STREAM_AI$ with data:', data)
9073
9108
  this.STREAM_AI.next(data);
9074
9109
  break;
9075
9110
  default:
9076
- console.log('[COMPONENT] No requestType set, ignoring data');
9111
+ // console.log('[COMPONENT] No requestType set, ignoring data')
9077
9112
  break;
9078
9113
  }
9079
9114
  })).subscribe();
@@ -9137,18 +9172,18 @@ class RequestManagerStateDemoComponent {
9137
9172
  this.stateManagerDemoService.deleteClient(this.sampleClientData);
9138
9173
  }
9139
9174
  onStreamRequest() {
9140
- console.log('[COMPONENT] onStreamRequest called');
9175
+ // console.log('[COMPONENT] onStreamRequest called')
9141
9176
  if (!this.isValid) {
9142
- console.log('[COMPONENT] Form invalid, aborting');
9177
+ // console.log('[COMPONENT] Form invalid, aborting')
9143
9178
  return;
9144
9179
  }
9145
- console.log('[COMPONENT] Compiling request...');
9180
+ // console.log('[COMPONENT] Compiling request...')
9146
9181
  const reqParams = this.compileRequest();
9147
- console.log('[COMPONENT] Setting stream options:', reqParams.apiOptions);
9182
+ // console.log('[COMPONENT] Setting stream options:', reqParams.apiOptions)
9148
9183
  reqParams.apiOptions.stream = true;
9149
9184
  reqParams.apiOptions.streamType = this.streamType;
9150
9185
  this.requestType = 'STREAM';
9151
- console.log('[COMPONENT] Calling streamRequest...');
9186
+ // console.log('[COMPONENT] Calling streamRequest...')
9152
9187
  this.stateManagerDemoService.streamRequest();
9153
9188
  }
9154
9189
  errorHandling(err, type) {
@@ -9173,11 +9208,11 @@ class RequestManagerStateDemoComponent {
9173
9208
  this.prompts = [];
9174
9209
  }
9175
9210
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9176
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [StateManagerDemoService, HTTPManagerService], viewQueries: [{ propertyName: "failedState", first: true, predicate: ["failedState"], descendants: true, static: true }, { propertyName: "pollingState", first: true, predicate: ["pollingState"], descendants: true, static: true }], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n @for (task of headers.controls; track task; let i = $index) {\n <div [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n @if (failedState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n }\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n </div>\n </div>\n </div>\n }\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((STREAM$ | async) && (isStreamingPending$ | async); as data) {\n <mat-progress-bar mode=\"determinate\" [value]=\"(progress$ | async)?.percent ?? 0\"></mat-progress-bar>\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Data received\n </div>\n </div>\n }\n </div>\n\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
9211
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [StateManagerDemoService, HTTPManagerService], viewQueries: [{ propertyName: "failedState", first: true, predicate: ["failedState"], descendants: true, static: true }, { propertyName: "pollingState", first: true, predicate: ["pollingState"], descendants: true, static: true }], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n @for (task of headers.controls; track task; let i = $index) {\n <div [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n @if (failedState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n }\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n </div>\n </div>\n </div>\n }\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((isStreamingPending$ | async) || ((STREAM$ | async)?.length)) {\n <mat-progress-bar mode=\"determinate\" [value]=\"(progress$ | async)?.percent ?? 0\"></mat-progress-bar>\n }\n @if ((STREAM$ | async); as data) {\n @if (data?.length) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Rows: {{ data.length }}\n </div>\n </div>\n }\n }\n </div>\n\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
9177
9212
  }
9178
9213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, decorators: [{
9179
9214
  type: Component,
9180
- args: [{ selector: 'app-request-manager-state-demo', providers: [StateManagerDemoService, HTTPManagerService], standalone: false, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n @for (task of headers.controls; track task; let i = $index) {\n <div [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n @if (failedState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n }\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n </div>\n </div>\n </div>\n }\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((STREAM$ | async) && (isStreamingPending$ | async); as data) {\n <mat-progress-bar mode=\"determinate\" [value]=\"(progress$ | async)?.percent ?? 0\"></mat-progress-bar>\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Data received\n </div>\n </div>\n }\n </div>\n\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}.box{padding:10px;border:1px solid #ccc}\n"] }]
9215
+ args: [{ selector: 'app-request-manager-state-demo', providers: [StateManagerDemoService, HTTPManagerService], standalone: false, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n @for (task of headers.controls; track task; let i = $index) {\n <div [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n @if (failedState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n }\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n </div>\n </div>\n </div>\n }\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((isStreamingPending$ | async) || ((STREAM$ | async)?.length)) {\n <mat-progress-bar mode=\"determinate\" [value]=\"(progress$ | async)?.percent ?? 0\"></mat-progress-bar>\n }\n @if ((STREAM$ | async); as data) {\n @if (data?.length) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Rows: {{ data.length }}\n </div>\n </div>\n }\n }\n </div>\n\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}.box{padding:10px;border:1px solid #ccc}\n"] }]
9181
9216
  }], ctorParameters: () => [], propDecorators: { server: [{
9182
9217
  type: Input
9183
9218
  }], adapter: [{
@@ -9208,7 +9243,7 @@ class RequestManagerDemoComponent {
9208
9243
  // Update displayed columns when data changes
9209
9244
  updateDisplayedColumns(data) {
9210
9245
  this.displayedColumns = this.getColumnsFromData(data);
9211
- console.log('[DEMO] Updated columns:', this.displayedColumns);
9246
+ // console.log('[DEMO] Updated columns:', this.displayedColumns)
9212
9247
  }
9213
9248
  // Helper to check if value is an object
9214
9249
  isObject(value) {
@@ -9492,7 +9527,7 @@ class RequestManagerDemoComponent {
9492
9527
  this.STREAM_error$.next('');
9493
9528
  this.STREAM$ = this.httpManagerService.getRequest(reqParams.apiOptions, reqParams.path)
9494
9529
  .pipe(tap((data) => {
9495
- console.log("API STREAM response", data);
9530
+ // console.log("API STREAM response", data)
9496
9531
  if (data && data.length > 0) {
9497
9532
  this.updateDisplayedColumns(data);
9498
9533
  }