ng-qubee 1.0.11 → 2.0.2

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.
Files changed (71) hide show
  1. package/README.md +90 -67
  2. package/esm2022/lib/enums/sort.enum.mjs +6 -0
  3. package/esm2022/lib/errors/key-not-found.error.mjs +6 -0
  4. package/esm2022/lib/errors/unselectable-model.error.mjs +6 -0
  5. package/esm2022/lib/interfaces/config.interface.mjs +2 -0
  6. package/esm2022/lib/interfaces/fields.interface.mjs +2 -0
  7. package/esm2022/lib/interfaces/filters.interface.mjs +2 -0
  8. package/esm2022/lib/interfaces/normalized.interface.mjs +2 -0
  9. package/esm2022/lib/interfaces/paginated-object.interface.mjs +2 -0
  10. package/esm2022/lib/interfaces/pagination-config.interface.mjs +2 -0
  11. package/esm2022/lib/interfaces/query-builder-config.interface.mjs +2 -0
  12. package/esm2022/lib/interfaces/query-builder-state.interface.mjs +2 -0
  13. package/esm2022/lib/interfaces/sort.interface.mjs +2 -0
  14. package/esm2022/lib/models/paginated-collection.mjs +47 -0
  15. package/esm2022/lib/models/query-builder-options.mjs +12 -0
  16. package/esm2022/lib/models/response-options.mjs +17 -0
  17. package/esm2022/lib/ng-qubee.module.mjs +42 -0
  18. package/esm2022/lib/provide-ngqubee.mjs +39 -0
  19. package/esm2022/lib/services/nest.service.mjs +173 -0
  20. package/esm2022/lib/services/ng-qubee.service.mjs +319 -0
  21. package/esm2022/lib/services/pagination.service.mjs +23 -0
  22. package/esm2022/ng-qubee.mjs +5 -0
  23. package/esm2022/public-api.mjs +9 -0
  24. package/{fesm2015/ng-qubee.js → fesm2022/ng-qubee.mjs} +369 -217
  25. package/fesm2022/ng-qubee.mjs.map +1 -0
  26. package/index.d.ts +5 -0
  27. package/lib/interfaces/normalized.interface.d.ts +3 -0
  28. package/lib/interfaces/paginated-object.interface.d.ts +3 -0
  29. package/lib/interfaces/query-builder-state.interface.d.ts +1 -2
  30. package/lib/interfaces/sort.interface.d.ts +2 -1
  31. package/lib/models/paginated-collection.d.ts +18 -16
  32. package/lib/ng-qubee.module.d.ts +4 -1
  33. package/lib/provide-ngqubee.d.ts +21 -0
  34. package/lib/services/nest.service.d.ts +81 -0
  35. package/lib/{ng-qubee.service.d.ts → services/ng-qubee.service.d.ts} +30 -8
  36. package/lib/services/pagination.service.d.ts +5 -1
  37. package/package.json +20 -18
  38. package/public-api.d.ts +3 -2
  39. package/bundles/ng-qubee.umd.js +0 -927
  40. package/bundles/ng-qubee.umd.js.map +0 -1
  41. package/bundles/ng-qubee.umd.min.js +0 -16
  42. package/bundles/ng-qubee.umd.min.js.map +0 -1
  43. package/esm2015/lib/actions/query-builder.actions.js +0 -17
  44. package/esm2015/lib/enums/sort.enum.js +0 -6
  45. package/esm2015/lib/errors/key-not-found.error.js +0 -6
  46. package/esm2015/lib/errors/unselectable-model.error.js +0 -6
  47. package/esm2015/lib/interfaces/config.interface.js +0 -2
  48. package/esm2015/lib/interfaces/fields.interface.js +0 -2
  49. package/esm2015/lib/interfaces/filters.interface.js +0 -2
  50. package/esm2015/lib/interfaces/nest-state.interface.js +0 -2
  51. package/esm2015/lib/interfaces/pagination-config.interface.js +0 -2
  52. package/esm2015/lib/interfaces/query-builder-config.interface.js +0 -2
  53. package/esm2015/lib/interfaces/query-builder-state.interface.js +0 -2
  54. package/esm2015/lib/interfaces/sort.interface.js +0 -2
  55. package/esm2015/lib/models/paginated-collection.js +0 -45
  56. package/esm2015/lib/models/query-builder-options.js +0 -12
  57. package/esm2015/lib/models/response-options.js +0 -17
  58. package/esm2015/lib/ng-qubee.module.js +0 -33
  59. package/esm2015/lib/ng-qubee.service.js +0 -298
  60. package/esm2015/lib/reducers/query-builder.reducer.js +0 -51
  61. package/esm2015/lib/services/pagination.service.js +0 -18
  62. package/esm2015/lib/services/store.service.js +0 -26
  63. package/esm2015/ng-qubee.js +0 -6
  64. package/esm2015/public-api.js +0 -8
  65. package/fesm2015/ng-qubee.js.map +0 -1
  66. package/lib/actions/query-builder.actions.d.ts +0 -43
  67. package/lib/interfaces/nest-state.interface.d.ts +0 -4
  68. package/lib/reducers/query-builder.reducer.d.ts +0 -2
  69. package/lib/services/store.service.d.ts +0 -9
  70. package/ng-qubee.d.ts +0 -7
  71. package/ng-qubee.metadata.json +0 -1
@@ -1,25 +1,57 @@
1
- import { ɵɵdefineInjectable, Injectable, Inject, Optional, NgModule } from '@angular/core';
2
- import { stringify } from 'qs';
3
- import { createAction, createReducer } from '@reduxjs/toolkit';
4
- import { BehaviorSubject } from 'rxjs';
5
- import { filter } from 'rxjs/operators';
6
- import { createStore, combineReducers } from 'redux';
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, Injectable, Inject, Optional, NgModule, makeEnvironmentProviders } from '@angular/core';
3
+ import * as qs from 'qs';
4
+ import { BehaviorSubject, filter } from 'rxjs';
7
5
 
8
- class QueryBuilderOptions {
9
- constructor(options) {
10
- this.appends = options.appends || 'append';
11
- this.fields = options.fields || 'fields';
12
- this.filters = options.filters || 'filter';
13
- this.includes = options.includes || 'include';
14
- this.limit = options.limit || 'limit';
15
- this.page = options.page || 'page';
16
- this.sort = options.sort || 'sort';
6
+ class KeyNotFoundError extends Error {
7
+ constructor(key) {
8
+ super(`Cannot find the key ${key} inside the collection item: does it really exists?`);
17
9
  }
18
10
  }
19
11
 
20
- class UnselectableModelError extends Error {
21
- constructor(model) {
22
- super(`Unselectable Model: the selected model (${model}) is not present neither in the "model" property, nor in the includes object.`);
12
+ class PaginatedCollection {
13
+ constructor(data, page, from, to, total, perPage, prevPageUrl, nextPageUrl, lastPage, firstPageUrl, lastPageUrl) {
14
+ this.data = data;
15
+ this.page = page;
16
+ this.from = from;
17
+ this.to = to;
18
+ this.total = total;
19
+ this.perPage = perPage;
20
+ this.prevPageUrl = prevPageUrl;
21
+ this.nextPageUrl = nextPageUrl;
22
+ this.lastPage = lastPage;
23
+ this.firstPageUrl = firstPageUrl;
24
+ this.lastPageUrl = lastPageUrl;
25
+ //
26
+ }
27
+ /**
28
+ * Normalize the collection to a paginated list of ids for state-managed applications.
29
+ *
30
+ * This method returns a single key object, where the key is the page number and the associated value is
31
+ * an array of ids. Each id is fetched by the collection items, looking up for the "id" key. If an id is supplied
32
+ * to this method, it will be used instead of the default "id" key.
33
+ *
34
+ * Please note that in case the key doesn't exist in the collection's item, a KeyNotFoundError is thrown
35
+ *
36
+ * @param k A key to use instead of the default "id": this will be searched inside each element of the collection
37
+ * @returns []
38
+ * @throws KeyNotFoundItem
39
+ */
40
+ normalize(id) {
41
+ return {
42
+ [this.page]: this.data.reduce((ids, value) => {
43
+ if (id && id in value) {
44
+ ids.push(value[id]);
45
+ }
46
+ else if (value.hasOwnProperty('id')) {
47
+ ids.push(value['id']);
48
+ }
49
+ else {
50
+ throw new KeyNotFoundError(id || 'id');
51
+ }
52
+ return ids;
53
+ }, [])
54
+ };
23
55
  }
24
56
  }
25
57
 
@@ -29,23 +61,25 @@ var SortEnum;
29
61
  SortEnum["DESC"] = "desc";
30
62
  })(SortEnum || (SortEnum = {}));
31
63
 
32
- // Interfaces
33
- const addFields = createAction('[Query Buillder] Add Fields');
34
- const addFilters = createAction('[Query Buillder] Add Filters');
35
- const addIncludes = createAction('[Query Buillder] Add Includes');
36
- const addSorts = createAction('[Query Buillder] Add Sorts');
37
- const deleteFields = createAction('[Query Buillder] Delete Fields');
38
- const deleteFilters = createAction('[Query Buillder] Delete Filters');
39
- const deleteIncludes = createAction('[Query Buillder] Delete Includes');
40
- const deleteSorts = createAction('[Query Buillder] Delete Sorts');
41
- const reset = createAction('[Query Builder] Reset');
42
- const setBaseUrl = createAction('[Query Buillder] Set Base URL');
43
- const setLimit = createAction('[Query Buillder] Set Limit');
44
- const setModel = createAction('[Query Builder] Set Model');
45
- const setPage = createAction('[Query Builder] Set Page');
46
- const updateUri = createAction('[Query Builder] Update URI');
64
+ class UnselectableModelError extends Error {
65
+ constructor(model) {
66
+ super(`Unselectable Model: the selected model (${model}) is not present neither in the "model" property, nor in the includes object.`);
67
+ }
68
+ }
47
69
 
48
- const initialState = {
70
+ class QueryBuilderOptions {
71
+ constructor(options) {
72
+ this.appends = options.appends || 'append';
73
+ this.fields = options.fields || 'fields';
74
+ this.filters = options.filters || 'filter';
75
+ this.includes = options.includes || 'include';
76
+ this.limit = options.limit || 'limit';
77
+ this.page = options.page || 'page';
78
+ this.sort = options.sort || 'sort';
79
+ }
80
+ }
81
+
82
+ const INITIAL_STATE = {
49
83
  baseUrl: '',
50
84
  fields: {},
51
85
  filters: {},
@@ -53,71 +87,172 @@ const initialState = {
53
87
  limit: 15,
54
88
  model: '',
55
89
  page: 1,
56
- sort: {},
57
- uri: ''
58
- };
59
- const ɵ0 = builder => {
60
- builder.addCase(addFields, (state, { payload: { fields } }) => (Object.assign(Object.assign({}, state), { fields: Object.assign(Object.assign({}, state.fields), fields) }))),
61
- builder.addCase(addFilters, (state, { payload: { filters } }) => (Object.assign(Object.assign({}, state), { filters: Object.assign(Object.assign({}, state.filters), filters) }))),
62
- builder.addCase(addIncludes, (state, { payload: { includes } }) => (Object.assign(Object.assign({}, state), { includes: [...state.includes, ...includes] }))),
63
- builder.addCase(addSorts, (state, { payload: { sorts } }) => (Object.assign(Object.assign({}, state), { sort: Object.assign(Object.assign({}, state.sort), sorts) }))),
64
- builder.addCase(deleteFields, (state, { payload: { fields } }) => {
65
- const f = Object.assign({}, state.fields);
66
- Object.keys(fields).forEach(k => {
67
- if (!(k in state.fields)) {
68
- return;
69
- }
70
- f[k] = state.fields[k].filter(v => !fields[k].includes(v));
71
- });
72
- return Object.assign(Object.assign({}, state), { fields: f });
73
- }),
74
- builder.addCase(deleteFilters, (state, { payload: { filters } }) => {
75
- const f = Object.assign({}, state.filters);
76
- filters.forEach(k => delete f[k]);
77
- return Object.assign(Object.assign({}, state), { filters: f });
78
- }),
79
- builder.addCase(deleteIncludes, (state, { payload: { includes } }) => {
80
- return Object.assign(Object.assign({}, state), { includes: state.includes.filter(v => !includes.includes(v)) });
81
- }),
82
- builder.addCase(deleteSorts, (state, { payload: { sorts } }) => {
83
- const s = Object.assign({}, state.sort);
84
- sorts.forEach(v => delete s[v]);
85
- return Object.assign(Object.assign({}, state), { sort: s });
86
- }),
87
- builder.addCase(reset, state => initialState),
88
- builder.addCase(setBaseUrl, (state, { payload: { baseUrl } }) => (Object.assign(Object.assign({}, state), { baseUrl }))),
89
- builder.addCase(setLimit, (state, { payload: { limit } }) => (Object.assign(Object.assign({}, state), { limit }))),
90
- builder.addCase(setModel, (state, { payload: { model } }) => (Object.assign(Object.assign({}, state), { model }))),
91
- builder.addCase(setPage, (state, { payload: { page } }) => (Object.assign(Object.assign({}, state), { page }))),
92
- builder.addCase(updateUri, (state, { payload: { uri } }) => (Object.assign(Object.assign({}, state), { uri })));
90
+ sorts: []
93
91
  };
94
- const queryBuilderReducer = createReducer(initialState, ɵ0);
95
-
96
- class StoreService {
92
+ class NestService {
97
93
  constructor() {
98
- this._store = createStore(combineReducers({ nest: queryBuilderReducer }));
94
+ /**
95
+ * Private writable signal that holds the Query Builder state
96
+ *
97
+ * @type {IQueryBuilderState}
98
+ */
99
+ this._nest = signal(this._clone(INITIAL_STATE));
100
+ /**
101
+ * A computed signal that makes readonly the writable signal _nest
102
+ *
103
+ * @type {Signal<IQueryBuilderState>}
104
+ */
105
+ this.nest = computed(() => this._clone(this._nest()));
106
+ // Nothing to see here 👮🏻‍♀️
99
107
  }
100
- get state() {
101
- return this._store.getState();
108
+ set baseUrl(baseUrl) {
109
+ this._nest.update(nest => ({
110
+ ...nest,
111
+ baseUrl
112
+ }));
102
113
  }
103
- dispatch(action) {
104
- this._store.dispatch(action);
114
+ set limit(limit) {
115
+ this._nest.update(nest => ({
116
+ ...nest,
117
+ limit
118
+ }));
105
119
  }
106
- subscribe(listener) {
107
- this._store.subscribe(listener);
120
+ set model(model) {
121
+ this._nest.update(nest => ({
122
+ ...nest,
123
+ model
124
+ }));
108
125
  }
126
+ set page(page) {
127
+ this._nest.update(nest => ({
128
+ ...nest,
129
+ page
130
+ }));
131
+ }
132
+ _clone(obj) {
133
+ return JSON.parse(JSON.stringify(obj));
134
+ }
135
+ /**
136
+ * Add selectable fields for the given model to the request
137
+ *
138
+ * @param {IFields} fields
139
+ * @return {void}
140
+ * @todo Avoid duplicated fields
141
+ */
142
+ addFields(fields) {
143
+ this._nest.update(nest => ({
144
+ ...nest,
145
+ fields: { ...nest.fields, ...fields }
146
+ }));
147
+ }
148
+ /**
149
+ * Add filters to the request
150
+ *
151
+ * @param {IFilters} filters
152
+ * @todo Avoid duplicated filters
153
+ */
154
+ addFilters(filters) {
155
+ this._nest.update(nest => ({
156
+ ...nest,
157
+ filters: { ...nest.filters, ...filters }
158
+ }));
159
+ }
160
+ /**
161
+ * Add resources to include with the request
162
+ *
163
+ * @param {string[]} includes models to include to the request
164
+ * @return {void}
165
+ * @todo Avoid duplicated includes
166
+ */
167
+ addIncludes(includes) {
168
+ this._nest.update(nest => ({
169
+ ...nest,
170
+ includes: [...nest.includes, ...includes]
171
+ }));
172
+ }
173
+ /**
174
+ * Add a field that should be used for sorting data
175
+ *
176
+ * @param {ISort} sort
177
+ * @return {void}
178
+ */
179
+ addSort(sort) {
180
+ this._nest.update(nest => ({
181
+ ...nest,
182
+ sorts: [...nest.sorts, sort]
183
+ }));
184
+ }
185
+ /**
186
+ * Remove fields for the given model
187
+ *
188
+ * @param {IFields} fields
189
+ */
190
+ deleteFields(fields) {
191
+ const f = Object.assign({}, this.nest().fields);
192
+ Object.keys(fields).forEach(k => {
193
+ if (!(k in f)) {
194
+ return;
195
+ }
196
+ f[k] = this._nest().fields[k].filter(v => !fields[k].includes(v));
197
+ });
198
+ this._nest.update(nest => ({
199
+ ...nest,
200
+ fields: f
201
+ }));
202
+ }
203
+ /**
204
+ *
205
+ * @param filters
206
+ * @todo Create a clone of the filter obj before assigning to f
207
+ */
208
+ deleteFilters(...filters) {
209
+ const f = Object.assign({}, this._nest().filters);
210
+ filters.forEach(k => delete f[k]);
211
+ this._nest.update(nest => ({
212
+ ...nest,
213
+ filters: f
214
+ }));
215
+ }
216
+ /**
217
+ *
218
+ * @param includes
219
+ */
220
+ deleteIncludes(...includes) {
221
+ this._nest.update(nest => ({
222
+ ...nest,
223
+ includes: nest.includes.filter(v => !includes.includes(v))
224
+ }));
225
+ }
226
+ /**
227
+ *
228
+ * @param sorts
229
+ */
230
+ deleteSorts(...sorts) {
231
+ const s = [...this._nest().sorts];
232
+ sorts.forEach(field => {
233
+ const p = this.nest().sorts.findIndex(sort => sort.field === field);
234
+ if (p > -1) {
235
+ s.splice(p, 1);
236
+ }
237
+ });
238
+ this._nest.update(nest => ({
239
+ ...nest,
240
+ sorts: s
241
+ }));
242
+ }
243
+ reset() {
244
+ this._nest.update(_ => this._clone(INITIAL_STATE));
245
+ }
246
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NestService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
247
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NestService }); }
109
248
  }
110
- StoreService.ɵprov = ɵɵdefineInjectable({ factory: function StoreService_Factory() { return new StoreService(); }, token: StoreService, providedIn: "root" });
111
- StoreService.decorators = [
112
- { type: Injectable, args: [{
113
- providedIn: 'root'
114
- },] }
115
- ];
116
- StoreService.ctorParameters = () => [];
249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NestService, decorators: [{
250
+ type: Injectable
251
+ }], ctorParameters: () => [] });
117
252
 
118
253
  class NgQubeeService {
119
- constructor(_store, options = {}) {
120
- this._store = _store;
254
+ constructor(_nestService, options = {}) {
255
+ this._nestService = _nestService;
121
256
  /**
122
257
  * This property serves as an accumulator for holding the composed string with each query param
123
258
  */
@@ -125,9 +260,6 @@ class NgQubeeService {
125
260
  this._uri$ = new BehaviorSubject('');
126
261
  this.uri$ = this._uri$.asObservable().pipe(filter(uri => !!uri));
127
262
  this._options = new QueryBuilderOptions(options);
128
- this._store.subscribe(() => {
129
- this._uri$.next(this._store.state.nest.uri);
130
- });
131
263
  }
132
264
  _parseFields(s) {
133
265
  if (!Object.keys(s.fields).length) {
@@ -150,7 +282,7 @@ class NgQubeeService {
150
282
  Object.assign(f, { [`${this._options.fields}[${k}]`]: s.fields[k].join(',') });
151
283
  }
152
284
  }
153
- const param = `${this._prepend(s.model)}${stringify(f, { encode: false })}`;
285
+ const param = `${this._prepend(s.model)}${qs.stringify(f, { encode: false })}`;
154
286
  this._uri += param;
155
287
  return param;
156
288
  }
@@ -160,11 +292,11 @@ class NgQubeeService {
160
292
  return this._uri;
161
293
  }
162
294
  const f = {
163
- [this._options.filters]: keys.reduce((acc, key) => {
295
+ [`${this._options.filters}`]: keys.reduce((acc, key) => {
164
296
  return Object.assign(acc, { [key]: s.filters[key].join(',') });
165
297
  }, {})
166
298
  };
167
- const param = `${this._prepend(s.model)}${stringify(f, { encode: false })}`;
299
+ const param = `${this._prepend(s.model)}${qs.stringify(f, { encode: false })}`;
168
300
  this._uri += param;
169
301
  return param;
170
302
  }
@@ -188,14 +320,13 @@ class NgQubeeService {
188
320
  }
189
321
  _parseSort(s) {
190
322
  let param = '';
191
- const fields = Object.keys(s.sort);
192
- if (!fields.length) {
323
+ if (!s.sorts.length) {
193
324
  return param;
194
325
  }
195
326
  param = `${this._prepend(s.model)}${this._options.sort}=`;
196
- fields.forEach((field, idx) => {
197
- param += `${s.sort[field] === SortEnum.DESC ? '-' : ''}${field}`;
198
- if (idx < fields.length - 1) {
327
+ s.sorts.forEach((sort, idx) => {
328
+ param += `${sort.order === SortEnum.DESC ? '-' : ''}${sort.field}`;
329
+ if (idx < s.sorts.length - 1) {
199
330
  param += ',';
200
331
  }
201
332
  });
@@ -206,17 +337,25 @@ class NgQubeeService {
206
337
  if (!s.model) {
207
338
  throw new Error('Set the model property BEFORE adding filters or calling the url() / get() methods');
208
339
  }
340
+ // Cleanup the previously generated URI
341
+ this._uri = '';
209
342
  this._parseIncludes(s);
210
343
  this._parseFields(s);
211
344
  this._parseFilters(s);
212
345
  this._parseLimit(s);
213
346
  this._parsePage(s);
214
347
  this._parseSort(s);
215
- this._store.dispatch(updateUri({ uri: this._uri }));
348
+ return this._uri;
216
349
  }
217
350
  _prepend(model) {
218
351
  return this._uri ? '&' : `/${model}?`;
219
352
  }
353
+ // private _removeArgIfEmpty(arg: string): string {
354
+ // const params = new URL(this._uri).searchParams;
355
+ // if (!params.get(arg)) {
356
+ // params.delete(arg);
357
+ // }
358
+ // }
220
359
  /**
221
360
  * Add fields to the select statement for the given model
222
361
  *
@@ -228,11 +367,7 @@ class NgQubeeService {
228
367
  if (!fields.length) {
229
368
  return this;
230
369
  }
231
- this._store.dispatch(addFields({
232
- fields: {
233
- [model]: fields
234
- }
235
- }));
370
+ this._nestService.addFields({ [model]: fields });
236
371
  return this;
237
372
  }
238
373
  /**
@@ -247,11 +382,9 @@ class NgQubeeService {
247
382
  if (!values.length) {
248
383
  return this;
249
384
  }
250
- this._store.dispatch(addFilters({
251
- filters: {
252
- [field]: values
253
- }
254
- }));
385
+ this._nestService.addFilters({
386
+ [field]: values
387
+ });
255
388
  return this;
256
389
  }
257
390
  /**
@@ -261,41 +394,61 @@ class NgQubeeService {
261
394
  * @returns
262
395
  */
263
396
  addIncludes(...models) {
264
- if (!models) {
397
+ if (!models.length) {
265
398
  return this;
266
399
  }
267
- this._store.dispatch(addIncludes({
268
- includes: models
269
- }));
400
+ this._nestService.addIncludes(models);
270
401
  return this;
271
402
  }
272
403
  /**
273
404
  * Add a field with a sort criteria
274
405
  *
275
406
  * @param field Field to use for sorting
276
- * @param {SortEnum} value A value from the SortEnum enumeration
407
+ * @param {SortEnum} order A value from the SortEnum enumeration
277
408
  * @returns {this}
278
409
  */
279
- addSort(field, value) {
280
- this._store.dispatch(addSorts({
281
- sorts: {
282
- [field]: value
283
- }
284
- }));
410
+ addSort(field, order) {
411
+ this._nestService.addSort({
412
+ field,
413
+ order
414
+ });
415
+ return this;
416
+ }
417
+ /**
418
+ * Delete selected fields for the given models in the current query builder state
419
+ *
420
+ * ```
421
+ * ngQubeeService.deleteFields({
422
+ * users: ['email', 'password'],
423
+ * address: ['zipcode']
424
+ * });
425
+ * ```
426
+ *
427
+ * @param {IFields} fields
428
+ * @returns
429
+ */
430
+ deleteFields(fields) {
431
+ this._nestService.deleteFields(fields);
285
432
  return this;
286
433
  }
287
434
  /**
288
435
  * Delete selected fields for the given model in the current query builder state
289
436
  *
437
+ * ```
438
+ * ngQubeeService.deleteFieldsByModel('users', 'email', 'password']);
439
+ * ```
440
+ *
290
441
  * @param model Model that holds the fields
291
442
  * @param {string[]} fields Fields to delete from the state
292
443
  * @returns {this}
293
444
  */
294
- deleteFields(model, ...fields) {
445
+ deleteFieldsByModel(model, ...fields) {
295
446
  if (!fields.length) {
296
447
  return this;
297
448
  }
298
- this._store.dispatch(deleteFields({ fields }));
449
+ this._nestService.deleteFields({
450
+ [model]: fields
451
+ });
299
452
  return this;
300
453
  }
301
454
  /**
@@ -308,7 +461,7 @@ class NgQubeeService {
308
461
  if (!filters.length) {
309
462
  return this;
310
463
  }
311
- this._store.dispatch(deleteFilters({ filters }));
464
+ this._nestService.deleteFilters(...filters);
312
465
  return this;
313
466
  }
314
467
  /**
@@ -321,7 +474,7 @@ class NgQubeeService {
321
474
  if (!includes.length) {
322
475
  return this;
323
476
  }
324
- this._store.dispatch(deleteIncludes({ includes }));
477
+ this._nestService.deleteIncludes(...includes);
325
478
  return this;
326
479
  }
327
480
  /**
@@ -331,7 +484,7 @@ class NgQubeeService {
331
484
  * @returns {this}
332
485
  */
333
486
  deleteSorts(...sorts) {
334
- this._store.dispatch(deleteSorts({ sorts }));
487
+ this._nestService.deleteSorts(...sorts);
335
488
  return this;
336
489
  }
337
490
  /**
@@ -340,9 +493,7 @@ class NgQubeeService {
340
493
  * @returns {Observable<string>} An observable that emits the generated uri
341
494
  */
342
495
  generateUri() {
343
- // Cleanup the previously generated URI
344
- this._uri = '';
345
- this._parse(this._store.state.nest);
496
+ this._uri$.next(this._parse(this._nestService.nest()));
346
497
  return this.uri$;
347
498
  }
348
499
  /**
@@ -351,7 +502,7 @@ class NgQubeeService {
351
502
  * @returns {this}
352
503
  */
353
504
  reset() {
354
- this._store.dispatch(reset());
505
+ this._nestService.reset();
355
506
  return this;
356
507
  }
357
508
  /**
@@ -361,7 +512,7 @@ class NgQubeeService {
361
512
  * @returns {this}
362
513
  */
363
514
  setBaseUrl(baseUrl) {
364
- this._store.dispatch(setBaseUrl({ baseUrl }));
515
+ this._nestService.baseUrl = baseUrl;
365
516
  return this;
366
517
  }
367
518
  /**
@@ -371,7 +522,7 @@ class NgQubeeService {
371
522
  * @returns {this}
372
523
  */
373
524
  setLimit(limit) {
374
- this._store.dispatch(setLimit({ limit }));
525
+ this._nestService.limit = limit;
375
526
  return this;
376
527
  }
377
528
  /**
@@ -382,7 +533,7 @@ class NgQubeeService {
382
533
  * @returns {this}
383
534
  */
384
535
  setModel(model) {
385
- this._store.dispatch(setModel({ model }));
536
+ this._nestService.model = model;
386
537
  return this;
387
538
  }
388
539
  /**
@@ -392,67 +543,20 @@ class NgQubeeService {
392
543
  * @returns {this}
393
544
  */
394
545
  setPage(page) {
395
- this._store.dispatch(setPage({ page }));
546
+ this._nestService.page = page;
396
547
  return this;
397
548
  }
549
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeService, deps: [{ token: NestService }, { token: 'QUERY_PARAMS_CONFIG', optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
550
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeService }); }
398
551
  }
399
- NgQubeeService.decorators = [
400
- { type: Injectable }
401
- ];
402
- NgQubeeService.ctorParameters = () => [
403
- { type: StoreService },
404
- { type: undefined, decorators: [{ type: Inject, args: ['QUERY_PARAMS_CONFIG',] }, { type: Optional }] }
405
- ];
406
-
407
- class KeyNotFoundError extends Error {
408
- constructor(key) {
409
- super(`Cannot find the key ${key} inside the collection item: does it really exists?`);
410
- }
411
- }
412
-
413
- class PaginatedCollection {
414
- constructor(data, page, from, to, total, perPage, prevPageUrl, nextPageUrl, lastPage, firstPageUrl, lastPageUrl) {
415
- this.data = data;
416
- this.page = page;
417
- this.from = from;
418
- this.to = to;
419
- this.total = total;
420
- this.perPage = perPage;
421
- this.prevPageUrl = prevPageUrl;
422
- this.nextPageUrl = nextPageUrl;
423
- this.lastPage = lastPage;
424
- this.firstPageUrl = firstPageUrl;
425
- this.lastPageUrl = lastPageUrl;
426
- //
427
- }
428
- /**
429
- * Normalize the collection to a paginated list of ids for state-managed applciations.
430
- *
431
- * This method returns a single key object, where the key is the page number and the associated value is
432
- * an array of ids. Each id is fetched by the collection items, looking up for the "id" key. If an id is supplied
433
- * to this method, it will be used instead of the default "id" key.
434
- *
435
- * Please note that in case the key doesn't exist in the collection's item, the array will be empty
436
- *
437
- * @param k A key to use instead of the default "id": this will be searched inside each element of the collection
438
- */
439
- normalize(id) {
440
- return {
441
- [this.page]: this.data.reduce((ids, value) => {
442
- if (id && value[id]) {
443
- ids.push(value[id]);
444
- }
445
- else if (value.hasOwnProperty('id')) {
446
- ids.push(value['id']);
447
- }
448
- else {
449
- throw new KeyNotFoundError(id || 'id');
450
- }
451
- return ids;
452
- }, [])
453
- };
454
- }
455
- }
552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeService, decorators: [{
553
+ type: Injectable
554
+ }], ctorParameters: () => [{ type: NestService }, { type: undefined, decorators: [{
555
+ type: Inject,
556
+ args: ['QUERY_PARAMS_CONFIG']
557
+ }, {
558
+ type: Optional
559
+ }] }] });
456
560
 
457
561
  class ResponseOptions {
458
562
  constructor(options) {
@@ -478,41 +582,89 @@ class PaginationService {
478
582
  paginate(response) {
479
583
  return new PaginatedCollection(response[this._options.data], response[this._options.currentPage], response[this._options.from], response[this._options.to], response[this._options.total], response[this._options.perPage], response[this._options.prevPageUrl], response[this._options.nextPageUrl], response[this._options.lastPage], response[this._options.firstPageUrl], response[this._options.lastPageUrl]);
480
584
  }
585
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: PaginationService, deps: [{ token: 'RESPONSE_OPTIONS', optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
586
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: PaginationService }); }
481
587
  }
482
- PaginationService.decorators = [
483
- { type: Injectable }
484
- ];
485
- PaginationService.ctorParameters = () => [
486
- { type: undefined, decorators: [{ type: Inject, args: ['RESPONSE_OPTIONS',] }, { type: Optional }] }
487
- ];
588
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: PaginationService, decorators: [{
589
+ type: Injectable
590
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
591
+ type: Inject,
592
+ args: ['RESPONSE_OPTIONS']
593
+ }, {
594
+ type: Optional
595
+ }] }] });
488
596
 
489
- const ɵ0$1 = (store) => new NgQubeeService(store, {});
490
597
  // @dynamic
491
598
  class NgQubeeModule {
492
599
  static forRoot(config = {}) {
493
600
  return {
494
601
  ngModule: NgQubeeModule,
495
- providers: [{
496
- deps: [StoreService],
602
+ providers: [
603
+ NestService,
604
+ {
605
+ deps: [NestService],
497
606
  provide: NgQubeeService,
498
- useFactory: (store) => new NgQubeeService(store, Object.assign({}, this._config.request, config.request))
607
+ useFactory: (nestService) => new NgQubeeService(nestService, Object.assign({}, config.request))
499
608
  }, {
500
609
  provide: PaginationService,
501
- useFactory: () => new PaginationService(Object.assign({}, this._config.response, config.response))
502
- }]
610
+ useFactory: () => new PaginationService(Object.assign({}, config.response))
611
+ }
612
+ ]
503
613
  };
504
614
  }
615
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
616
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeModule }); }
617
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeModule, providers: [{
618
+ deps: [NestService],
619
+ provide: NgQubeeService,
620
+ useFactory: (nestService) => new NgQubeeService(nestService, {})
621
+ }] }); }
622
+ }
623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NgQubeeModule, decorators: [{
624
+ type: NgModule,
625
+ args: [{
626
+ providers: [{
627
+ deps: [NestService],
628
+ provide: NgQubeeService,
629
+ useFactory: (nestService) => new NgQubeeService(nestService, {})
630
+ }]
631
+ }]
632
+ }] });
633
+
634
+ /**
635
+ * Sets up providers necessary to enable `NgQubee` functionality for the application.
636
+ *
637
+ * @usageNotes
638
+ *
639
+ * Basic example of how you can add NgQubee to your application:
640
+ * ```
641
+ * const config = {};
642
+ *
643
+ * bootstrapApplication(AppComponent, {
644
+ * providers: [provideNgQubee(config)]
645
+ * });
646
+ * ```
647
+ *
648
+ * @publicApi
649
+ * @param config Configuration object compliant to the IConfig interface
650
+ * @returns A set of providers to setup NgQubee
651
+ */
652
+ function provideNgQubee(config = {}) {
653
+ return makeEnvironmentProviders([
654
+ {
655
+ provide: NestService,
656
+ useClass: NestService
657
+ },
658
+ {
659
+ deps: [NestService],
660
+ provide: NgQubeeService,
661
+ useFactory: (nestService) => new NgQubeeService(nestService, Object.assign({}, config.request))
662
+ }, {
663
+ provide: PaginationService,
664
+ useFactory: () => new PaginationService(Object.assign({}, config.response))
665
+ }
666
+ ]);
505
667
  }
506
- NgQubeeModule._config = {};
507
- NgQubeeModule.decorators = [
508
- { type: NgModule, args: [{
509
- providers: [{
510
- deps: [StoreService],
511
- provide: NgQubeeService,
512
- useFactory: ɵ0$1
513
- }]
514
- },] }
515
- ];
516
668
 
517
669
  /*
518
670
  * Public API Surface of angular-query-builder
@@ -522,5 +674,5 @@ NgQubeeModule.decorators = [
522
674
  * Generated bundle index. Do not edit.
523
675
  */
524
676
 
525
- export { NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationService, ɵ0$1 as ɵ0, StoreService as ɵa };
526
- //# sourceMappingURL=ng-qubee.js.map
677
+ export { NgQubeeModule, NgQubeeService, PaginatedCollection, PaginationService, provideNgQubee };
678
+ //# sourceMappingURL=ng-qubee.mjs.map