UNPKG

@rxap/data-source

Version:

Provides a set of classes and decorators for creating and managing data sources in Angular applications, including base classes, static data sources, observable data sources, and method data sources. It also includes a component for displaying data source

656 lines (642 loc) 29.7 kB
import { NgIf, JsonPipe } from '@angular/common'; import * as i0 from '@angular/core'; import { signal, Component, ChangeDetectionStrategy, Inject, Input, isDevMode, Injectable, Optional, InjectionToken } from '@angular/core'; import * as i1 from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button'; import * as i2 from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { IsNotReleaseVersion, RXAP_ENVIRONMENT } from '@rxap/environment'; import * as i1$1 from 'rxjs'; import { Subscription, Observable, Subject, EMPTY, ReplaySubject, firstValueFrom, from, isObservable } from 'rxjs'; import { BaseDefinition, RXAP_DEFINITION_METADATA, DefinitionMetadata, DefinitionLoader } from '@rxap/definition'; import { ToggleSubject, CloneObservable } from '@rxap/rxjs'; import { clone, GenerateRandomString, deepMerge, RxapError, isPromiseLike, isPromise } from '@rxap/utilities'; import { tap, finalize, takeUntil, startWith, take, switchMap, map } from 'rxjs/operators'; import { ToMethod } from '@rxap/pattern'; class DataSourceErrorComponent { set dataSourceLike(value) { this.refresh ??= value.refresh; this.retry ??= value.retry; this.reset ??= value.reset; this.loading ??= value.loading ?? value.loading$; this.error ??= value.error ?? value.error$; } constructor(environment) { this.environment = environment; this.isNotRelease = false; this.errorMessage = signal('Unknown Error'); this.retryInProgress = signal(false); this.resetInProgress = signal(false); this.isNotRelease = IsNotReleaseVersion(environment); } ngOnChanges(changes) { if (changes['error']) { this.retryInProgress.set(false); this.resetInProgress.set(false); } if (changes['loading']) { if (!changes['loading'].currentValue && typeof changes['loading'].currentValue === 'boolean') { this.retryInProgress.set(false); this.resetInProgress.set(false); } } } ngOnDestroy() { this._subscription?.unsubscribe(); } ngOnInit() { this._subscription = new Subscription(); if (this.loading instanceof Observable) { this._subscription.add(this.loading.subscribe((loading) => { if (!loading) { if (this.retryInProgress()) { this.retryInProgress.set(false); } if (this.resetInProgress()) { this.resetInProgress.set(false); } } })); } if (this.error instanceof Observable) { this._subscription.add(this.error.subscribe((error) => { if (error) { this.errorMessage.set(error.message); } })); } } triggerRetry() { if (this.retry) { this.retryInProgress.set(true); this.retry(); } else if (this.refresh) { this.retryInProgress.set(true); this.refresh(); } } triggerReset() { if (this.reset) { this.resetInProgress.set(true); this.reset(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceErrorComponent, deps: [{ token: RXAP_ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.1", type: DataSourceErrorComponent, isStandalone: true, selector: "rxap-data-source-error", inputs: { error: "error", refresh: "refresh", retry: "retry", reset: "reset", dataSourceLike: "dataSourceLike", loading: "loading" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"p-10 w-full\">\n <div class=\"flex flex-col justify-center items-center gap-8\">\n <span i18n>Something has gone wrong!</span>\n <div class=\"flex flex-row justify-center items-center gap-4\">\n <button *ngIf=\"refresh || retry\" type=\"button\" (click)=\"triggerRetry()\" [disabled]=\"retryInProgress() || resetInProgress()\" mat-stroked-button>\n <span class=\"flex flex-row items-center gap-4\">\n <span i18n>Retry</span>\n <mat-spinner *ngIf=\"retryInProgress()\" [diameter]=\"15\"></mat-spinner>\n </span>\n </button>\n <button *ngIf=\"reset\" type=\"button\" (click)=\"triggerReset()\" [disabled]=\"resetInProgress() || retryInProgress()\" mat-stroked-button>\n <span class=\"flex flex-row items-center gap-4\">\n <span i18n>Reset</span>\n <mat-spinner *ngIf=\"resetInProgress()\" [diameter]=\"15\"></mat-spinner>\n </span>\n </button>\n </div>\n <span *ngIf=\"isNotRelease\" class=\"text-red-700\">{{errorMessage()}}</span>\n </div>\n</div>\n", styles: [".container{padding:64px;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceErrorComponent, decorators: [{ type: Component, args: [{ selector: 'rxap-data-source-error', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ MatButtonModule, NgIf, MatProgressSpinnerModule, JsonPipe, ], template: "<div class=\"p-10 w-full\">\n <div class=\"flex flex-col justify-center items-center gap-8\">\n <span i18n>Something has gone wrong!</span>\n <div class=\"flex flex-row justify-center items-center gap-4\">\n <button *ngIf=\"refresh || retry\" type=\"button\" (click)=\"triggerRetry()\" [disabled]=\"retryInProgress() || resetInProgress()\" mat-stroked-button>\n <span class=\"flex flex-row items-center gap-4\">\n <span i18n>Retry</span>\n <mat-spinner *ngIf=\"retryInProgress()\" [diameter]=\"15\"></mat-spinner>\n </span>\n </button>\n <button *ngIf=\"reset\" type=\"button\" (click)=\"triggerReset()\" [disabled]=\"resetInProgress() || retryInProgress()\" mat-stroked-button>\n <span class=\"flex flex-row items-center gap-4\">\n <span i18n>Reset</span>\n <mat-spinner *ngIf=\"resetInProgress()\" [diameter]=\"15\"></mat-spinner>\n </span>\n </button>\n </div>\n <span *ngIf=\"isNotRelease\" class=\"text-red-700\">{{errorMessage()}}</span>\n </div>\n</div>\n", styles: [".container{padding:64px;width:100%}\n"] }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [RXAP_ENVIRONMENT] }] }], propDecorators: { error: [{ type: Input }], refresh: [{ type: Input }], retry: [{ type: Input }], reset: [{ type: Input }], dataSourceLike: [{ type: Input }], loading: [{ type: Input }] } }); class BaseDataSource extends BaseDefinition { get lastRefreshed() { return this._lastRefreshed; } constructor(metadata = null) { super(metadata); this.change$ = new Subject(); /** * Indicates weather the data source is currently loading new data */ this.loading$ = EMPTY; this.hasError$ = new ToggleSubject(); this.error$ = new ReplaySubject(1); this._lastRefreshed = null; this._connectedViewer = new Map(); this._connectedViewerTeardown = new Map(); this._data$ = EMPTY; /** * a map of viewer to view id. * Allows to create a view id from the viewer object reference * @protected */ this._viewerIds = new Map(); this._retry$ = new Subject(); } get data() { return clone(this._data); } get hasConnections() { return this._connectedViewer.size > 0; } getViewerId(viewer) { if (viewer.id) { return viewer.id; } if (!this._viewerIds.has(viewer)) { this._viewerIds.set(viewer, GenerateRandomString()); } return this._viewerIds.get(viewer); } connect(viewerOrString) { let viewer; if (typeof viewerOrString === 'string') { viewer = { id: viewerOrString }; } else { viewer = viewerOrString; } if (!viewer.id) { viewer.id = this.getViewerId(viewer); } if (this.isConnected(viewer)) { return this._connectedViewer.get(viewer.id); } if (!viewer.viewChange) { viewer.viewChange = EMPTY; } const _connection = this._connect(viewer); let connection; let teardownLogic = null; if (Array.isArray(_connection)) { if (_connection.length !== 2) { throw new Error('if this._connect returns an array. The array should have two items'); } connection = _connection[0]; teardownLogic = _connection[1]; } else { connection = _connection; } const destroy$ = new Subject(); const cacheKey = ['rxap', 'data-source', this.constructor.name, this.id].join('_'); const restore = viewer.restore ?? this.metadata.restore ?? false; connection = connection.pipe(tap((data) => { this._data = data; if (restore) { try { const cache = JSON.stringify(data); localStorage.setItem(cacheKey, cache); } catch (e) { console.warn(`Failed to store data source '${this.id}' data in local storage`); } } }), tap((data) => this.change$.next(data)), tap(() => this._lastRefreshed = new Date()), finalize(() => this.disconnect(viewer)), takeUntil(destroy$)); if (restore) { const data = localStorage.getItem(cacheKey); if (data) { this._data = JSON.parse(data); connection = connection.pipe(startWith(this._data)); } } this._connectedViewer.set(viewer.id, connection); if (teardownLogic) { const tl = teardownLogic; teardownLogic = () => { destroy$.next(); if (typeof tl === 'function') { tl(); } else { tl.unsubscribe(); } }; } else { teardownLogic = () => { destroy$.next(); }; } this._connectedViewerTeardown.set(viewer.id, teardownLogic); return connection; } attach(viewerId) { if (this.isConnected(viewerId)) { return CloneObservable(this._connectedViewer.get(viewerId)); } throw new Error(`No active connection with viewer id '${viewerId}' found`); } isConnected(viewerOrId) { const viewerId = typeof viewerOrId === 'string' ? viewerOrId : viewerOrId.id ?? this.getViewerId(viewerOrId); return this._connectedViewer.has(viewerId); } disconnect(viewerOrId) { const viewerId = typeof viewerOrId === 'string' ? viewerOrId : viewerOrId.id ?? this.getViewerId(viewerOrId); if (this.isConnected(viewerId)) { this._disconnect(viewerId); this._connectedViewer.delete(viewerId); if (this._connectedViewerTeardown.has(viewerId)) { const teardownLogic = this._connectedViewerTeardown.get(viewerId); if (teardownLogic) { if (typeof teardownLogic === 'function') { teardownLogic(); } else { teardownLogic.unsubscribe(); } } } } else { console.warn(`Connection with viewer id '${viewerId}' is not connected to the data source '${this.id}'`); } // TODO : find better cleanup solution if (typeof viewerOrId === 'string') { for (const [viewer, id] of this._viewerIds.entries()) { if (viewerOrId === id) { this._viewerIds.delete(viewer); } } } else { this._viewerIds.delete(viewerOrId); } } /** * Creates a connection to tha data source and converts the Observable into a * promise and then disconnects the viewer */ async toPromise(viewer) { const result = await firstValueFrom(this.connect(viewer).pipe(take(1))); this.disconnect(viewer); return result; } derive(id, metadata = this.metadata) { return new BaseDataSource({ ...deepMerge(this.metadata, metadata), id, }); } toJSON() { return { id: this.id, metadata: this.metadata, connected: this._connectedViewer.keys(), data: this._data, }; } // eslint-disable-next-line @typescript-eslint/no-empty-function refresh() { } retry() { this._retry$.next(); } reset() { for (const viewerId of this._connectedViewer.keys()) { this.disconnect(viewerId); } // eslint-disable-next-line no-prototype-builtins if (this.metadata.hasOwnProperty('context')) { delete this.metadata['context']; } } // eslint-disable-next-line @typescript-eslint/no-empty-function _disconnect(viewerId) { } genericRetryFunction(error, retryCount) { return this._retry$.asObservable().pipe(tap(() => this.hasError$.disable())); } handelError(error) { if (isDevMode()) { console.log(`DataSource '${this.id}' has an error:`, error); } } _connect(viewer) { this.init(); return this._data$; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource, deps: [{ token: RXAP_DEFINITION_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseDataSource, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_DEFINITION_METADATA] }] }] }); function RxapDataSource(dataSourceIdOrMetadata, className = 'BaseDataSource', packageName = '@rxap/data-source') { return function (target) { DefinitionMetadata(dataSourceIdOrMetadata, className, packageName)(target); }; } class DataSourceLoader extends DefinitionLoader { connect(dataSourceIdOrInstanceOrToken, viewer, metadata, injector, notFoundValue, flags) { return this .load(dataSourceIdOrInstanceOrToken, metadata, injector, notFoundValue, flags) .connect(viewer); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataSourceLoader, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); function DataSourceRefreshToMethodAdapterFactory(dataSource) { return ToMethod(() => dataSource.refresh()); } class RxapDataSourceError extends RxapError { constructor(message, code, className) { super('@rxap/data-source', message, code, className); } } const RXAP_STATIC_DATA_SOURCE_DATA = new InjectionToken('rxap/data-source/static-data-source-data'); const RXAP_DATA_SOURCE_REFRESH = new InjectionToken('rxap/data-source/refresh'); const RXAP_OBSERVABLE_DATA_SOURCE = new InjectionToken('rxap/data-source/observable-data-source'); const RXAP_DATA_SOURCE_METADATA = new InjectionToken('rxap/data-source/metadata'); const RXAP_DATA_SOURCE = new InjectionToken('rxap/data-source/instance'); const RXAP_PIPE_DATA_SOURCE_OPERATOR = new InjectionToken('rxap/data-source/pipe-operator'); const RXAP_DATA_SOURCE_METHOD = new InjectionToken('rxap/data-source/method'); const RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS = new InjectionToken('rxap/data-source/method-without-parameters', { providedIn: 'root', factory: () => false, }); class MethodDataSource extends BaseDataSource { constructor(method, withoutParameters = false) { super(method.metadata); this.method = method; this.withoutParameters = withoutParameters; this._data$ = new ReplaySubject(1); this.loading$ = new ToggleSubject(false); this._refresh = new Subject(); } ngOnInit() { if (this.withoutParameters) { this.executeWithoutParameters(); } } refresh() { this._refresh.next(); if (this.withoutParameters) { this.executeWithoutParameters(); } } _connect(viewer) { if (this.withoutParameters) { return super._connect(viewer); } else { return this._refresh.pipe(tap(() => this.hasError$.disable()), startWith(undefined), switchMap(() => { if (viewer.viewChange && viewer.viewChange !== EMPTY) { return viewer.viewChange.pipe(tap(() => this.loading$.enable()), switchMap((parameters) => from(this.execute(parameters)).pipe(this.handelExecution()))); } else { this.loading$.enable(); return from(this.execute(viewer)).pipe(this.handelExecution()); } })); } } handelExecution() { return tap({ next: () => { this.loading$.disable(); }, error: (error) => { this.loading$.disable(); this.hasError$.enable(); this.error$.next(error); }, finalize: () => { this.loading$.disable(); } }); } async execute(parameters) { return this.method.call(parameters); } async executeWithoutParameters() { this.hasError$.disable(); this.loading$.enable(); await firstValueFrom(from(this.execute()).pipe(this.handelExecution(), tap({ next: (data) => this._data$.next(data), }))); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource, deps: [{ token: RXAP_DATA_SOURCE_METHOD }, { token: RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: MethodDataSource, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [RXAP_DATA_SOURCE_METHOD] }] }, { type: undefined, decorators: [{ type: Inject, args: [RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS] }] }] }); class ObservableDataSource extends BaseDataSource { constructor(observable, metadata = null) { super(metadata); if (observable) { this._data$ = observable; } else if (this.metadata.data) { this._data$ = this.metadata.data; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource, deps: [{ token: RXAP_OBSERVABLE_DATA_SOURCE, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: ObservableDataSource, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1$1.Observable, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_OBSERVABLE_DATA_SOURCE] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_DATA_SOURCE_METADATA] }] }] }); function RxapObservableDataSource(metadata, className = 'ObservableDataSource', packageName = '@rxap/data-source') { return function (target) { RxapDataSource(metadata, className, packageName)(target); }; } function observableDataSource(data, metadata = { id: 'static' }) { return new ObservableDataSource(data, metadata); } function RxapPipeDataSource(metadata, className = 'PipeDataSource', packageName = '@rxap/data-source') { return function (target) { RxapDataSource(metadata, className, packageName)(target); }; } class PipeDataSource extends BaseDataSource { constructor(dataSource, operation = null, ...operations) { super(dataSource.metadata); this.dataSource = dataSource; this._refresh = new Subject(); this._operations = []; this.loading$ = this.dataSource.loading$; if (operation) { this.setOperations(operation, ...operations.filter(op => typeof op === 'function')); if (operations.some(op => typeof op !== 'function')) { this.metadata = { ...this.metadata, ...operations.find(op => typeof op !== 'function'), }; } } } get operations() { return this._operations; } setOperations(operation, ...operations) { if (this._initialised) { throw new RxapDataSourceError('Can not set operations after the data source is initialised', '', 'PipeDataSource'); } this._operations = [operation, ...operations]; } ngOnDestroy() { super.ngOnDestroy(); this.dataSource.disconnect(this.metadata); } /** * @param parent true - call the refresh method of the parent data source */ refresh(parent = this.metadata['refreshParent'] ?? false) { if (parent) { this.dataSource.refresh(); } else { this._refresh.next(); } } reset() { return this.dataSource.reset(); } toJSON() { return { ...super.toJSON(), dataSource: this.dataSource, }; } _connect(viewer) { this.init(); return [ this.dataSource.connect(viewer).pipe(switchMap(data => this._refresh.pipe(startWith(null), map(() => data))), // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore ...this.viewerToOperations(viewer)), () => this.dataSource.disconnect(viewer), ]; } viewerToOperations(viewer) { return this.operations; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource, deps: [{ token: RXAP_DATA_SOURCE }, { token: RXAP_PIPE_DATA_SOURCE_OPERATOR, optional: true }, { token: Array }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: PipeDataSource, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: BaseDataSource, decorators: [{ type: Inject, args: [RXAP_DATA_SOURCE] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_PIPE_DATA_SOURCE_OPERATOR] }] }, { type: Array }] }); function pipeDataSource(dataSource, operation, ...operations) { return new PipeDataSource(dataSource, operation, ...operations); } class StaticDataSource extends BaseDataSource { constructor(data, metadata) { super(metadata); this._data$ = new ReplaySubject(1); if ((data === undefined || data === null) && this.metadata.data !== undefined) { data = this.metadata.data; } if (data === undefined) { throw new RxapDataSourceError(`Can not create static data source '${this.id}' with undefined as data`, ''); } if (isObservable(data)) { this._dataSubscription = data.pipe(tap({ next: data => this._data$.next(data), error: error => this.error$.next(error), })).subscribe(); } else if (isPromiseLike(data)) { if (isPromise(data)) { data.then(data => this._data$.next(data)).catch((error) => this.error$.next(error)); } else { data.then(data => this._data$.next(data)); } } else if (typeof data === 'function') { // TODO : fix typeof function cast this._data$.next((this._data = data())); } else { this._data$.next((this._data = data)); } } get data() { return clone(this._data); } set data(value) { const data = clone(value); this._data = data; this._data$.next(data); } ngOnDestroy() { super.ngOnDestroy(); this._dataSubscription?.unsubscribe(); } _connect() { this.init(); return this._data$.asObservable(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource, deps: [{ token: RXAP_STATIC_DATA_SOURCE_DATA, optional: true }, { token: RXAP_DATA_SOURCE_METADATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StaticDataSource, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_STATIC_DATA_SOURCE_DATA] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_DATA_SOURCE_METADATA] }] }] }); function RxapStaticDataSource(metadata, className = 'StaticDataSource', packageName = '@rxap/data-source') { return function (target) { RxapDataSource(metadata, className, packageName)(target); }; } function staticDataSource(data, metadata = { id: 'static' }) { return new StaticDataSource(data, metadata); } // region data-source-error // endregion /** * Generated bundle index. Do not edit. */ export { BaseDataSource, DataSourceErrorComponent, DataSourceLoader, DataSourceRefreshToMethodAdapterFactory, MethodDataSource, ObservableDataSource, PipeDataSource, RXAP_DATA_SOURCE, RXAP_DATA_SOURCE_METADATA, RXAP_DATA_SOURCE_METHOD, RXAP_DATA_SOURCE_METHOD_WITHOUT_PARAMETERS, RXAP_DATA_SOURCE_REFRESH, RXAP_OBSERVABLE_DATA_SOURCE, RXAP_PIPE_DATA_SOURCE_OPERATOR, RXAP_STATIC_DATA_SOURCE_DATA, RxapDataSource, RxapDataSourceError, RxapObservableDataSource, RxapPipeDataSource, RxapStaticDataSource, StaticDataSource, observableDataSource, pipeDataSource, staticDataSource }; //# sourceMappingURL=rxap-data-source.mjs.map