@mysteryinfosolutions/api-core 1.6.3 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Component } from '@angular/core';
|
|
3
|
-
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { BehaviorSubject, map } from 'rxjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* BaseResourceConfig<T>
|
|
@@ -142,7 +142,7 @@ class BaseStateService {
|
|
|
142
142
|
recordsSubject = new BehaviorSubject([]);
|
|
143
143
|
pagerSubject = new BehaviorSubject(null);
|
|
144
144
|
selectedSubject = new BehaviorSubject(null);
|
|
145
|
-
|
|
145
|
+
loadingMapSubject = new BehaviorSubject({});
|
|
146
146
|
savingSubject = new BehaviorSubject(false);
|
|
147
147
|
errorSubject = new BehaviorSubject(null);
|
|
148
148
|
/** Observable stream of current filter. */
|
|
@@ -154,7 +154,7 @@ class BaseStateService {
|
|
|
154
154
|
/** Observable stream of the currently selected record. */
|
|
155
155
|
selected$ = this.selectedSubject.asObservable();
|
|
156
156
|
/** Observable stream of loading state. */
|
|
157
|
-
loading$ = this.
|
|
157
|
+
loading$ = this.loadingMapSubject.asObservable();
|
|
158
158
|
/** Observable stream of saving state. */
|
|
159
159
|
saving$ = this.savingSubject.asObservable();
|
|
160
160
|
/** Observable stream of current error message. */
|
|
@@ -252,11 +252,25 @@ class BaseStateService {
|
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
254
|
/**
|
|
255
|
-
*
|
|
256
|
-
*
|
|
255
|
+
* Returns an observable boolean for a specific loading key.
|
|
256
|
+
* Useful for tracking loading state in a specific view or feature.
|
|
257
|
+
*
|
|
258
|
+
* @param key A unique key representing the loading context (e.g., "list", "detail")
|
|
259
|
+
* @returns Observable emitting `true` if the given context is loading, `false` otherwise.
|
|
257
260
|
*/
|
|
258
|
-
|
|
259
|
-
this.
|
|
261
|
+
isLoading$(key) {
|
|
262
|
+
return this.loading$.pipe(map(state => !!state[key]));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Sets the loading state for a specific key.
|
|
266
|
+
* This allows you to control multiple concurrent loading states independently.
|
|
267
|
+
*
|
|
268
|
+
* @param key The loading context name (e.g., "list", "form", "detail")
|
|
269
|
+
* @param value The loading status (`true` for loading, `false` for done)
|
|
270
|
+
*/
|
|
271
|
+
setLoading(key, value) {
|
|
272
|
+
const current = this.loadingMapSubject.value;
|
|
273
|
+
this.loadingMapSubject.next({ ...current, [key]: value });
|
|
260
274
|
}
|
|
261
275
|
/**
|
|
262
276
|
* Sets the saving flag.
|
|
@@ -283,13 +297,27 @@ class BaseStateService {
|
|
|
283
297
|
clearSelection() {
|
|
284
298
|
this.selectedSubject.next(null);
|
|
285
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Clears the loading state for a specific key or all keys if none is provided.
|
|
302
|
+
*
|
|
303
|
+
* @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.
|
|
304
|
+
*/
|
|
305
|
+
clearLoading(key) {
|
|
306
|
+
if (key) {
|
|
307
|
+
const { [key]: _, ...rest } = this.loadingMapSubject.value;
|
|
308
|
+
this.loadingMapSubject.next(rest);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.loadingMapSubject.next({});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
286
314
|
/** Resets the entire state to initial values. */
|
|
287
315
|
reset() {
|
|
288
316
|
this.recordsSubject.next([]);
|
|
289
317
|
this.pagerSubject.next(null);
|
|
290
318
|
this.selectedSubject.next(null);
|
|
291
319
|
this.setFilter({ page: 1, pageLength: 10 });
|
|
292
|
-
this.
|
|
320
|
+
this.clearLoading();
|
|
293
321
|
this.setSaving(false);
|
|
294
322
|
this.setError(null);
|
|
295
323
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysteryinfosolutions-api-core.mjs","sources":["../../../projects/api-core/src/lib/configs/base-resource-config.ts","../../../projects/api-core/src/lib/api-core.ts","../../../projects/api-core/src/lib/enums/selectmodes.enum.ts","../../../projects/api-core/src/lib/utils/query-utils.ts","../../../projects/api-core/src/lib/models/filter.model.ts","../../../projects/api-core/src/lib/models/sort.model.ts","../../../projects/api-core/src/lib/services/base-state.service.ts","../../../projects/api-core/src/lib/services/base.service.ts","../../../projects/api-core/src/public-api.ts","../../../projects/api-core/src/mysteryinfosolutions-api-core.ts"],"sourcesContent":["// base-resource-config.ts\nimport { TableColumn } from \"../models\";\n\n/**\n * BaseResourceConfig<T>\n *\n * A generic configuration class to standardize table-based resource UIs.\n * Extend this in feature modules (e.g., Users, Roles, Genders) to reuse core settings.\n */\nexport abstract class BaseResourceConfig<T> {\n /**\n * Table columns definition for the resource.\n */\n columns: TableColumn<T>[] = [];\n\n /**\n * The column used for date-range filtering (e.g., in filters or reporting).\n */\n dateRangeColumn: keyof T | string = 'updated_at';\n\n /**\n * Default column used to sort the table data.\n */\n defaultSortColumn: keyof T | string = 'updated_at';\n\n /**\n * Default sorting order (ASC or DESC).\n */\n defaultSortOrder: 'ASC' | 'DESC' = 'DESC';\n\n /**\n * Page size options for the table paginator.\n */\n pageLengthOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Default page size.\n */\n defaultPageLength: number = 10;\n\n /**\n * Keys (fields) to apply search filter on.\n */\n searchColumns: (keyof T | string)[] = [];\n\n /**\n * Modal configuration: size for the create/update (modify) modal.\n */\n modifyModalSize: 'sm' | 'md' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for modify modal.\n */\n modifyModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Modal configuration: size for the view/summary modal.\n */\n summaryModalSize: 'sm' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for summary modal.\n */\n summaryModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Determines the default view when viewing details of a record.\n * 'overview' = navigates to a new page\n * 'summary' = opens a modal with summary component\n */\n defaultDetailView: 'overview' | 'summary' = 'summary';\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-api-core',\n imports: [],\n template: `\n <p>\n api-core works!\n </p>\n `,\n styles: ``\n})\nexport class ApiCore {\n\n}\n","export enum SELECT_MODE {\n ALL = 1,\n ONLYCOLUMNS = 2,\n};\n","import { SortItem } from '../models';\n\nexport const sortObjectToString = (sortItems: SortItem[]): string => {\n if (!Array.isArray(sortItems) || sortItems.length === 0) return '';\n return sortItems.map(s => `${s.field}:${s.order}`).join(',');\n};\n\nexport const jsonToQueryString = (json: any): string => {\n if (!json || typeof json !== 'object') return '';\n\n if (json.hasOwnProperty('sort')) {\n json.sort = sortObjectToString(json.sort);\n }\n\n const queryArray = Object.keys(json)\n .filter(key => json[key] !== undefined && json[key] !== null)\n .map(key => {\n if (Array.isArray(json[key])) {\n return `${encodeURIComponent(key)}=${encodeURIComponent('[' + json[key].toString() + ']')}`;\n } else {\n return `${encodeURIComponent(key)}=${encodeURIComponent(json[key])}`;\n }\n });\n\n return queryArray.length > 0 ? `?${queryArray.join('&')}` : '';\n};\n\nexport const isEmpty = (obj: any): boolean => {\n return !obj || Object.keys(obj).length === 0;\n};\n","import { SortItem } from './';\nimport { SELECT_MODE } from '../enums';\n\nexport abstract class Filter {\n dateRangeColumn?: string;\n dateRangeFrom?: string;\n dateRangeTo?: string;\n\n page?: number = 1;\n pageLength?: number = 10;\n\n sort?: SortItem[] = [];\n\n search?: string;\n searchColumns?: string;\n selectColumns?: string;\n selectMode?: SELECT_MODE;\n}","export class SortItem {\n constructor(\n public field: string,\n public order: 'ASC' | 'DESC'\n ) {}\n}\n\n","import { BehaviorSubject } from \"rxjs\";\nimport { Filter, IMultiresult, IMultiresultMetaData, SortItem } from \"../models\";\n\n/**\n * A generic state management service for handling filters, pagination, and records.\n */\nexport class BaseStateService<\n TRecord,\n TFilter extends Partial<TRecord> & Filter = Partial<TRecord> & Filter\n> {\n private readonly filterSubject = new BehaviorSubject<TFilter>({ page: 1, pageLength: 10 } as TFilter);\n private readonly recordsSubject = new BehaviorSubject<TRecord[]>([]);\n private readonly pagerSubject = new BehaviorSubject<IMultiresultMetaData | null>(null);\n private readonly selectedSubject = new BehaviorSubject<TRecord | null>(null);\n private readonly loadingSubject = new BehaviorSubject<boolean>(false);\n private readonly savingSubject = new BehaviorSubject<boolean>(false);\n private readonly errorSubject = new BehaviorSubject<string | null>(null);\n\n /** Observable stream of current filter. */\n filter$ = this.filterSubject.asObservable();\n\n /** Observable stream of current records. */\n records$ = this.recordsSubject.asObservable();\n\n /** Observable stream of current pager metadata. */\n pager$ = this.pagerSubject.asObservable();\n\n /** Observable stream of the currently selected record. */\n selected$ = this.selectedSubject.asObservable();\n\n /** Observable stream of loading state. */\n loading$ = this.loadingSubject.asObservable();\n\n /** Observable stream of saving state. */\n saving$ = this.savingSubject.asObservable();\n\n /** Observable stream of current error message. */\n error$ = this.errorSubject.asObservable();\n\n /** Returns the current filter. */\n get currentFilter(): TFilter {\n return this.filterSubject.value;\n }\n\n /** Returns the currently loaded records. */\n get currentRecords(): TRecord[] {\n return this.recordsSubject.value;\n }\n\n /** Returns the currently selected record, if any. */\n get selected(): TRecord | null {\n return this.selectedSubject.value;\n }\n\n /**\n * Updates the current filter with new values.\n * @param update Partial filter to merge.\n */\n setFilter(update: Partial<TFilter>) {\n const current = this.filterSubject.value;\n this.filterSubject.next({ ...current, ...update });\n }\n\n /**\n * Replaces all records in the current state.\n * @param records Array of new records.\n */\n setRecords(records: TRecord[]) {\n this.recordsSubject.next(records);\n }\n\n /**\n * Appends records to the current record list.\n * @param records Records to add.\n */\n appendRecords(records: TRecord[]) {\n this.recordsSubject.next([...this.currentRecords, ...records]);\n }\n\n /**\n * Sets the pagination metadata.\n * @param pager Metadata to use.\n */\n setPager(pager: IMultiresultMetaData) {\n this.pagerSubject.next(pager);\n }\n\n /**\n * Sets records and pager data from API response.\n * @param response API response containing records and pager.\n */\n setApiResponse(response: IMultiresult<TRecord>) {\n this.setRecords(response.records);\n this.setPager(response.pager);\n }\n\n /**\n * Updates the sort order in the current filter.\n * Toggles order if column already exists, or adds it otherwise.\n * @param column Column name to sort by.\n */\n setSort(column: string, sort: \"ASC\" | \"DESC\" = \"ASC\") {\n const current = this.filterSubject.value;\n\n let sortItems = [...(current.sort ?? [])];\n\n const index = sortItems.findIndex(item => item.field === column);\n\n if (index !== -1) {\n const currentOrder = sortItems[index].order;\n sortItems[index] = new SortItem(\n sortItems[index].field,\n currentOrder === 'ASC' ? 'DESC' : 'ASC'\n );\n } else {\n sortItems.push(new SortItem(column, sort));\n }\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Removes a specific column from the current sort.\n * @param column Column name to remove from sorting.\n */\n removeSort(column: string) {\n const current = this.filterSubject.value;\n const sortItems = [...(current.sort ?? [])].filter(item => item.field !== column);\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Clears all sorting from the current filter.\n */\n clearSort() {\n const current = this.filterSubject.value;\n\n this.filterSubject.next({\n ...current,\n sort: []\n });\n }\n\n /**\n * Sets the loading flag.\n * @param loading Whether loading is active.\n */\n setLoading(loading: boolean) {\n this.loadingSubject.next(loading);\n }\n\n /**\n * Sets the saving flag.\n * @param saving Whether a save operation is in progress.\n */\n setSaving(saving: boolean) {\n this.savingSubject.next(saving);\n }\n\n /**\n * Sets the error state.\n * @param error Error message or null.\n */\n setError(error: string | null) {\n this.errorSubject.next(error);\n }\n\n /**\n * Selects a record.\n * @param record The record to select.\n */\n select(record: TRecord) {\n this.selectedSubject.next(record);\n }\n\n /** Clears the current selection. */\n clearSelection() {\n this.selectedSubject.next(null);\n }\n\n /** Resets the entire state to initial values. */\n reset() {\n this.recordsSubject.next([]);\n this.pagerSubject.next(null);\n this.selectedSubject.next(null);\n this.setFilter({ page: 1, pageLength: 10 } as Partial<TFilter>);\n this.setLoading(false);\n this.setSaving(false);\n this.setError(null);\n }\n\n /**\n * Removes a record by its ID field.\n * @param id The ID to remove.\n * @param idKey The record property key used as ID (default: 'id').\n */\n removeRecordById(id: number | string, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(this.currentRecords.filter(r => r[idKey] !== id));\n }\n\n /**\n * Replaces a record by matching its ID field.\n * @param updated The updated record.\n * @param idKey The record property key used as ID (default: 'id').\n */\n replaceRecord(updated: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(\n this.currentRecords.map(r => r[idKey] === updated[idKey] ? updated : r)\n );\n }\n\n /**\n * Checks if a specific record is currently selected.\n * @param record Record to check.\n * @param idKey Key to use for comparison (default: 'id').\n */\n isSelected(record: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord): boolean {\n const selected = this.selectedSubject.value;\n return selected ? selected[idKey] === record[idKey] : false;\n }\n\n /**\n * Updates the current page number in the filter.\n * @param page Page number.\n */\n setPage(page: number) {\n this.setFilter({ page } as Partial<TFilter>);\n }\n\n /**\n * Updates the page length in the filter.\n * @param pageLength Number of records per page.\n */\n setPageLength(pageLength: number) {\n this.setFilter({ pageLength } as Partial<TFilter>);\n }\n\n /**\n * Resets the filter to default values.\n * @param defaults Default filter values.\n */\n resetFilter(defaults: Partial<TFilter> = { page: 1, pageLength: 10 } as Partial<TFilter>) {\n this.filterSubject.next(defaults as TFilter);\n }\n\n /** Returns true if there are more pages after the current one. */\n hasMorePages(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! < pager.lastPage!;\n }\n\n /** Returns true if a previous page exists. */\n hasPreviousPage(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! > 0;\n }\n\n /** Resets and clears all managed state. */\n destroy() {\n this.reset();\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { jsonToQueryString, isEmpty } from '../utils/query-utils';\nimport { IMultiresult, IResponse, Filter } from '../models';\n\nexport abstract class BaseService<\n T, // Full model type\n TFilter extends Partial<T> & Filter = Partial<T> & Filter, // Filter: model fields + pagination/sorting\n TCreate = Partial<T>, // DTO for create\n TUpdate = Partial<T> // DTO for update\n> {\n constructor(\n protected http: HttpClient,\n protected baseUrl: string\n ) { }\n\n getAll(filter: TFilter = {} as TFilter): Observable<IResponse<IMultiresult<T>>> {\n const clonedFilter = structuredClone(filter);\n const query = !isEmpty(filter) ? jsonToQueryString(clonedFilter) : '';\n return this.http.get<IResponse<IMultiresult<T>>>(`${this.baseUrl}${query}`);\n }\n\n getDetails(id: number): Observable<IResponse<T>> {\n return this.http.get<IResponse<T>>(`${this.baseUrl}/${id}`);\n }\n\n create(data: TCreate): Observable<IResponse<T>> {\n return this.http.post<IResponse<T>>(this.baseUrl, data);\n }\n\n update(id: number, data: TUpdate): Observable<IResponse<T>> {\n return this.http.put<IResponse<T>>(`${this.baseUrl}/${id}`, data);\n }\n\n delete(id: number, method: 'soft' | 'hard' = 'soft'): Observable<any> {\n const methodQuery = `?method=${method}`;\n if (method === 'soft') {\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`, {});\n }\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`);\n }\n}\n","/*\n * Public API Surface of api-core\n */\n\nexport * from './lib/configs';\nexport * from './lib/api-core';\nexport * from './lib/enums';\nexport * from './lib/utils';\nexport * from './lib/models';\nexport * from './lib/services';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysteryinfosolutions-api-core.mjs","sources":["../../../projects/api-core/src/lib/configs/base-resource-config.ts","../../../projects/api-core/src/lib/api-core.ts","../../../projects/api-core/src/lib/enums/selectmodes.enum.ts","../../../projects/api-core/src/lib/utils/query-utils.ts","../../../projects/api-core/src/lib/models/filter.model.ts","../../../projects/api-core/src/lib/models/sort.model.ts","../../../projects/api-core/src/lib/services/base-state.service.ts","../../../projects/api-core/src/lib/services/base.service.ts","../../../projects/api-core/src/public-api.ts","../../../projects/api-core/src/mysteryinfosolutions-api-core.ts"],"sourcesContent":["// base-resource-config.ts\nimport { TableColumn } from \"../models\";\n\n/**\n * BaseResourceConfig<T>\n *\n * A generic configuration class to standardize table-based resource UIs.\n * Extend this in feature modules (e.g., Users, Roles, Genders) to reuse core settings.\n */\nexport abstract class BaseResourceConfig<T> {\n /**\n * Table columns definition for the resource.\n */\n columns: TableColumn<T>[] = [];\n\n /**\n * The column used for date-range filtering (e.g., in filters or reporting).\n */\n dateRangeColumn: keyof T | string = 'updated_at';\n\n /**\n * Default column used to sort the table data.\n */\n defaultSortColumn: keyof T | string = 'updated_at';\n\n /**\n * Default sorting order (ASC or DESC).\n */\n defaultSortOrder: 'ASC' | 'DESC' = 'DESC';\n\n /**\n * Page size options for the table paginator.\n */\n pageLengthOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Default page size.\n */\n defaultPageLength: number = 10;\n\n /**\n * Keys (fields) to apply search filter on.\n */\n searchColumns: (keyof T | string)[] = [];\n\n /**\n * Modal configuration: size for the create/update (modify) modal.\n */\n modifyModalSize: 'sm' | 'md' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for modify modal.\n */\n modifyModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Modal configuration: size for the view/summary modal.\n */\n summaryModalSize: 'sm' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for summary modal.\n */\n summaryModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Determines the default view when viewing details of a record.\n * 'overview' = navigates to a new page\n * 'summary' = opens a modal with summary component\n */\n defaultDetailView: 'overview' | 'summary' = 'summary';\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-api-core',\n imports: [],\n template: `\n <p>\n api-core works!\n </p>\n `,\n styles: ``\n})\nexport class ApiCore {\n\n}\n","export enum SELECT_MODE {\n ALL = 1,\n ONLYCOLUMNS = 2,\n};\n","import { SortItem } from '../models';\n\nexport const sortObjectToString = (sortItems: SortItem[]): string => {\n if (!Array.isArray(sortItems) || sortItems.length === 0) return '';\n return sortItems.map(s => `${s.field}:${s.order}`).join(',');\n};\n\nexport const jsonToQueryString = (json: any): string => {\n if (!json || typeof json !== 'object') return '';\n\n if (json.hasOwnProperty('sort')) {\n json.sort = sortObjectToString(json.sort);\n }\n\n const queryArray = Object.keys(json)\n .filter(key => json[key] !== undefined && json[key] !== null)\n .map(key => {\n if (Array.isArray(json[key])) {\n return `${encodeURIComponent(key)}=${encodeURIComponent('[' + json[key].toString() + ']')}`;\n } else {\n return `${encodeURIComponent(key)}=${encodeURIComponent(json[key])}`;\n }\n });\n\n return queryArray.length > 0 ? `?${queryArray.join('&')}` : '';\n};\n\nexport const isEmpty = (obj: any): boolean => {\n return !obj || Object.keys(obj).length === 0;\n};\n","import { SortItem } from './';\nimport { SELECT_MODE } from '../enums';\n\nexport abstract class Filter {\n dateRangeColumn?: string;\n dateRangeFrom?: string;\n dateRangeTo?: string;\n\n page?: number = 1;\n pageLength?: number = 10;\n\n sort?: SortItem[] = [];\n\n search?: string;\n searchColumns?: string;\n selectColumns?: string;\n selectMode?: SELECT_MODE;\n}","export class SortItem {\n constructor(\n public field: string,\n public order: 'ASC' | 'DESC'\n ) {}\n}\n\n","import { BehaviorSubject, map, Observable } from \"rxjs\";\nimport { Filter, IMultiresult, IMultiresultMetaData, SortItem } from \"../models\";\n\n/**\n * A generic state management service for handling filters, pagination, and records.\n */\nexport class BaseStateService<\n TRecord,\n TFilter extends Partial<TRecord> & Filter = Partial<TRecord> & Filter\n> {\n private readonly filterSubject = new BehaviorSubject<TFilter>({ page: 1, pageLength: 10 } as TFilter);\n private readonly recordsSubject = new BehaviorSubject<TRecord[]>([]);\n private readonly pagerSubject = new BehaviorSubject<IMultiresultMetaData | null>(null);\n private readonly selectedSubject = new BehaviorSubject<TRecord | null>(null);\n private readonly loadingMapSubject = new BehaviorSubject<Record<string, boolean>>({});\n private readonly savingSubject = new BehaviorSubject<boolean>(false);\n private readonly errorSubject = new BehaviorSubject<string | null>(null);\n\n /** Observable stream of current filter. */\n filter$ = this.filterSubject.asObservable();\n\n /** Observable stream of current records. */\n records$ = this.recordsSubject.asObservable();\n\n /** Observable stream of current pager metadata. */\n pager$ = this.pagerSubject.asObservable();\n\n /** Observable stream of the currently selected record. */\n selected$ = this.selectedSubject.asObservable();\n\n /** Observable stream of loading state. */\n loading$ = this.loadingMapSubject.asObservable();\n\n /** Observable stream of saving state. */\n saving$ = this.savingSubject.asObservable();\n\n /** Observable stream of current error message. */\n error$ = this.errorSubject.asObservable();\n\n /** Returns the current filter. */\n get currentFilter(): TFilter {\n return this.filterSubject.value;\n }\n\n /** Returns the currently loaded records. */\n get currentRecords(): TRecord[] {\n return this.recordsSubject.value;\n }\n\n /** Returns the currently selected record, if any. */\n get selected(): TRecord | null {\n return this.selectedSubject.value;\n }\n\n /**\n * Updates the current filter with new values.\n * @param update Partial filter to merge.\n */\n setFilter(update: Partial<TFilter>) {\n const current = this.filterSubject.value;\n this.filterSubject.next({ ...current, ...update });\n }\n\n /**\n * Replaces all records in the current state.\n * @param records Array of new records.\n */\n setRecords(records: TRecord[]) {\n this.recordsSubject.next(records);\n }\n\n /**\n * Appends records to the current record list.\n * @param records Records to add.\n */\n appendRecords(records: TRecord[]) {\n this.recordsSubject.next([...this.currentRecords, ...records]);\n }\n\n /**\n * Sets the pagination metadata.\n * @param pager Metadata to use.\n */\n setPager(pager: IMultiresultMetaData) {\n this.pagerSubject.next(pager);\n }\n\n /**\n * Sets records and pager data from API response.\n * @param response API response containing records and pager.\n */\n setApiResponse(response: IMultiresult<TRecord>) {\n this.setRecords(response.records);\n this.setPager(response.pager);\n }\n\n /**\n * Updates the sort order in the current filter.\n * Toggles order if column already exists, or adds it otherwise.\n * @param column Column name to sort by.\n */\n setSort(column: string, sort: \"ASC\" | \"DESC\" = \"ASC\") {\n const current = this.filterSubject.value;\n\n let sortItems = [...(current.sort ?? [])];\n\n const index = sortItems.findIndex(item => item.field === column);\n\n if (index !== -1) {\n const currentOrder = sortItems[index].order;\n sortItems[index] = new SortItem(\n sortItems[index].field,\n currentOrder === 'ASC' ? 'DESC' : 'ASC'\n );\n } else {\n sortItems.push(new SortItem(column, sort));\n }\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Removes a specific column from the current sort.\n * @param column Column name to remove from sorting.\n */\n removeSort(column: string) {\n const current = this.filterSubject.value;\n const sortItems = [...(current.sort ?? [])].filter(item => item.field !== column);\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Clears all sorting from the current filter.\n */\n clearSort() {\n const current = this.filterSubject.value;\n\n this.filterSubject.next({\n ...current,\n sort: []\n });\n }\n\n /**\n * Returns an observable boolean for a specific loading key.\n * Useful for tracking loading state in a specific view or feature.\n *\n * @param key A unique key representing the loading context (e.g., \"list\", \"detail\")\n * @returns Observable emitting `true` if the given context is loading, `false` otherwise.\n */\n isLoading$(key: string): Observable<boolean> {\n return this.loading$.pipe(map(state => !!state[key]));\n }\n\n /**\n * Sets the loading state for a specific key.\n * This allows you to control multiple concurrent loading states independently.\n *\n * @param key The loading context name (e.g., \"list\", \"form\", \"detail\")\n * @param value The loading status (`true` for loading, `false` for done)\n */\n setLoading(key: string, value: boolean): void {\n const current = this.loadingMapSubject.value;\n this.loadingMapSubject.next({ ...current, [key]: value });\n }\n\n /**\n * Sets the saving flag.\n * @param saving Whether a save operation is in progress.\n */\n setSaving(saving: boolean) {\n this.savingSubject.next(saving);\n }\n\n /**\n * Sets the error state.\n * @param error Error message or null.\n */\n setError(error: string | null) {\n this.errorSubject.next(error);\n }\n\n /**\n * Selects a record.\n * @param record The record to select.\n */\n select(record: TRecord) {\n this.selectedSubject.next(record);\n }\n\n /** Clears the current selection. */\n clearSelection() {\n this.selectedSubject.next(null);\n }\n\n /**\n * Clears the loading state for a specific key or all keys if none is provided.\n *\n * @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.\n */\n clearLoading(key?: string): void {\n if (key) {\n const { [key]: _, ...rest } = this.loadingMapSubject.value;\n this.loadingMapSubject.next(rest);\n } else {\n this.loadingMapSubject.next({});\n }\n }\n\n /** Resets the entire state to initial values. */\n reset() {\n this.recordsSubject.next([]);\n this.pagerSubject.next(null);\n this.selectedSubject.next(null);\n this.setFilter({ page: 1, pageLength: 10 } as Partial<TFilter>);\n this.clearLoading();\n this.setSaving(false);\n this.setError(null);\n }\n\n /**\n * Removes a record by its ID field.\n * @param id The ID to remove.\n * @param idKey The record property key used as ID (default: 'id').\n */\n removeRecordById(id: number | string, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(this.currentRecords.filter(r => r[idKey] !== id));\n }\n\n /**\n * Replaces a record by matching its ID field.\n * @param updated The updated record.\n * @param idKey The record property key used as ID (default: 'id').\n */\n replaceRecord(updated: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(\n this.currentRecords.map(r => r[idKey] === updated[idKey] ? updated : r)\n );\n }\n\n /**\n * Checks if a specific record is currently selected.\n * @param record Record to check.\n * @param idKey Key to use for comparison (default: 'id').\n */\n isSelected(record: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord): boolean {\n const selected = this.selectedSubject.value;\n return selected ? selected[idKey] === record[idKey] : false;\n }\n\n /**\n * Updates the current page number in the filter.\n * @param page Page number.\n */\n setPage(page: number) {\n this.setFilter({ page } as Partial<TFilter>);\n }\n\n /**\n * Updates the page length in the filter.\n * @param pageLength Number of records per page.\n */\n setPageLength(pageLength: number) {\n this.setFilter({ pageLength } as Partial<TFilter>);\n }\n\n /**\n * Resets the filter to default values.\n * @param defaults Default filter values.\n */\n resetFilter(defaults: Partial<TFilter> = { page: 1, pageLength: 10 } as Partial<TFilter>) {\n this.filterSubject.next(defaults as TFilter);\n }\n\n /** Returns true if there are more pages after the current one. */\n hasMorePages(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! < pager.lastPage!;\n }\n\n /** Returns true if a previous page exists. */\n hasPreviousPage(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! > 0;\n }\n\n /** Resets and clears all managed state. */\n destroy() {\n this.reset();\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { jsonToQueryString, isEmpty } from '../utils/query-utils';\nimport { IMultiresult, IResponse, Filter } from '../models';\n\nexport abstract class BaseService<\n T, // Full model type\n TFilter extends Partial<T> & Filter = Partial<T> & Filter, // Filter: model fields + pagination/sorting\n TCreate = Partial<T>, // DTO for create\n TUpdate = Partial<T> // DTO for update\n> {\n constructor(\n protected http: HttpClient,\n protected baseUrl: string\n ) { }\n\n getAll(filter: TFilter = {} as TFilter): Observable<IResponse<IMultiresult<T>>> {\n const clonedFilter = structuredClone(filter);\n const query = !isEmpty(filter) ? jsonToQueryString(clonedFilter) : '';\n return this.http.get<IResponse<IMultiresult<T>>>(`${this.baseUrl}${query}`);\n }\n\n getDetails(id: number): Observable<IResponse<T>> {\n return this.http.get<IResponse<T>>(`${this.baseUrl}/${id}`);\n }\n\n create(data: TCreate): Observable<IResponse<T>> {\n return this.http.post<IResponse<T>>(this.baseUrl, data);\n }\n\n update(id: number, data: TUpdate): Observable<IResponse<T>> {\n return this.http.put<IResponse<T>>(`${this.baseUrl}/${id}`, data);\n }\n\n delete(id: number, method: 'soft' | 'hard' = 'soft'): Observable<any> {\n const methodQuery = `?method=${method}`;\n if (method === 'soft') {\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`, {});\n }\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`);\n }\n}\n","/*\n * Public API Surface of api-core\n */\n\nexport * from './lib/configs';\nexport * from './lib/api-core';\nexport * from './lib/enums';\nexport * from './lib/utils';\nexport * from './lib/models';\nexport * from './lib/services';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import * as rxjs from 'rxjs';
|
|
3
2
|
import { Observable } from 'rxjs';
|
|
4
3
|
import { HttpClient } from '@angular/common/http';
|
|
5
4
|
|
|
@@ -147,23 +146,23 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
147
146
|
private readonly recordsSubject;
|
|
148
147
|
private readonly pagerSubject;
|
|
149
148
|
private readonly selectedSubject;
|
|
150
|
-
private readonly
|
|
149
|
+
private readonly loadingMapSubject;
|
|
151
150
|
private readonly savingSubject;
|
|
152
151
|
private readonly errorSubject;
|
|
153
152
|
/** Observable stream of current filter. */
|
|
154
|
-
filter$:
|
|
153
|
+
filter$: Observable<TFilter>;
|
|
155
154
|
/** Observable stream of current records. */
|
|
156
|
-
records$:
|
|
155
|
+
records$: Observable<TRecord[]>;
|
|
157
156
|
/** Observable stream of current pager metadata. */
|
|
158
|
-
pager$:
|
|
157
|
+
pager$: Observable<IMultiresultMetaData | null>;
|
|
159
158
|
/** Observable stream of the currently selected record. */
|
|
160
|
-
selected$:
|
|
159
|
+
selected$: Observable<TRecord | null>;
|
|
161
160
|
/** Observable stream of loading state. */
|
|
162
|
-
loading$:
|
|
161
|
+
loading$: Observable<Record<string, boolean>>;
|
|
163
162
|
/** Observable stream of saving state. */
|
|
164
|
-
saving$:
|
|
163
|
+
saving$: Observable<boolean>;
|
|
165
164
|
/** Observable stream of current error message. */
|
|
166
|
-
error$:
|
|
165
|
+
error$: Observable<string | null>;
|
|
167
166
|
/** Returns the current filter. */
|
|
168
167
|
get currentFilter(): TFilter;
|
|
169
168
|
/** Returns the currently loaded records. */
|
|
@@ -211,10 +210,21 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
211
210
|
*/
|
|
212
211
|
clearSort(): void;
|
|
213
212
|
/**
|
|
214
|
-
*
|
|
215
|
-
*
|
|
213
|
+
* Returns an observable boolean for a specific loading key.
|
|
214
|
+
* Useful for tracking loading state in a specific view or feature.
|
|
215
|
+
*
|
|
216
|
+
* @param key A unique key representing the loading context (e.g., "list", "detail")
|
|
217
|
+
* @returns Observable emitting `true` if the given context is loading, `false` otherwise.
|
|
216
218
|
*/
|
|
217
|
-
|
|
219
|
+
isLoading$(key: string): Observable<boolean>;
|
|
220
|
+
/**
|
|
221
|
+
* Sets the loading state for a specific key.
|
|
222
|
+
* This allows you to control multiple concurrent loading states independently.
|
|
223
|
+
*
|
|
224
|
+
* @param key The loading context name (e.g., "list", "form", "detail")
|
|
225
|
+
* @param value The loading status (`true` for loading, `false` for done)
|
|
226
|
+
*/
|
|
227
|
+
setLoading(key: string, value: boolean): void;
|
|
218
228
|
/**
|
|
219
229
|
* Sets the saving flag.
|
|
220
230
|
* @param saving Whether a save operation is in progress.
|
|
@@ -232,6 +242,12 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
232
242
|
select(record: TRecord): void;
|
|
233
243
|
/** Clears the current selection. */
|
|
234
244
|
clearSelection(): void;
|
|
245
|
+
/**
|
|
246
|
+
* Clears the loading state for a specific key or all keys if none is provided.
|
|
247
|
+
*
|
|
248
|
+
* @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.
|
|
249
|
+
*/
|
|
250
|
+
clearLoading(key?: string): void;
|
|
235
251
|
/** Resets the entire state to initial values. */
|
|
236
252
|
reset(): void;
|
|
237
253
|
/**
|