angular-odata 0.110.0 → 0.120.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.
Files changed (64) hide show
  1. package/esm2020/lib/client.mjs +26 -19
  2. package/esm2020/lib/constants.mjs +10 -5
  3. package/esm2020/lib/index.mjs +2 -2
  4. package/esm2020/lib/loaders.mjs +33 -0
  5. package/esm2020/lib/models/collection.mjs +43 -22
  6. package/esm2020/lib/models/model.mjs +41 -9
  7. package/esm2020/lib/models/options.mjs +15 -15
  8. package/esm2020/lib/module.mjs +21 -17
  9. package/esm2020/lib/options.mjs +4 -3
  10. package/esm2020/lib/resources/query/expressions/count.mjs +89 -0
  11. package/esm2020/lib/resources/query/expressions/filter.mjs +5 -1
  12. package/esm2020/lib/resources/request.mjs +6 -1
  13. package/esm2020/lib/resources/resource.mjs +2 -2
  14. package/esm2020/lib/resources/responses/annotations.mjs +2 -2
  15. package/esm2020/lib/resources/responses/options.mjs +6 -1
  16. package/esm2020/lib/resources/responses/response.mjs +9 -5
  17. package/esm2020/lib/resources/types/action.mjs +12 -1
  18. package/esm2020/lib/resources/types/batch.mjs +133 -29
  19. package/esm2020/lib/resources/types/entity-set.mjs +15 -15
  20. package/esm2020/lib/resources/types/function.mjs +12 -1
  21. package/esm2020/lib/resources/types/navigation-property.mjs +21 -19
  22. package/esm2020/lib/resources/types/options.mjs +1 -1
  23. package/esm2020/lib/resources/types/property.mjs +7 -4
  24. package/esm2020/lib/schema/parsers/edm.mjs +3 -3
  25. package/esm2020/lib/schema/parsers/enum-type.mjs +1 -1
  26. package/esm2020/lib/schema/parsers/structured-type.mjs +1 -1
  27. package/esm2020/lib/services/entity-set.mjs +4 -2
  28. package/esm2020/lib/services/factory.mjs +3 -3
  29. package/esm2020/lib/settings.mjs +2 -2
  30. package/esm2020/lib/types.mjs +1 -1
  31. package/esm2020/lib/utils/enums.mjs +21 -21
  32. package/esm2020/lib/utils/strings.mjs +2 -2
  33. package/fesm2015/angular-odata.mjs +513 -182
  34. package/fesm2015/angular-odata.mjs.map +1 -1
  35. package/fesm2020/angular-odata.mjs +513 -180
  36. package/fesm2020/angular-odata.mjs.map +1 -1
  37. package/lib/client.d.ts +5 -2
  38. package/lib/constants.d.ts +5 -3
  39. package/lib/index.d.ts +1 -1
  40. package/lib/loaders.d.ts +15 -0
  41. package/lib/models/collection.d.ts +17 -2
  42. package/lib/models/model.d.ts +16 -4
  43. package/lib/models/options.d.ts +2 -1
  44. package/lib/module.d.ts +12 -6
  45. package/lib/options.d.ts +8 -0
  46. package/lib/resources/query/expressions/count.d.ts +44 -0
  47. package/lib/resources/query/expressions/filter.d.ts +5 -0
  48. package/lib/resources/resource.d.ts +1 -1
  49. package/lib/resources/responses/options.d.ts +1 -0
  50. package/lib/resources/types/action.d.ts +19 -2
  51. package/lib/resources/types/batch.d.ts +16 -5
  52. package/lib/resources/types/entity-set.d.ts +5 -4
  53. package/lib/resources/types/function.d.ts +17 -2
  54. package/lib/resources/types/navigation-property.d.ts +9 -9
  55. package/lib/resources/types/options.d.ts +0 -3
  56. package/lib/schema/parsers/structured-type.d.ts +1 -1
  57. package/lib/services/entity-set.d.ts +6 -1
  58. package/lib/settings.d.ts +1 -1
  59. package/lib/types.d.ts +1 -0
  60. package/lib/utils/enums.d.ts +18 -6
  61. package/lib/utils/strings.d.ts +4 -1
  62. package/package.json +1 -1
  63. package/esm2020/lib/tokens.mjs +0 -3
  64. package/lib/tokens.d.ts +0 -3
@@ -1,9 +1,10 @@
1
1
  import * as i1 from '@angular/common/http';
2
2
  import { HttpHeaders, HttpParams, HttpResponse, HttpErrorResponse, HttpEventType, HttpClientModule } from '@angular/common/http';
3
- import { of, throwError, Subject, map as map$1, firstValueFrom, EMPTY, Observable, forkJoin, NEVER } from 'rxjs';
3
+ import { of, throwError, Subject, map as map$1, EMPTY, Observable, forkJoin, NEVER } from 'rxjs';
4
4
  import { tap, startWith, map, expand, reduce, finalize, switchMap, catchError } from 'rxjs/operators';
5
5
  import * as i0 from '@angular/core';
6
6
  import { EventEmitter, Injectable, InjectionToken, NgModule } from '@angular/core';
7
+ import { CommonModule } from '@angular/common';
7
8
 
8
9
  var PathSegmentNames;
9
10
  (function (PathSegmentNames) {
@@ -57,18 +58,20 @@ const $INLINECOUNT = '$inlinecount';
57
58
  const IF_MATCH_HEADER = 'If-Match';
58
59
  const IF_NONE_MATCH_HEADER = 'If-None-Match';
59
60
  const CONTENT_TYPE = 'Content-Type';
60
- const CACHE_CONTROL = 'Cache-Control';
61
61
  const HTTP11 = 'HTTP/1.1';
62
62
  const ACCEPT = 'Accept';
63
63
  const PREFER = 'Prefer';
64
+ const CACHE_CONTROL = 'Cache-Control';
65
+ const CACHE_CONTROL_HEADERS = [
66
+ CACHE_CONTROL,
67
+ CACHE_CONTROL.toLowerCase(),
68
+ ];
64
69
  const ODATA_VERSION = 'OData-Version';
65
70
  const ODATA_VERSION_HEADERS = [
66
71
  ODATA_VERSION,
67
72
  ODATA_VERSION.toLowerCase(),
68
73
  'dataserviceversion',
69
74
  ];
70
- const ETAG_HEADER = 'ETag';
71
- const ETAG_HEADERS = [ETAG_HEADER, ETAG_HEADER.toLowerCase()];
72
75
  const LOCATION_HEADER = 'Location';
73
76
  const LOCATION_HEADERS = [
74
77
  LOCATION_HEADER,
@@ -84,6 +87,8 @@ const PREFERENCE_APPLIED_HEADERS = [
84
87
  PREFERENCE_APPLIED,
85
88
  PREFERENCE_APPLIED.toLowerCase(),
86
89
  ];
90
+ const ETAG_HEADER = 'ETag';
91
+ const ETAG_HEADERS = [ETAG_HEADER, ETAG_HEADER.toLowerCase()];
87
92
  const RETRY_AFTER = 'Retry-After';
88
93
  const RETRY_AFTER_HEADERS = [RETRY_AFTER, RETRY_AFTER.toLowerCase()];
89
94
  // HTTP HEADER VALUES
@@ -123,11 +128,12 @@ const CACHE_KEY_SEPARATOR = ':';
123
128
  // Models
124
129
  const CID_FIELD_NAME = '_cid';
125
130
  // Standard vocabularies for annotating OData services
126
- // http://docs.oasis-open.org/odata/odata-vocabularies/v4.0/csprd01/odata-vocabularies-v4.0-csprd01.html
131
+ // https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md
127
132
  const COMPUTED = /.*Computed$/;
128
133
  const OPTIMISTIC_CONCURRENCY = /.*OptimisticConcurrency$/;
129
134
  const DESCRIPTION = /.*Description$/;
130
135
  const LONG_DESCRIPTION = /.*LongDescription$/;
136
+ const OPTIONARL_PARAMETER = /.*OptionalParameter$/;
131
137
 
132
138
  class ODataCache {
133
139
  constructor({ timeout = DEFAULT_TIMEOUT }) {
@@ -974,48 +980,48 @@ const Durations = {
974
980
  };
975
981
 
976
982
  const Enums = {
977
- names(Enum) {
978
- return Object.values(Enum).filter((v) => typeof v === 'string');
983
+ names(enums) {
984
+ return Object.values(enums).filter((v) => typeof v === 'string');
979
985
  },
980
- values(Enum) {
981
- return Object.values(Enum).filter((v) => typeof v === 'number');
986
+ values(enums) {
987
+ return Object.values(enums).filter((v) => typeof v === 'number');
982
988
  },
983
- toValue(Enum, value) {
984
- if (value in Enum)
985
- return typeof value === 'string' ? Enum[value] : value;
989
+ toValue(enums, value) {
990
+ if (value in enums)
991
+ return typeof value === 'string' ? enums[value] : value;
986
992
  return undefined;
987
993
  },
988
- toValues(Enum, value) {
994
+ toValues(enums, value) {
989
995
  if (typeof value === 'number') {
990
- return this.values(Enum).filter((v) => (value & v) === v);
996
+ return this.values(enums).filter((v) => (value & v) === v);
991
997
  }
992
998
  if (typeof value === 'string') {
993
999
  value = value.split(',').map((o) => o.trim());
994
1000
  }
995
- if (Array.isArray(value) && value.every((v) => v in Enum)) {
996
- return value.map((o) => this.toValue(Enum, o));
1001
+ if (Array.isArray(value) && value.every((v) => v in enums)) {
1002
+ return value.map((o) => this.toValue(enums, o));
997
1003
  }
998
1004
  return [];
999
1005
  },
1000
- toName(Enum, value) {
1001
- if (value in Enum)
1002
- return typeof value === 'number' ? Enum[value] : value;
1006
+ toName(enums, value) {
1007
+ if (value in enums)
1008
+ return typeof value === 'number' ? enums[value] : value;
1003
1009
  return undefined;
1004
1010
  },
1005
- toNames(Enum, value) {
1011
+ toNames(enums, value) {
1006
1012
  if (typeof value === 'number') {
1007
- return this.values(Enum)
1013
+ return this.values(enums)
1008
1014
  .filter((v) => (value & v) === v)
1009
- .map((v) => this.toName(Enum, v));
1015
+ .map((v) => this.toName(enums, v));
1010
1016
  }
1011
1017
  if (typeof value === 'string') {
1012
1018
  value = value.split(',').map((o) => o.trim());
1013
1019
  }
1014
- if (Array.isArray(value) && value.every((v) => v in Enum)) {
1015
- return value.map((o) => this.toName(Enum, o));
1020
+ if (Array.isArray(value) && value.every((v) => v in enums)) {
1021
+ return value.map((o) => this.toName(enums, o));
1016
1022
  }
1017
1023
  return [];
1018
- },
1024
+ }
1019
1025
  };
1020
1026
 
1021
1027
  function cloneSymbol(targe) {
@@ -1472,7 +1478,7 @@ function now() {
1472
1478
  return (glast = time > last ? time : last + 1);
1473
1479
  }
1474
1480
  const Strings = {
1475
- uniqueId(prefix, suffix) {
1481
+ uniqueId({ prefix, suffix, } = {}) {
1476
1482
  return (prefix ? prefix : '') + now().toString(36) + (suffix ? suffix : '');
1477
1483
  },
1478
1484
  titleCase(text) {
@@ -1527,7 +1533,7 @@ class Expression {
1527
1533
  }
1528
1534
  }
1529
1535
 
1530
- class Field$1 {
1536
+ let Field$1 = class Field {
1531
1537
  constructor(name = '') {
1532
1538
  this.name = name;
1533
1539
  }
@@ -1559,7 +1565,7 @@ class Field$1 {
1559
1565
  has(target, key) {
1560
1566
  return ['toJSON', 'clone', 'render'].includes(key) || key in target;
1561
1567
  }
1562
- }
1568
+ };
1563
1569
  function applyMixins(derivedCtor, constructors) {
1564
1570
  constructors.forEach((baseCtor) => {
1565
1571
  Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
@@ -1971,6 +1977,90 @@ class ComputeExpression extends Expression {
1971
1977
  }
1972
1978
  }
1973
1979
 
1980
+ class CountField {
1981
+ constructor(field, values = {}) {
1982
+ this.field = field;
1983
+ this.values = values;
1984
+ }
1985
+ get [Symbol.toStringTag]() {
1986
+ return 'CountField';
1987
+ }
1988
+ toJSON() {
1989
+ return {
1990
+ field: this.field.toJSON(),
1991
+ };
1992
+ }
1993
+ render({ aliases, escape, prefix, }) {
1994
+ const params = [
1995
+ QueryOptionNames.filter,
1996
+ QueryOptionNames.search,
1997
+ ]
1998
+ .filter((key) => !Types.isEmpty(this.values[key]))
1999
+ .reduce((acc, key) => {
2000
+ let value = this.values[key];
2001
+ if (Types.rawType(value).endsWith('Expression')) {
2002
+ value = value.render({ aliases, prefix, escape });
2003
+ }
2004
+ return Object.assign(acc, { [key]: value });
2005
+ }, {});
2006
+ let count = `${render(this.field, { aliases, escape, prefix })}/$count`;
2007
+ if (!Types.isEmpty(params)) {
2008
+ count = `${count}(${Object.keys(params)
2009
+ .map((key) => `$${key}=${params[key]}`)
2010
+ .join(';')})`;
2011
+ }
2012
+ return count;
2013
+ }
2014
+ filter(opts) {
2015
+ return this.option(QueryOptionNames.filter, FilterExpression.filter(opts, this.values[QueryOptionNames.filter]));
2016
+ }
2017
+ clone() {
2018
+ const values = Object.keys(this.values).reduce((acc, key) => Object.assign(acc, { [key]: Objects.clone(this.values[key]) }), {});
2019
+ return new CountField(this.field.clone(), values);
2020
+ }
2021
+ // Option Handler
2022
+ option(name, opts) {
2023
+ if (opts !== undefined)
2024
+ this.values[name] = opts;
2025
+ return this.values[name];
2026
+ }
2027
+ }
2028
+ class CountExpression extends Expression {
2029
+ constructor({ children, } = {}) {
2030
+ super({ children });
2031
+ }
2032
+ static count(opts, current) {
2033
+ return opts({
2034
+ t: Field$1.factory(),
2035
+ e: () => new CountExpression(),
2036
+ }, current);
2037
+ }
2038
+ _add(node) {
2039
+ this._children.push(node);
2040
+ return this;
2041
+ }
2042
+ render({ aliases, escape, prefix, } = {}) {
2043
+ let content = this._children
2044
+ .map((n) => n.render({ aliases, escape, prefix }))
2045
+ .join(`,`);
2046
+ return content;
2047
+ }
2048
+ clone() {
2049
+ return new CountExpression({
2050
+ children: this._children.map((c) => c.clone()),
2051
+ });
2052
+ }
2053
+ field(field, opts) {
2054
+ let countField = new CountField(field);
2055
+ if (opts !== undefined)
2056
+ opts({
2057
+ t: Field$1.factory(),
2058
+ f: countField,
2059
+ });
2060
+ return this._add(countField);
2061
+ }
2062
+ }
2063
+
1974
2064
  class FilterExpression extends Expression {
1975
2065
  constructor({ children, connector, negated, } = {}) {
1976
2066
  super({ children });
@@ -2121,6 +2211,9 @@ class FilterExpression extends Expression {
2121
2211
  });
2122
2212
  return this._add(syntax.all(left, exp, alias));
2123
2213
  }
2214
+ count(left, opts) {
2215
+ return this._add(new CountExpression().field(left, opts));
2216
+ }
2124
2217
  isof(left, type) {
2125
2218
  return this._add(syntax.isof(left, type));
2126
2219
  }
@@ -3181,6 +3274,11 @@ class ODataRequest {
3181
3274
  if (this.api.options.prefer?.includeAnnotations !== undefined &&
3182
3275
  ['GET'].indexOf(this._method) !== -1)
3183
3276
  prefer.push(`odata.include-annotations=${this.api.options.prefer?.includeAnnotations}`);
3277
+ // Omit Null Values
3278
+ if (this.api.options.prefer?.omitNullValues === true &&
3279
+ ['GET'].indexOf(this._method) !== -1)
3280
+ prefer.push(`omit-values=nulls`);
3281
+ // Continue on Error
3184
3282
  if (this.api.options.prefer?.continueOnError === true &&
3185
3283
  ['POST'].indexOf(this._method) !== -1)
3186
3284
  prefer.push(`odata.continue-on-error`);
@@ -3796,9 +3894,9 @@ const EDM_PARSERS = {
3796
3894
  return v;
3797
3895
  }),
3798
3896
  //Edm.Double IEEE 754 binary64 floating-point number (15-17 decimal digits)
3799
- 'Edm.Double': EdmParser((v) => (v === 'INF' ? Infinity : v), (v) => (v === Infinity ? 'INF' : v), (v) => raw((v === Infinity ? 'INF' : v.toString()))),
3897
+ 'Edm.Double': EdmParser((v) => (v === 'INF' ? Infinity : v), (v) => (v === Infinity ? 'INF' : v), (v) => raw(v === Infinity ? 'INF' : v.toString())),
3800
3898
  //Edm.Single IEEE 754 binary32 floating-point number (6-9 decimal digits)
3801
- 'Edm.Single': EdmParser((v) => (v === 'INF' ? Infinity : v), (v) => (v === Infinity ? 'INF' : v), (v) => raw((v === Infinity ? 'INF' : v.toString()))),
3899
+ 'Edm.Single': EdmParser((v) => (v === 'INF' ? Infinity : v), (v) => (v === Infinity ? 'INF' : v), (v) => raw(v === Infinity ? 'INF' : v.toString())),
3802
3900
  //Edm.Binary Binary data
3803
3901
  'Edm.Binary': EdmParser((v) => ArrayBuffers.toArrayBuffer(v), (v) => ArrayBuffers.toString(v), (v) => raw(ArrayBuffers.toString(v))),
3804
3902
  };
@@ -4949,7 +5047,7 @@ class ODataResource {
4949
5047
  return this.pathSegments.last({ key: true })?.clearKey();
4950
5048
  }
4951
5049
  //#region Models
4952
- asModel(entity, { annots, reset } = {}) {
5050
+ asModel(entity, { annots, reset, } = {}) {
4953
5051
  let resource = this;
4954
5052
  const type = annots?.type || this.returnType();
4955
5053
  if (type === undefined)
@@ -5250,6 +5348,17 @@ class ODataActionResource extends ODataResource {
5250
5348
  ? this.asCollection(entities, { annots, reset: true })
5251
5349
  : null));
5252
5350
  }
5351
+ //#endregion
5352
+ callArraybuffer(params, { alias, ...options } = {}) {
5353
+ return this.call(params, {
5354
+ responseType: 'arraybuffer',
5355
+ alias,
5356
+ ...options,
5357
+ });
5358
+ }
5359
+ callBlob(params, { alias, ...options } = {}) {
5360
+ return this.call(params, { responseType: 'blob', alias, ...options });
5361
+ }
5253
5362
  }
5254
5363
 
5255
5364
  const Arrays = {
@@ -5266,8 +5375,13 @@ class ODataBatchRequest extends Subject {
5266
5375
  constructor(request) {
5267
5376
  super();
5268
5377
  this.request = request;
5378
+ this.id = Strings.uniqueId({ prefix: 'r' });
5379
+ this.group = Strings.uniqueId({ prefix: 'g' });
5269
5380
  }
5270
5381
  toString() {
5382
+ return this.toLegacy();
5383
+ }
5384
+ toLegacy() {
5271
5385
  //TODO: Relative or Absolute url ?
5272
5386
  let res = [
5273
5387
  `${this.request.method} ${this.request.pathWithParams} ${HTTP11}`,
@@ -5286,8 +5400,34 @@ class ODataBatchRequest extends Subject {
5286
5400
  .map((key) => `${key}: ${(headers.getAll(key) || []).join(',')}`),
5287
5401
  ];
5288
5402
  }
5403
+ if (this.request.method === 'GET' || this.request.method === 'DELETE') {
5404
+ res.push(NEWLINE);
5405
+ }
5406
+ else {
5407
+ res.push(`${NEWLINE}${JSON.stringify(this.request.body)}`);
5408
+ }
5289
5409
  return res.join(NEWLINE);
5290
5410
  }
5411
+ toJson() {
5412
+ //TODO: Relative or Absolute url ?
5413
+ let res = {
5414
+ id: this.id,
5415
+ method: this.request.method,
5416
+ url: this.request.pathWithParams,
5417
+ //'atomicityGroup': this.group
5418
+ //"dependsOn": ["g1", "g2", "r2"]
5419
+ };
5420
+ if (this.request.headers instanceof HttpHeaders) {
5421
+ let headers = this.request.headers;
5422
+ res['headers'] = headers
5423
+ .keys()
5424
+ .map((key) => `${key}: ${(headers.getAll(key) || []).join(',')}`);
5425
+ }
5426
+ if (!(this.request.method === 'GET' || this.request.method === 'DELETE')) {
5427
+ res['body'] = this.request.body;
5428
+ }
5429
+ return res;
5430
+ }
5291
5431
  onLoad(response) {
5292
5432
  if (response.ok) {
5293
5433
  this.next(response);
@@ -5356,16 +5496,49 @@ class ODataBatchResource extends ODataResource {
5356
5496
  // Store original requester
5357
5497
  var handler = this.storeRequester();
5358
5498
  // Execute the context
5359
- const obs$ = ctx(this);
5499
+ const result = ctx(this);
5360
5500
  // Restore original requester
5361
5501
  this.restoreRequester(handler);
5362
- return obs$;
5502
+ return result;
5363
5503
  }
5364
5504
  send(options) {
5365
- if (this._requests.length == 0) {
5366
- return of(null);
5505
+ if (this.api.options.jsonBatchFormat) {
5506
+ return this.sendJson(options);
5367
5507
  }
5368
- const bound = Strings.uniqueId(BATCH_PREFIX);
5508
+ else {
5509
+ return this.sendLegacy(options);
5510
+ }
5511
+ }
5512
+ sendJson(options) {
5513
+ const headers = Http.mergeHttpHeaders((options && options.headers) || {}, {
5514
+ [ODATA_VERSION]: VERSION_4_0,
5515
+ });
5516
+ return this.api
5517
+ .request('POST', this, {
5518
+ body: ODataBatchResource.buildJsonBody(this._requests),
5519
+ responseType: 'json',
5520
+ observe: 'response',
5521
+ headers: headers,
5522
+ params: options ? options.params : undefined,
5523
+ withCredentials: options ? options.withCredentials : undefined,
5524
+ })
5525
+ .pipe(map$1((response) => {
5526
+ if (this._responses == null) {
5527
+ this._responses = [];
5528
+ }
5529
+ this._responses = [
5530
+ ...this._responses,
5531
+ ...ODataBatchResource.parseJsonResponse(this._requests, response),
5532
+ ];
5533
+ Arrays.zip(this._requests, this._responses).forEach((tuple) => {
5534
+ if (!tuple[0].isStopped)
5535
+ tuple[0].onLoad(tuple[1]);
5536
+ });
5537
+ return response;
5538
+ }));
5539
+ }
5540
+ sendLegacy(options) {
5541
+ const bound = Strings.uniqueId({ prefix: BATCH_PREFIX });
5369
5542
  const headers = Http.mergeHttpHeaders((options && options.headers) || {}, {
5370
5543
  [ODATA_VERSION]: VERSION_4_0,
5371
5544
  [CONTENT_TYPE]: MULTIPART_MIXED_BOUNDARY + bound,
@@ -5373,7 +5546,7 @@ class ODataBatchResource extends ODataResource {
5373
5546
  });
5374
5547
  return this.api
5375
5548
  .request('POST', this, {
5376
- body: ODataBatchResource.buildBody(bound, this._requests),
5549
+ body: ODataBatchResource.buildLegacyBody(bound, this._requests),
5377
5550
  responseType: 'text',
5378
5551
  observe: 'response',
5379
5552
  headers: headers,
@@ -5386,7 +5559,7 @@ class ODataBatchResource extends ODataResource {
5386
5559
  }
5387
5560
  this._responses = [
5388
5561
  ...this._responses,
5389
- ...ODataBatchResource.parseResponse(this._requests, response),
5562
+ ...ODataBatchResource.parseLegacyResponse(this._requests, response),
5390
5563
  ];
5391
5564
  Arrays.zip(this._requests, this._responses).forEach((tuple) => {
5392
5565
  if (!tuple[0].isStopped)
@@ -5402,22 +5575,22 @@ class ODataBatchResource extends ODataResource {
5402
5575
  * @returns The result of execute the context
5403
5576
  */
5404
5577
  exec(ctx, options) {
5405
- let ctx$ = this.add(ctx);
5406
- let send$ = this.send(options);
5407
- firstValueFrom(send$);
5408
- return ctx$;
5409
- //return this.send(options).pipe(switchMap(() => ctx$));
5578
+ let result = this.add(ctx);
5579
+ return this.send(options).pipe(map$1((response) => [result, response]));
5410
5580
  }
5411
5581
  body() {
5412
- return ODataBatchResource.buildBody(Strings.uniqueId(BATCH_PREFIX), this._requests);
5582
+ return ODataBatchResource.buildLegacyBody(Strings.uniqueId({ prefix: BATCH_PREFIX }), this._requests);
5413
5583
  }
5414
- static buildBody(batchBoundary, requests) {
5584
+ json() {
5585
+ return ODataBatchResource.buildJsonBody(this._requests);
5586
+ }
5587
+ static buildLegacyBody(batchBoundary, requests) {
5415
5588
  let res = [];
5416
5589
  let changesetBoundary = null;
5417
5590
  let changesetId = 1;
5418
- for (const batch of requests) {
5591
+ for (const request of requests) {
5419
5592
  // if method is GET and there is a changeset boundary open then close it
5420
- if (batch.request.method === 'GET' && changesetBoundary !== null) {
5593
+ if (request.request.method === 'GET' && changesetBoundary !== null) {
5421
5594
  res.push(`${BOUNDARY_PREFIX_SUFFIX}${changesetBoundary}${BOUNDARY_PREFIX_SUFFIX}`);
5422
5595
  changesetBoundary = null;
5423
5596
  }
@@ -5426,9 +5599,9 @@ class ODataBatchResource extends ODataResource {
5426
5599
  res.push(`${BOUNDARY_PREFIX_SUFFIX}${batchBoundary}`);
5427
5600
  }
5428
5601
  // if method is not GET and there is no changeset boundary open then open a changeset boundary
5429
- if (batch.request.method !== 'GET') {
5602
+ if (request.request.method !== 'GET') {
5430
5603
  if (changesetBoundary === null) {
5431
- changesetBoundary = Strings.uniqueId(CHANGESET_PREFIX);
5604
+ changesetBoundary = Strings.uniqueId({ prefix: CHANGESET_PREFIX });
5432
5605
  res.push(`${CONTENT_TYPE}: ${MULTIPART_MIXED_BOUNDARY}${changesetBoundary}`);
5433
5606
  res.push(NEWLINE);
5434
5607
  }
@@ -5436,17 +5609,11 @@ class ODataBatchResource extends ODataResource {
5436
5609
  }
5437
5610
  res.push(`${CONTENT_TYPE}: ${APPLICATION_HTTP}`);
5438
5611
  res.push(`${CONTENT_TRANSFER_ENCODING}: ${BINARY}`);
5439
- if (batch.request.method !== 'GET') {
5612
+ if (request.request.method !== 'GET') {
5440
5613
  res.push(`${CONTENT_ID}: ${changesetId++}`);
5441
5614
  }
5442
5615
  res.push(NEWLINE);
5443
- res.push(`${batch}`);
5444
- if (batch.request.method === 'GET' || batch.request.method === 'DELETE') {
5445
- res.push(NEWLINE);
5446
- }
5447
- else {
5448
- res.push(`${NEWLINE}${JSON.stringify(batch.request.body)}`);
5449
- }
5616
+ res.push(`${request.toLegacy()}`);
5450
5617
  }
5451
5618
  if (res.length) {
5452
5619
  if (changesetBoundary !== null) {
@@ -5457,7 +5624,12 @@ class ODataBatchResource extends ODataResource {
5457
5624
  }
5458
5625
  return res.join(NEWLINE);
5459
5626
  }
5460
- static parseResponse(requests, response) {
5627
+ static buildJsonBody(requests) {
5628
+ return {
5629
+ requests: requests.map((request) => request.toJson()),
5630
+ };
5631
+ }
5632
+ static parseLegacyResponse(requests, response) {
5461
5633
  let chunks = [];
5462
5634
  const contentType = response.headers.get(CONTENT_TYPE) || '';
5463
5635
  const batchBoundary = Http.boundaryDelimiter(contentType);
@@ -5573,6 +5745,47 @@ class ODataBatchResource extends ODataResource {
5573
5745
  });
5574
5746
  });
5575
5747
  }
5748
+ static parseJsonResponse(requests, response) {
5749
+ const responses = (response.body ? response.body : {})['responses'] ?? [];
5750
+ return responses.map((response, index) => {
5751
+ let request = requests[index].request;
5752
+ let code = response['status'];
5753
+ let headers = new HttpHeaders(response['headers']);
5754
+ let body = response['body'];
5755
+ if (code === 0) {
5756
+ code = !!body ? 200 : 0;
5757
+ }
5758
+ let ok = code >= 200 && code < 300;
5759
+ if (request.responseType === 'json' && typeof body === 'string') {
5760
+ const originalBody = body;
5761
+ body = body.replace(XSSI_PREFIX, '');
5762
+ try {
5763
+ body = body !== '' ? JSON.parse(body) : null;
5764
+ }
5765
+ catch (error) {
5766
+ body = originalBody;
5767
+ if (ok) {
5768
+ ok = false;
5769
+ body = { error, text: body };
5770
+ }
5771
+ }
5772
+ }
5773
+ return ok
5774
+ ? new HttpResponse({
5775
+ body,
5776
+ headers,
5777
+ status: code,
5778
+ url: request.urlWithParams,
5779
+ })
5780
+ : new HttpErrorResponse({
5781
+ // The error in this case is the response body (error from the server).
5782
+ error: body,
5783
+ headers,
5784
+ status: code,
5785
+ url: request.urlWithParams,
5786
+ });
5787
+ });
5788
+ }
5576
5789
  }
5577
5790
 
5578
5791
  class ODataCountResource extends ODataResource {
@@ -5743,6 +5956,17 @@ class ODataFunctionResource extends ODataResource {
5743
5956
  ? this.asCollection(entities, { annots, reset: true })
5744
5957
  : null));
5745
5958
  }
5959
+ //#endregion
5960
+ callArraybuffer(params, { alias, ...options } = {}) {
5961
+ return this.call(params, {
5962
+ responseType: 'arraybuffer',
5963
+ alias,
5964
+ ...options,
5965
+ });
5966
+ }
5967
+ callBlob(params, { alias, ...options } = {}) {
5968
+ return this.call(params, { responseType: 'blob', alias, ...options });
5969
+ }
5746
5970
  }
5747
5971
 
5748
5972
  class ODataMediaResource extends ODataResource {
@@ -5989,7 +6213,10 @@ class ODataPropertyResource extends ODataResource {
5989
6213
  fetchOne(options) {
5990
6214
  let res = this.clone();
5991
6215
  res.query((q) => q.top(1));
5992
- return res.fetch({ responseType: 'entities', ...options }).pipe(map(({ entities, annots }) => ({ entity: entities !== null ? entities[0] || null : null, annots })));
6216
+ return res.fetch({ responseType: 'entities', ...options }).pipe(map(({ entities, annots }) => ({
6217
+ entity: entities !== null ? entities[0] || null : null,
6218
+ annots,
6219
+ })));
5993
6220
  }
5994
6221
  fetchMany(top, options) {
5995
6222
  let res = this.clone();
@@ -6001,7 +6228,7 @@ class ODataPropertyResource extends ODataResource {
6001
6228
  };
6002
6229
  return fetch({ top }).pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6003
6230
  entities: [...(acc.entities || []), ...(entities || [])],
6004
- annots: acc.annots.union(annots)
6231
+ annots: acc.annots.union(annots),
6005
6232
  })));
6006
6233
  }
6007
6234
  /**
@@ -6021,7 +6248,7 @@ class ODataPropertyResource extends ODataResource {
6021
6248
  };
6022
6249
  return fetch().pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6023
6250
  entities: [...(acc.entities || []), ...(entities || [])],
6024
- annots: acc.annots.union(annots)
6251
+ annots: acc.annots.union(annots),
6025
6252
  })));
6026
6253
  }
6027
6254
  }
@@ -6311,42 +6538,44 @@ class ODataNavigationPropertyResource extends ODataResource {
6311
6538
  ? this.asCollection(entities, { annots, reset: true })
6312
6539
  : null));
6313
6540
  }
6314
- fetchOne(options) {
6315
- let res = this.clone();
6316
- res.query((q) => q.top(1));
6317
- return res.fetch({ responseType: 'entities', ...options }).pipe(map(({ entities, annots }) => ({ entity: entities !== null ? entities[0] || null : null, annots })));
6318
- }
6319
- fetchMany(top, options) {
6541
+ /**
6542
+ * Fetch all entities
6543
+ * @param options Options for the request
6544
+ * @returns All entities
6545
+ */
6546
+ fetchAll(options = {}) {
6320
6547
  let res = this.clone();
6548
+ // Clean Paging
6549
+ res.query((q) => q.clearPaging());
6321
6550
  let fetch = (opts) => {
6322
6551
  if (opts) {
6323
6552
  res.query((q) => q.paging(opts));
6324
6553
  }
6325
6554
  return res.fetch({ responseType: 'entities', ...options });
6326
6555
  };
6327
- return fetch({ top }).pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6556
+ return fetch().pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6328
6557
  entities: [...(acc.entities || []), ...(entities || [])],
6329
- annots: acc.annots.union(annots)
6558
+ annots: acc.annots.union(annots),
6330
6559
  })));
6331
6560
  }
6332
- /**
6333
- * Fetch all entities
6334
- * @param options Options for the request
6335
- * @returns All entities
6336
- */
6337
- fetchAll(options = {}) {
6561
+ //#endregion
6562
+ fetchMany(top, options) {
6338
6563
  let res = this.clone();
6339
- // Clean Paging
6340
- res.query((q) => q.clearPaging());
6341
6564
  let fetch = (opts) => {
6342
6565
  if (opts) {
6343
6566
  res.query((q) => q.paging(opts));
6344
6567
  }
6345
6568
  return res.fetch({ responseType: 'entities', ...options });
6346
6569
  };
6347
- return fetch().pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6570
+ return fetch({ top }).pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6348
6571
  entities: [...(acc.entities || []), ...(entities || [])],
6349
- annots: acc.annots.union(annots)
6572
+ annots: acc.annots.union(annots),
6573
+ })));
6574
+ }
6575
+ fetchOne(options) {
6576
+ return this.fetchMany(1, options).pipe(map(({ entities, annots }) => ({
6577
+ entity: entities.length === 1 ? entities[0] : null,
6578
+ annots,
6350
6579
  })));
6351
6580
  }
6352
6581
  }
@@ -6517,40 +6746,40 @@ class ODataEntitySetResource extends ODataResource {
6517
6746
  fetch(options) {
6518
6747
  return this.get(options);
6519
6748
  }
6520
- fetchOne(options) {
6521
- let res = this.clone();
6522
- res.query((q) => q.top(1));
6523
- return res.fetch(options).pipe(map(({ entities, annots }) => ({ entity: entities !== null ? entities[0] || null : null, annots })));
6524
- }
6525
- fetchMany(top, options) {
6749
+ fetchAll(options) {
6526
6750
  let res = this.clone();
6751
+ // Clean Paging
6752
+ res.query((q) => q.clearPaging());
6527
6753
  let fetch = (opts) => {
6528
6754
  if (opts) {
6529
6755
  res.query((q) => q.paging(opts));
6530
6756
  }
6531
6757
  return res.fetch(options);
6532
6758
  };
6533
- return fetch({ top }).pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6759
+ return fetch().pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6534
6760
  entities: [...(acc.entities || []), ...(entities || [])],
6535
- annots: acc.annots.union(annots)
6761
+ annots: acc.annots.union(annots),
6536
6762
  })));
6537
6763
  }
6538
- fetchAll(options) {
6764
+ fetchMany(top, options) {
6539
6765
  let res = this.clone();
6540
- // Clean Paging
6541
- res.query((q) => q.clearPaging());
6542
6766
  let fetch = (opts) => {
6543
6767
  if (opts) {
6544
6768
  res.query((q) => q.paging(opts));
6545
6769
  }
6546
6770
  return res.fetch(options);
6547
6771
  };
6548
- return fetch().pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6772
+ return fetch({ top }).pipe(expand(({ annots }) => annots.skip || annots.skiptoken ? fetch(annots) : EMPTY), map(({ entities, annots }) => ({ entities: entities || [], annots })), reduce((acc, { entities, annots }) => ({
6549
6773
  entities: [...(acc.entities || []), ...(entities || [])],
6550
- annots: acc.annots.union(annots)
6774
+ annots: acc.annots.union(annots),
6775
+ })));
6776
+ }
6777
+ fetchOne(options) {
6778
+ return this.fetchMany(1, options).pipe(map(({ entities, annots }) => ({
6779
+ entity: entities.length === 1 ? entities[0] : null,
6780
+ annots,
6551
6781
  })));
6552
6782
  }
6553
- //#endregion
6554
6783
  fetchEntities(options) {
6555
6784
  return this.fetch(options).pipe(map(({ entities }) => entities));
6556
6785
  }
@@ -6684,7 +6913,7 @@ class ODataEntitiesAnnotations extends ODataAnnotations {
6684
6913
  return match !== null ? Number(match[1]) : undefined;
6685
6914
  }
6686
6915
  get skiptoken() {
6687
- let match = (this.nextLink || '').match(/[&?]{1}\$skiptoken=([\d\w\s']+)/);
6916
+ let match = (this.nextLink || '').match(/[&?]{1}\$skiptoken=([\d\w\s'\-]+)/);
6688
6917
  return match !== null ? match[1] : undefined;
6689
6918
  }
6690
6919
  get functions() {
@@ -6733,6 +6962,11 @@ class ODataResponseOptions {
6733
6962
  // TODO: resolve location?
6734
6963
  this.location = location;
6735
6964
  }
6965
+ setPreferenceApplied(preference) {
6966
+ preference.split(',').forEach((prefer) => {
6967
+ // TODO: resolve preference
6968
+ });
6969
+ }
6736
6970
  setCache(cacheControl) {
6737
6971
  cacheControl.split(',').forEach((directive) => {
6738
6972
  if (directive.startsWith(MAX_AGE)) {
@@ -6800,11 +7034,15 @@ class ODataResponse extends HttpResponse {
6800
7034
  .find((p) => p.startsWith(APPLICATION_JSON));
6801
7035
  this._options.setFeatures(features);
6802
7036
  }
6803
- const header = Http.resolveHeaderKey(this.headers, ODATA_VERSION_HEADERS);
6804
- if (header) {
6805
- const version = (this.headers.get(header) || '').replace(/\;/g, '');
7037
+ const headerKey = Http.resolveHeaderKey(this.headers, ODATA_VERSION_HEADERS);
7038
+ if (headerKey) {
7039
+ const version = (this.headers.get(headerKey) || '').replace(/\;/g, '');
6806
7040
  this._options.setVersion(version);
6807
7041
  }
7042
+ const preferenceApplied = this.headers.get(PREFERENCE_APPLIED);
7043
+ if (preferenceApplied) {
7044
+ this._options.setPreferenceApplied(preferenceApplied);
7045
+ }
6808
7046
  const location = this.headers.get(LOCATION_HEADER);
6809
7047
  if (location) {
6810
7048
  this._options.setLocation(location);
@@ -8154,9 +8392,9 @@ class ODataModelField {
8154
8392
  : base.property(this.parser.name);
8155
8393
  }
8156
8394
  annotationsFactory(base) {
8157
- return this.parser.collection ?
8158
- base.property(this.parser.name, 'collection') :
8159
- base.property(this.parser.name, 'single');
8395
+ return this.parser.collection
8396
+ ? base.property(this.parser.name, 'collection')
8397
+ : base.property(this.parser.name, 'single');
8160
8398
  }
8161
8399
  schemaFactory(base) {
8162
8400
  return this.api.findStructuredTypeForType(this.parser.type);
@@ -8515,30 +8753,28 @@ class ODataModelOptions {
8515
8753
  (state === ODataModelState.Changed ||
8516
8754
  (model != undefined && model.hasChanged({ include_navigation })))));
8517
8755
  }
8756
+ hasKey(self) {
8757
+ return this.resolveKey(self) !== undefined;
8758
+ }
8518
8759
  asEntity(self, func) {
8519
8760
  // Build new resource
8520
8761
  const query = self._resource?.cloneQuery();
8521
8762
  let resource = this.modelResourceFactory(query);
8522
8763
  if (resource === undefined)
8523
8764
  throw new Error('Model does not have associated Entity endpoint');
8524
- // Store parent and resource
8525
- const store = { parent: self._parent, resource: self._resource };
8526
- // Replace parent and resource
8527
- self._parent = null;
8528
- self._resource = resource;
8765
+ // Push
8766
+ self.pushResource(resource);
8529
8767
  // Execute function
8530
8768
  const result = func(self);
8531
8769
  if (result instanceof Observable) {
8532
8770
  return result.pipe(finalize(() => {
8533
- // Restore parent and resource
8534
- self._parent = store.parent;
8535
- self._resource = store.resource;
8771
+ // Pop
8772
+ self.popResource();
8536
8773
  }));
8537
8774
  }
8538
8775
  else {
8539
- // Restore parent and resource
8540
- self._parent = store.parent;
8541
- self._resource = store.resource;
8776
+ // Pop
8777
+ self.popResource();
8542
8778
  return result;
8543
8779
  }
8544
8780
  }
@@ -8576,6 +8812,7 @@ class ODataModelOptions {
8576
8812
  client_id,
8577
8813
  include_navigation,
8578
8814
  include_concurrency,
8815
+ include_computed,
8579
8816
  include_non_field,
8580
8817
  field_mapping,
8581
8818
  changes_only: changesOnly,
@@ -8591,6 +8828,7 @@ class ODataModelOptions {
8591
8828
  client_id,
8592
8829
  include_navigation,
8593
8830
  include_concurrency,
8831
+ include_computed,
8594
8832
  include_non_field,
8595
8833
  field_mapping,
8596
8834
  changes_only: changesOnly,
@@ -8975,6 +9213,7 @@ class ODataCollection {
8975
9213
  constructor(entities = [], { parent, resource, annots, model, reset = false, } = {}) {
8976
9214
  this._parent = null;
8977
9215
  this._resource = null;
9216
+ this._resources = [];
8978
9217
  this._entries = [];
8979
9218
  //Events
8980
9219
  this.events$ = new EventEmitter();
@@ -9017,14 +9256,33 @@ class ODataCollection {
9017
9256
  resource() {
9018
9257
  return ODataModelOptions.resource(this);
9019
9258
  }
9259
+ pushResource(resource) {
9260
+ // Push current parent and resource
9261
+ this._resources.push({ parent: this._parent, resource: this._resource });
9262
+ // Replace parent and resource
9263
+ this._parent = null;
9264
+ this._resource = resource;
9265
+ }
9266
+ popResource() {
9267
+ // Pop parent and resource
9268
+ const pop = this._resources.pop();
9269
+ if (pop !== undefined) {
9270
+ const current = { parent: this._parent, resource: this._resource };
9271
+ this._parent = pop.parent;
9272
+ this._resource = pop.resource;
9273
+ return current;
9274
+ }
9275
+ return undefined;
9276
+ }
9020
9277
  attach(resource) {
9021
9278
  if (this._resource !== null &&
9022
9279
  this._resource.type() !== resource.type() &&
9023
9280
  !this._resource.isSubtypeOf(resource))
9024
9281
  throw new Error(`attach: Can't reattach ${this._resource.type()} to ${resource.type()}`);
9025
9282
  this._entries.forEach(({ model }) => {
9026
- const mr = this._model.meta.modelResourceFactory(resource.cloneQuery());
9027
- model.attach(mr);
9283
+ const modelResource = this._model.meta.modelResourceFactory(resource.cloneQuery());
9284
+ if (modelResource !== undefined)
9285
+ model.attach(modelResource);
9028
9286
  });
9029
9287
  const current = this._resource;
9030
9288
  if (current === null || !current.isEqualTo(resource)) {
@@ -9042,24 +9300,16 @@ class ODataCollection {
9042
9300
  let resource = this._model.meta.collectionResourceFactory(query);
9043
9301
  if (resource === undefined)
9044
9302
  throw new Error('asEntitySet: Collection does not have associated EntitySet endpoint');
9045
- // Store parent and resource
9046
- const store = { parent: this._parent, resource: this._resource };
9047
- // Replace parent and resource
9048
- this._parent = null;
9049
- this._resource = resource;
9303
+ // Push
9304
+ this.pushResource(resource);
9050
9305
  // Execute
9051
9306
  const result = func(this);
9052
9307
  if (result instanceof Observable) {
9053
- return result.pipe(finalize(() => {
9054
- // Restore
9055
- this._parent = store.parent;
9056
- this._resource = store.resource;
9057
- }));
9308
+ return result.pipe(finalize(() => this.popResource()));
9058
9309
  }
9059
9310
  else {
9060
- // Restore
9061
- this._parent = store.parent;
9062
- this._resource = store.resource;
9311
+ // Pop
9312
+ this.popResource();
9063
9313
  return result;
9064
9314
  }
9065
9315
  }
@@ -9115,11 +9365,17 @@ class ODataCollection {
9115
9365
  });
9116
9366
  }
9117
9367
  _request(obs$) {
9118
- this.events$.emit(new ODataModelEvent('request', { collection: this, options: { observable: obs$ } }));
9368
+ this.events$.emit(new ODataModelEvent('request', {
9369
+ collection: this,
9370
+ options: { observable: obs$ },
9371
+ }));
9119
9372
  return obs$.pipe(map(({ entities, annots }) => {
9120
9373
  this._annotations = annots;
9121
9374
  this.assign(entities || [], { reset: true });
9122
- this.events$.emit(new ODataModelEvent('sync', { collection: this, options: { entities, annots } }));
9375
+ this.events$.emit(new ODataModelEvent('sync', {
9376
+ collection: this,
9377
+ options: { entities, annots },
9378
+ }));
9123
9379
  return this;
9124
9380
  }));
9125
9381
  }
@@ -9134,16 +9390,19 @@ class ODataCollection {
9134
9390
  });
9135
9391
  return this._request(obs$);
9136
9392
  }
9137
- fetchMany(top, { withCount, ...options } = {}) {
9393
+ fetchAll({ withCount, ...options } = {}) {
9138
9394
  const resource = this.resource();
9139
- const obs$ = resource.fetchMany(top, { withCount, ...options });
9395
+ const obs$ = resource.fetchAll({ withCount, ...options });
9140
9396
  return this._request(obs$);
9141
9397
  }
9142
- fetchAll({ withCount, ...options } = {}) {
9398
+ fetchMany(top, { withCount, ...options } = {}) {
9143
9399
  const resource = this.resource();
9144
- const obs$ = resource.fetchAll({ withCount, ...options });
9400
+ const obs$ = resource.fetchMany(top, { withCount, ...options });
9145
9401
  return this._request(obs$);
9146
9402
  }
9403
+ fetchOne({ withCount, ...options } = {}) {
9404
+ return this.fetchMany(1, { withCount, ...options }).pipe(map((col) => col.first() || null));
9405
+ }
9147
9406
  /**
9148
9407
  * Save all models in the collection
9149
9408
  * @param relModel The model is relationship
@@ -9774,10 +10033,11 @@ class ODataModel {
9774
10033
  constructor(data = {}, { parent, resource, annots, reset = false, } = {}) {
9775
10034
  // Parent
9776
10035
  this._parent = null;
10036
+ this._resource = null;
10037
+ this._resources = [];
9777
10038
  this._attributes = new Map();
9778
10039
  this._changes = new Map();
9779
10040
  this._relations = new Map();
9780
- this._resource = null;
9781
10041
  this._annotations = null;
9782
10042
  this._reset = false;
9783
10043
  this._reparent = false;
@@ -9792,10 +10052,12 @@ class ODataModel {
9792
10052
  // Client Id
9793
10053
  this[this._meta.cid] =
9794
10054
  data[this._meta.cid] ||
9795
- Strings.uniqueId(`${Klass.meta.schema.name.toLowerCase()}-`);
10055
+ Strings.uniqueId({ prefix: `${Klass.meta.schema.name.toLowerCase()}-` });
9796
10056
  let attrs = this.annots().attributes(data, 'full');
9797
10057
  let defaults = this.defaults();
9798
- this.assign(Objects.merge(defaults, attrs), { reset });
10058
+ this.assign(Objects.merge(defaults, attrs), {
10059
+ reset,
10060
+ });
9799
10061
  }
9800
10062
  static buildMeta({ options, schema, }) {
9801
10063
  if (options === undefined) {
@@ -9823,6 +10085,24 @@ class ODataModel {
9823
10085
  resource() {
9824
10086
  return ODataModelOptions.resource(this);
9825
10087
  }
10088
+ pushResource(resource) {
10089
+ // Push current parent and resource
10090
+ this._resources.push({ parent: this._parent, resource: this._resource });
10091
+ // Replace parent and resource
10092
+ this._parent = null;
10093
+ this._resource = resource;
10094
+ }
10095
+ popResource() {
10096
+ // Pop parent and resource
10097
+ const pop = this._resources.pop();
10098
+ if (pop !== undefined) {
10099
+ const current = { parent: this._parent, resource: this._resource };
10100
+ this._parent = pop.parent;
10101
+ this._resource = pop.resource;
10102
+ return current;
10103
+ }
10104
+ return undefined;
10105
+ }
9826
10106
  navigationProperty(name) {
9827
10107
  const field = this._meta.field(name);
9828
10108
  if (field === undefined || !field.navigation)
@@ -9849,14 +10129,12 @@ class ODataModel {
9849
10129
  return this._meta.schema;
9850
10130
  }
9851
10131
  annots() {
9852
- return this._annotations ?? new ODataEntityAnnotations(ODataHelper[DEFAULT_VERSION]);
10132
+ return (this._annotations ??
10133
+ new ODataEntityAnnotations(ODataHelper[DEFAULT_VERSION]));
9853
10134
  }
9854
10135
  key({ field_mapping = false, resolve = true, } = {}) {
9855
10136
  return this._meta.resolveKey(this, { field_mapping, resolve });
9856
10137
  }
9857
- isNew() {
9858
- return this.key() === undefined;
9859
- }
9860
10138
  isParentOf(child) {
9861
10139
  return (child !== this &&
9862
10140
  ODataModelOptions.chain(child).some((p) => p[0] === this));
@@ -10072,6 +10350,9 @@ class ODataModel {
10072
10350
  hasChanged({ include_navigation = false, } = {}) {
10073
10351
  return this._meta.hasChanged(this, { include_navigation });
10074
10352
  }
10353
+ isNew() {
10354
+ return !this._meta.hasKey(this);
10355
+ }
10075
10356
  /**
10076
10357
  * Create an execution context for a given function, where the model is bound to its entity endpoint
10077
10358
  * @param ctx Context function
@@ -10092,6 +10373,10 @@ class ODataModel {
10092
10373
  return func.callModel(params, options);
10093
10374
  case 'collection':
10094
10375
  return func.callCollection(params, options);
10376
+ case 'blob':
10377
+ return func.callBlob(params, options);
10378
+ case 'arraybuffer':
10379
+ return func.callArraybuffer(params, options);
10095
10380
  default:
10096
10381
  return func.call(params, { responseType, ...options });
10097
10382
  }
@@ -10108,6 +10393,10 @@ class ODataModel {
10108
10393
  return action.callModel(params, options);
10109
10394
  case 'collection':
10110
10395
  return action.callCollection(params, options);
10396
+ case 'blob':
10397
+ return action.callBlob(params, options);
10398
+ case 'arraybuffer':
10399
+ return action.callArraybuffer(params, options);
10111
10400
  default:
10112
10401
  return action.call(params, { responseType, ...options });
10113
10402
  }
@@ -10119,7 +10408,9 @@ class ODataModel {
10119
10408
  throw new Error(`cast: Can't cast to derived model without ODataEntityResource`);
10120
10409
  return resource
10121
10410
  .cast(type)
10122
- .asModel(this.toEntity(INCLUDE_DEEP), { annots: this.annots() });
10411
+ .asModel(this.toEntity(INCLUDE_DEEP), {
10412
+ annots: this.annots(),
10413
+ });
10123
10414
  }
10124
10415
  fetchNavigationProperty(name, responseType, { ...options } = {}) {
10125
10416
  const nav = this.navigationProperty(name);
@@ -10242,9 +10533,10 @@ class ODataApiOptions {
10242
10533
  this.accept = config.accept;
10243
10534
  Object.assign(this.etag, config.etag || {});
10244
10535
  this.prefer = config.prefer;
10245
- this.deleteRefBy = config.deleteRefBy || 'path';
10536
+ this.deleteRefBy = config.deleteRefBy ?? 'path';
10246
10537
  this.nonParenthesisForEmptyParameterFunction =
10247
- config.nonParenthesisForEmptyParameterFunction || false;
10538
+ config.nonParenthesisForEmptyParameterFunction ?? false;
10539
+ this.jsonBatchFormat = config.jsonBatchFormat ?? false;
10248
10540
  }
10249
10541
  get parserOptions() {
10250
10542
  return {
@@ -10624,7 +10916,7 @@ class ODataApi {
10624
10916
  }
10625
10917
 
10626
10918
  class ODataSettings {
10627
- constructor(...configs) {
10919
+ constructor(configs) {
10628
10920
  this.apis = configs.map((config) => new ODataApi(config));
10629
10921
  if (this.apis.length > 1) {
10630
10922
  if (this.apis.some((c) => c.name === undefined))
@@ -10826,6 +11118,37 @@ class ODataSettings {
10826
11118
  }
10827
11119
  }
10828
11120
 
11121
+ class ODataConfigLoader {
11122
+ }
11123
+ class ODataConfigSyncLoader {
11124
+ constructor(passedConfigs) {
11125
+ this.passedConfigs = passedConfigs;
11126
+ }
11127
+ loadConfigs() {
11128
+ if (Array.isArray(this.passedConfigs)) {
11129
+ return of(this.passedConfigs);
11130
+ }
11131
+ return of([this.passedConfigs]);
11132
+ }
11133
+ }
11134
+ class ODataConfigAsyncLoader {
11135
+ constructor(configs$) {
11136
+ this.configs$ = configs$;
11137
+ }
11138
+ loadConfigs() {
11139
+ if (Array.isArray(this.configs$)) {
11140
+ return forkJoin(this.configs$);
11141
+ }
11142
+ const singleConfigOrArray = this.configs$;
11143
+ return singleConfigOrArray.pipe(map((value) => {
11144
+ if (Array.isArray(value)) {
11145
+ return value;
11146
+ }
11147
+ return [value];
11148
+ }));
11149
+ }
11150
+ }
11151
+
10829
11152
  function addBody(options, body) {
10830
11153
  return {
10831
11154
  body,
@@ -10840,21 +11163,24 @@ function addBody(options, body) {
10840
11163
  };
10841
11164
  }
10842
11165
  class ODataClient {
10843
- constructor(http, settings, injector) {
11166
+ constructor(http, loader, injector) {
10844
11167
  this.http = http;
10845
- this.settings = settings;
11168
+ this.loader = loader;
10846
11169
  this.injector = injector;
10847
- this.settings.configure({
10848
- requester: (req) => this.http.request(req.method, `${req.url}`, {
10849
- body: req.body,
10850
- context: req.context,
10851
- headers: req.headers,
10852
- observe: req.observe,
10853
- params: req.params,
10854
- reportProgress: req.reportProgress,
10855
- responseType: req.responseType,
10856
- withCredentials: req.withCredentials,
10857
- }),
11170
+ this.loader.loadConfigs().subscribe(config => {
11171
+ this.settings = new ODataSettings(config);
11172
+ this.settings.configure({
11173
+ requester: (req) => this.http.request(req.method, `${req.url}`, {
11174
+ body: req.body,
11175
+ context: req.context,
11176
+ headers: req.headers,
11177
+ observe: req.observe,
11178
+ params: req.params,
11179
+ reportProgress: req.reportProgress,
11180
+ responseType: req.responseType,
11181
+ withCredentials: req.withCredentials,
11182
+ }),
11183
+ });
10858
11184
  });
10859
11185
  }
10860
11186
  //#region Resolve Building Blocks
@@ -10874,6 +11200,9 @@ class ODataClient {
10874
11200
  this.settings.findApiForType(value);
10875
11201
  return api || this.settings.defaultApi();
10876
11202
  }
11203
+ defaultApi() {
11204
+ return this.settings.defaultApi();
11205
+ }
10877
11206
  /**
10878
11207
  * Resolve the parser for the given string type.
10879
11208
  * @param type The string type of the parser.
@@ -11057,16 +11386,14 @@ class ODataClient {
11057
11386
  return this.request('PUT', resource, addBody(options, body));
11058
11387
  }
11059
11388
  }
11060
- ODataClient.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataClient, deps: [{ token: i1.HttpClient }, { token: ODataSettings }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
11061
- ODataClient.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataClient, providedIn: 'root' });
11062
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataClient, decorators: [{
11389
+ ODataClient.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataClient, deps: [{ token: i1.HttpClient }, { token: ODataConfigLoader }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
11390
+ ODataClient.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataClient, providedIn: 'root' });
11391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataClient, decorators: [{
11063
11392
  type: Injectable,
11064
11393
  args: [{
11065
11394
  providedIn: 'root',
11066
11395
  }]
11067
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: ODataSettings }, { type: i0.Injector }]; } });
11068
-
11069
- const ODATA_CONFIGURATIONS = new InjectionToken('odata.configuraions');
11396
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: ODataConfigLoader }, { type: i0.Injector }]; } });
11070
11397
 
11071
11398
  class ODataBaseService {
11072
11399
  constructor(client, name, apiNameOrEntityType) {
@@ -11215,7 +11542,9 @@ class ODataEntitySetService extends ODataEntityService {
11215
11542
  * @param options The options for the request.
11216
11543
  */
11217
11544
  fetchOrCreate(key, attrs, { etag, ...options } = {}) {
11218
- return this.entity(key).fetch({ etag, ...options }).pipe(catchError((error) => {
11545
+ return this.entity(key)
11546
+ .fetch({ etag, ...options })
11547
+ .pipe(catchError((error) => {
11219
11548
  if (error.status === 404)
11220
11549
  return this.create(attrs, options);
11221
11550
  else
@@ -11315,25 +11644,29 @@ class ODataServiceFactory {
11315
11644
  })(this.client, singletonName, apiNameOrEntityType);
11316
11645
  }
11317
11646
  }
11318
- ODataServiceFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataServiceFactory, deps: [{ token: ODataClient }], target: i0.ɵɵFactoryTarget.Injectable });
11319
- ODataServiceFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataServiceFactory });
11320
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataServiceFactory, decorators: [{
11647
+ ODataServiceFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataServiceFactory, deps: [{ token: ODataClient }], target: i0.ɵɵFactoryTarget.Injectable });
11648
+ ODataServiceFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataServiceFactory });
11649
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataServiceFactory, decorators: [{
11321
11650
  type: Injectable
11322
11651
  }], ctorParameters: function () { return [{ type: ODataClient }]; } });
11323
11652
 
11324
- function createSettings(configs) {
11325
- return new ODataSettings(...configs);
11653
+ const ODATA_CONFIG = new InjectionToken('odata.config');
11654
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
11655
+ function createSyncLoader(passedConfig) {
11656
+ return new ODataConfigSyncLoader(passedConfig.config);
11326
11657
  }
11327
11658
  class ODataModule {
11328
- static forRoot(...configs) {
11659
+ static forRoot(passedConfig) {
11329
11660
  return {
11330
11661
  ngModule: ODataModule,
11331
11662
  providers: [
11332
- { provide: ODATA_CONFIGURATIONS, useValue: configs },
11333
- {
11334
- provide: ODataSettings,
11335
- useFactory: createSettings,
11336
- deps: [ODATA_CONFIGURATIONS],
11663
+ // Make the ODATA_CONFIG available through injection
11664
+ { provide: ODATA_CONFIG, useValue: passedConfig },
11665
+ // Create the loader: Either the one getting passed or a sync one
11666
+ passedConfig?.loader || {
11667
+ provide: ODataConfigLoader,
11668
+ useFactory: createSyncLoader,
11669
+ deps: [ODATA_CONFIG],
11337
11670
  },
11338
11671
  ODataClient,
11339
11672
  ODataServiceFactory,
@@ -11341,13 +11674,13 @@ class ODataModule {
11341
11674
  };
11342
11675
  }
11343
11676
  }
11344
- ODataModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
11345
- ODataModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.1", ngImport: i0, type: ODataModule, imports: [HttpClientModule] });
11346
- ODataModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataModule, providers: [ODataClient, ODataServiceFactory], imports: [HttpClientModule] });
11347
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: ODataModule, decorators: [{
11677
+ ODataModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
11678
+ ODataModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.3", ngImport: i0, type: ODataModule, imports: [CommonModule, HttpClientModule] });
11679
+ ODataModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataModule, providers: [ODataClient, ODataServiceFactory], imports: [CommonModule, HttpClientModule] });
11680
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: ODataModule, decorators: [{
11348
11681
  type: NgModule,
11349
11682
  args: [{
11350
- imports: [HttpClientModule],
11683
+ imports: [CommonModule, HttpClientModule],
11351
11684
  providers: [ODataClient, ODataServiceFactory],
11352
11685
  }]
11353
11686
  }] });
@@ -11360,5 +11693,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImpor
11360
11693
  * Generated bundle index. Do not edit.
11361
11694
  */
11362
11695
 
11363
- export { BUBBLING, Dates, Durations, EDM_PARSERS, Enums, Http, INCLUDE_DEEP, INCLUDE_SHALLOW, ITEM_ROOT, Model, ModelField, NONE_PARSER, ODATA_CONFIGURATIONS, OData, ODataActionResource, ODataAnnotations, ODataApi, ODataBaseService, ODataBatchRequest, ODataBatchResource, ODataCache, ODataCallable, ODataCallableParser, ODataClient, ODataCollection, ODataCountResource, ODataEntitiesAnnotations, ODataEntityAnnotations, ODataEntityContainer, ODataEntityResource, ODataEntitySet, ODataEntitySetResource, ODataEntitySetService, ODataEntityTypeKey, ODataEnumType, ODataEnumTypeFieldParser, ODataEnumTypeParser, ODataFunctionResource, ODataInMemoryCache, ODataInStorageCache, ODataMediaResource, ODataMetadata, ODataMetadataResource, ODataModel, ODataModelEvent, ODataModelField, ODataModelOptions, ODataModelState, ODataModule, ODataNavigationPropertyResource, ODataParameterParser, ODataPathSegments, ODataPathSegmentsHandler, ODataPropertyAnnotations, ODataPropertyResource, ODataQueryOptionHandler, ODataQueryOptions, ODataQueryOptionsHandler, ODataReferenceResource, ODataReferential, ODataRequest, ODataResource, ODataResponse, ODataSchema, ODataServiceFactory, ODataSettings, ODataSingletonResource, ODataSingletonService, ODataStructuredType, ODataStructuredTypeFieldParser, ODataStructuredTypeParser, ODataValueResource, Objects, PathSegmentNames, QueryCustomTypes, QueryOptionNames, RESERVED_FIELD_NAMES, SegmentHandler, StandardAggregateMethods, Strings, Types, Urls, alias, binary, buildPathAndQuery, createSettings, duration, isQueryCustomType, normalizeValue, raw };
11696
+ export { BUBBLING, Dates, Durations, EDM_PARSERS, Enums, Http, INCLUDE_DEEP, INCLUDE_SHALLOW, ITEM_ROOT, Model, ModelField, NONE_PARSER, ODATA_CONFIG, OData, ODataActionResource, ODataAnnotations, ODataApi, ODataBaseService, ODataBatchRequest, ODataBatchResource, ODataCache, ODataCallable, ODataCallableParser, ODataClient, ODataCollection, ODataConfigAsyncLoader, ODataConfigLoader, ODataConfigSyncLoader, ODataCountResource, ODataEntitiesAnnotations, ODataEntityAnnotations, ODataEntityContainer, ODataEntityResource, ODataEntitySet, ODataEntitySetResource, ODataEntitySetService, ODataEntityTypeKey, ODataEnumType, ODataEnumTypeFieldParser, ODataEnumTypeParser, ODataFunctionResource, ODataInMemoryCache, ODataInStorageCache, ODataMediaResource, ODataMetadata, ODataMetadataResource, ODataModel, ODataModelEvent, ODataModelField, ODataModelOptions, ODataModelState, ODataModule, ODataNavigationPropertyResource, ODataParameterParser, ODataPathSegments, ODataPathSegmentsHandler, ODataPropertyAnnotations, ODataPropertyResource, ODataQueryOptionHandler, ODataQueryOptions, ODataQueryOptionsHandler, ODataReferenceResource, ODataReferential, ODataRequest, ODataResource, ODataResponse, ODataSchema, ODataServiceFactory, ODataSettings, ODataSingletonResource, ODataSingletonService, ODataStructuredType, ODataStructuredTypeFieldParser, ODataStructuredTypeParser, ODataValueResource, Objects, PathSegmentNames, QueryCustomTypes, QueryOptionNames, RESERVED_FIELD_NAMES, SegmentHandler, StandardAggregateMethods, Strings, Types, Urls, alias, binary, buildPathAndQuery, createSyncLoader, duration, isQueryCustomType, normalizeValue, raw };
11364
11697
  //# sourceMappingURL=angular-odata.mjs.map