@opra/common 0.10.2 → 0.12.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 (126) hide show
  1. package/cjs/filter/antlr/OpraFilterLexer.js +1 -1
  2. package/cjs/filter/antlr/OpraFilterListener.js +1 -1
  3. package/cjs/filter/antlr/OpraFilterParser.js +5 -5
  4. package/cjs/filter/antlr/OpraFilterVisitor.js +1 -1
  5. package/cjs/filter/filter-tree-visitor.js +8 -2
  6. package/cjs/filter/opra-error-listener.js +2 -2
  7. package/cjs/filter/parse.js +1 -1
  8. package/cjs/helpers/responsive-map.js +45 -28
  9. package/{esm/http/enums/http-headers.enum.js → cjs/http/enums/http-headers-codes.enum.js} +95 -92
  10. package/{esm/http/enums/http-status.enum.js → cjs/http/enums/http-status-codes.enum.js} +62 -59
  11. package/cjs/http/http-headers.js +213 -0
  12. package/cjs/http/http-param-codec.js +6 -0
  13. package/cjs/http/http-params.js +321 -0
  14. package/cjs/http/http-request-node.js +105 -0
  15. package/cjs/http/http-request.js +73 -88
  16. package/cjs/http/http-response.js +23 -0
  17. package/cjs/http/index.js +13 -2
  18. package/cjs/http/multipart/batch-multipart.js +12 -12
  19. package/cjs/http/param-codec/boolean-codec.js +25 -0
  20. package/cjs/http/param-codec/date-codec.js +44 -0
  21. package/cjs/http/param-codec/filter-codec.js +18 -0
  22. package/cjs/http/param-codec/integer-codec.js +19 -0
  23. package/cjs/http/param-codec/number-codec.js +26 -0
  24. package/cjs/http/param-codec/string-codec.js +25 -0
  25. package/cjs/http/utils/encodeURIParam.js +21 -0
  26. package/cjs/http/utils/normalize-headers.js +2 -2
  27. package/cjs/i18n/i18n.js +1 -4
  28. package/cjs/schema/implementation/opra-document.js +12 -11
  29. package/cjs/schema/implementation/resource/collection-resource-info.js +7 -0
  30. package/cjs/url/opra-url-path.js +96 -72
  31. package/cjs/url/opra-url-search-params.js +16 -234
  32. package/cjs/url/opra-url.js +201 -160
  33. package/esm/filter/antlr/OpraFilterLexer.d.ts +1 -1
  34. package/esm/filter/antlr/OpraFilterLexer.js +1 -1
  35. package/esm/filter/antlr/OpraFilterListener.d.ts +1 -1
  36. package/esm/filter/antlr/OpraFilterListener.js +1 -1
  37. package/esm/filter/antlr/OpraFilterParser.d.ts +1 -1
  38. package/esm/filter/antlr/OpraFilterParser.js +5 -5
  39. package/esm/filter/antlr/OpraFilterVisitor.d.ts +1 -1
  40. package/esm/filter/antlr/OpraFilterVisitor.js +1 -1
  41. package/esm/filter/ast/expressions/arithmetic-expression.d.ts +1 -1
  42. package/esm/filter/ast/expressions/comparison-expression.d.ts +1 -1
  43. package/esm/filter/ast/expressions/logical-expression.d.ts +1 -1
  44. package/esm/filter/build.d.ts +3 -3
  45. package/esm/filter/errors.d.ts +4 -2
  46. package/esm/filter/filter-tree-visitor.d.ts +2 -1
  47. package/esm/filter/filter-tree-visitor.js +8 -2
  48. package/esm/filter/opra-error-listener.d.ts +2 -2
  49. package/esm/filter/opra-error-listener.js +2 -2
  50. package/esm/filter/parse.d.ts +1 -1
  51. package/esm/filter/parse.js +1 -1
  52. package/esm/helpers/responsive-map.d.ts +19 -5
  53. package/esm/helpers/responsive-map.js +45 -28
  54. package/esm/http/enums/{http-headers.enum.d.ts → http-headers-codes.enum.d.ts} +1 -1
  55. package/{cjs/http/enums/http-headers.enum.js → esm/http/enums/http-headers-codes.enum.js} +92 -95
  56. package/esm/http/enums/{http-status.enum.d.ts → http-status-codes.enum.d.ts} +1 -1
  57. package/{cjs/http/enums/http-status.enum.js → esm/http/enums/http-status-codes.enum.js} +59 -62
  58. package/esm/http/http-headers.d.ts +70 -0
  59. package/esm/http/http-headers.js +209 -0
  60. package/esm/http/http-param-codec.d.ts +4 -0
  61. package/esm/http/http-param-codec.js +2 -0
  62. package/esm/http/http-params.d.ts +99 -0
  63. package/esm/http/http-params.js +317 -0
  64. package/esm/http/http-request-node.d.ts +34 -0
  65. package/esm/http/http-request-node.js +101 -0
  66. package/esm/http/http-request.d.ts +73 -31
  67. package/esm/http/http-request.js +72 -87
  68. package/esm/http/http-response.d.ts +41 -0
  69. package/esm/http/http-response.js +19 -0
  70. package/esm/http/index.d.ts +13 -2
  71. package/esm/http/index.js +13 -2
  72. package/esm/http/interfaces/client-http-headers.interface.d.ts +1 -1
  73. package/esm/http/interfaces/server-http-headers.interface.d.ts +1 -1
  74. package/esm/http/multipart/batch-multipart.d.ts +1 -1
  75. package/esm/http/multipart/batch-multipart.js +12 -12
  76. package/esm/http/multipart/http-request-content.d.ts +1 -1
  77. package/esm/http/multipart/http-response-content.d.ts +1 -1
  78. package/esm/http/param-codec/boolean-codec.d.ts +5 -0
  79. package/esm/http/param-codec/boolean-codec.js +21 -0
  80. package/esm/http/param-codec/date-codec.d.ts +16 -0
  81. package/esm/http/param-codec/date-codec.js +40 -0
  82. package/esm/http/param-codec/filter-codec.d.ts +6 -0
  83. package/esm/http/param-codec/filter-codec.js +14 -0
  84. package/esm/http/param-codec/integer-codec.d.ts +9 -0
  85. package/esm/http/param-codec/integer-codec.js +15 -0
  86. package/esm/http/param-codec/number-codec.d.ts +12 -0
  87. package/esm/http/param-codec/number-codec.js +22 -0
  88. package/esm/http/param-codec/string-codec.d.ts +14 -0
  89. package/esm/http/param-codec/string-codec.js +21 -0
  90. package/esm/http/utils/encodeURIParam.d.ts +1 -0
  91. package/esm/http/utils/encodeURIParam.js +17 -0
  92. package/esm/http/utils/normalize-headers.js +2 -2
  93. package/esm/i18n/i18n.d.ts +6 -6
  94. package/esm/i18n/i18n.js +1 -4
  95. package/esm/schema/decorators/opr-collection-resource.decorator.d.ts +1 -1
  96. package/esm/schema/decorators/opr-complex-type.decorator.d.ts +1 -1
  97. package/esm/schema/decorators/opr-simple-type.decorator.d.ts +1 -1
  98. package/esm/schema/decorators/opr-singleton-resource.decorator.d.ts +1 -1
  99. package/esm/schema/implementation/data-type/complex-type.d.ts +1 -1
  100. package/esm/schema/implementation/data-type/union-type.d.ts +1 -1
  101. package/esm/schema/implementation/document-builder.d.ts +1 -1
  102. package/esm/schema/implementation/opra-document.d.ts +2 -2
  103. package/esm/schema/implementation/opra-document.js +12 -11
  104. package/esm/schema/implementation/query/collection-count-query.d.ts +1 -1
  105. package/esm/schema/implementation/query/collection-create-query.d.ts +1 -1
  106. package/esm/schema/implementation/query/collection-delete-many-query.d.ts +1 -1
  107. package/esm/schema/implementation/query/collection-get-query.d.ts +1 -1
  108. package/esm/schema/implementation/query/collection-search-query.d.ts +1 -1
  109. package/esm/schema/implementation/query/collection-update-many-query.d.ts +1 -1
  110. package/esm/schema/implementation/query/collection-update-query.d.ts +1 -1
  111. package/esm/schema/implementation/query/field-get-query.d.ts +1 -1
  112. package/esm/schema/implementation/query/index.d.ts +4 -4
  113. package/esm/schema/implementation/query/singleton-get-query.d.ts +1 -1
  114. package/esm/schema/implementation/resource/collection-resource-info.d.ts +2 -0
  115. package/esm/schema/implementation/resource/collection-resource-info.js +7 -0
  116. package/esm/schema/interfaces/data-type.metadata.d.ts +4 -4
  117. package/esm/schema/interfaces/resource.metadata.d.ts +9 -9
  118. package/esm/schema/types.d.ts +8 -8
  119. package/esm/url/opra-url-path-component.d.ts +1 -1
  120. package/esm/url/opra-url-path.d.ts +24 -18
  121. package/esm/url/opra-url-path.js +96 -72
  122. package/esm/url/opra-url-search-params.d.ts +3 -42
  123. package/esm/url/opra-url-search-params.js +16 -234
  124. package/esm/url/opra-url.d.ts +38 -28
  125. package/esm/url/opra-url.js +201 -160
  126. package/package.json +12 -12
@@ -1,100 +1,85 @@
1
- import { HTTPParser } from 'http-parser-js';
2
- import { Readable } from 'stream';
3
- const crlfBuffer = Buffer.from('\r\n');
4
- const kHeaders = Symbol('kHeaders');
5
- const kHeadersCount = Symbol('kHeadersCount');
6
- const kTrailers = Symbol('kTrailers');
7
- const kTrailersCount = Symbol('kTrailersCount');
8
- export class HttpRequest extends Readable {
9
- constructor() {
10
- super(...arguments);
11
- this.aborted = false;
1
+ /// <reference lib="dom" />
2
+ import { OpraURL } from '../url/index.js';
3
+ import { HttpHeaders } from './http-headers.js';
4
+ const directCopyProperties = ['cache', 'credentials', 'destination', 'headers', 'integrity',
5
+ 'keepalive', 'mode', 'redirect', 'referrer', 'referrerPolicy'];
6
+ export class HttpRequest {
7
+ constructor(init) {
8
+ this.cache = init?.cache || 'default';
9
+ this.credentials = init?.credentials || 'same-origin';
10
+ this.destination = init?.destination || '';
11
+ this.headers = new HttpHeaders(init?.headers);
12
+ this.integrity = init?.integrity || '';
13
+ this.keepalive = init?.keepalive ?? false;
14
+ this.method = (init?.method || 'GET').toUpperCase();
15
+ this.mode = init?.mode || 'cors';
16
+ this.redirect = init?.redirect || 'follow';
17
+ this.mode = init?.mode || 'cors';
18
+ this.referrer = init?.referrer || '';
19
+ this.referrerPolicy = init?.referrerPolicy || '';
20
+ this.signal = init?.signal || new AbortController().signal;
21
+ this.body = init?.body;
22
+ this.urlInstance = new OpraURL(init?.url);
23
+ if (init?.params)
24
+ this.params.appendAll(init.params);
12
25
  }
13
- get headers() {
14
- if (!this[kHeaders])
15
- this[kHeaders] = arrayToHeaders(this.rawHeaders);
16
- return this[kHeaders];
26
+ /** Returns the URL of request as a string. */
27
+ get url() {
28
+ return this.urlInstance.href;
17
29
  }
18
- get headersCount() {
19
- return this[kHeadersCount];
30
+ set url(value) {
31
+ this.urlInstance.parse(value);
20
32
  }
21
- get trailers() {
22
- if (!this[kTrailers])
23
- this[kTrailers] = arrayToHeaders(this.rawTrailers);
24
- return this[kTrailers];
33
+ /** Returns the searchParams of the URL as OpraURLSearchParams */
34
+ get params() {
35
+ return this.urlInstance.searchParams;
25
36
  }
26
- get trailersCount() {
27
- return this[kTrailersCount];
37
+ /** Returns the path part of URL as OpraURLPath */
38
+ get path() {
39
+ return this.urlInstance.path;
28
40
  }
29
- _read() {
30
- if (this.data) {
31
- this.push(this.data);
32
- }
33
- this.push(null);
34
- }
35
- static parse(input) {
36
- const parser = new HTTPParser(HTTPParser.REQUEST);
41
+ clone(...update) {
37
42
  const out = new HttpRequest();
38
- const bodyChunks = [];
39
- parser[HTTPParser.kOnHeadersComplete] = function (req) {
40
- out.shouldKeepAlive = req.shouldKeepAlive;
41
- out.upgrade = req.upgrade;
42
- out.method = HTTPParser.methods[req.method];
43
- out.url = req.url;
44
- out.originalUrl = req.url;
45
- out.httpVersionMajor = req.versionMajor;
46
- out.httpVersionMinor = req.versionMinor;
47
- out.httpVersion = req.versionMajor + '.' + req.versionMinor;
48
- out.rawHeaders = req.headers;
49
- out[kHeadersCount] = Math.ceil(req.headers.length / 2);
50
- out[kTrailersCount] = 0;
51
- };
52
- parser[HTTPParser.kOnBody] = function (chunk, offset, length) {
53
- bodyChunks.push(chunk.subarray(offset, offset + length));
54
- };
55
- // This is actually the event for trailers, go figure.
56
- parser[HTTPParser.kOnHeaders] = function (t) {
57
- out.rawTrailers = t;
58
- out[kTrailersCount] = Math.ceil(t.length / 2);
59
- };
60
- parser[HTTPParser.kOnMessageComplete] = function () {
61
- out.complete = true;
62
- };
63
- // Since we are sending the entire Buffer at once here all callbacks above happen synchronously.
64
- // The parser does not do _anything_ asynchronous.
65
- // However, you can of course call execute() multiple times with multiple chunks, e.g. from a stream.
66
- // But then you have to refactor the entire logic to be async (e.g. resolve a Promise in kOnMessageComplete and add timeout logic).
67
- parser.execute(input);
68
- if (!out.complete)
69
- parser.execute(crlfBuffer);
70
- parser.finish();
71
- if (!out.complete) {
72
- throw new Error('Could not parse request');
43
+ out.merge(this);
44
+ for (const upd of update) {
45
+ out.merge(upd);
73
46
  }
74
- out.rawTrailers = out.rawTrailers || [];
75
- if (bodyChunks.length)
76
- out.data = Buffer.concat(bodyChunks);
77
- out.resume();
78
47
  return out;
79
48
  }
80
- }
81
- function arrayToHeaders(arr) {
82
- const headers = {};
83
- for (let i = 0; i < arr.length; i++) {
84
- const k = arr[i].toLowerCase();
85
- const v = arr[++i];
86
- const trgV = headers[k];
87
- // Array header -- only Set-Cookie at the moment
88
- if (trgV && k === 'set-cookie') {
89
- const a = Array.isArray(trgV) ? trgV : [trgV];
90
- a.push(v);
91
- headers[k] = a;
49
+ merge(update) {
50
+ directCopyProperties.forEach(k => {
51
+ if (update[k] != null)
52
+ this[k] = update[k];
53
+ });
54
+ if (update.headers) {
55
+ const h = update.headers instanceof HttpHeaders
56
+ ? update.headers
57
+ : new HttpHeaders(update.headers);
58
+ h.forEach((v, k) => {
59
+ if (k.toLowerCase() === 'set-cookie') {
60
+ this.headers.append(k, v);
61
+ }
62
+ else
63
+ this.headers.set(k, v);
64
+ });
92
65
  }
93
- else if (typeof trgV === 'string') {
94
- headers[k] += (k === 'cookie' ? '; ' : ', ') + v;
66
+ }
67
+ inset(src) {
68
+ directCopyProperties.forEach(k => {
69
+ if (this[k] == null && src[k] != null)
70
+ this[k] = src[k];
71
+ });
72
+ if (src.headers) {
73
+ const h = src.headers instanceof HttpHeaders
74
+ ? src.headers
75
+ : new HttpHeaders(src.headers);
76
+ h.forEach((v, k) => {
77
+ if (k.toLowerCase() === 'set-cookie') {
78
+ this.headers.append(k, v);
79
+ }
80
+ else if (!this.headers.has(k))
81
+ this.headers.set(k, v);
82
+ });
95
83
  }
96
- else
97
- headers[k] = v;
98
84
  }
99
- return headers;
100
85
  }
@@ -0,0 +1,41 @@
1
+ import { HttpHeaders, HttpHeadersInit } from './http-headers.js';
2
+ export interface HttpResponseInit {
3
+ headers?: HttpHeadersInit;
4
+ status?: number;
5
+ statusText?: string;
6
+ url?: string;
7
+ body?: any;
8
+ hasBody?: boolean;
9
+ }
10
+ export declare class HttpResponse<TBody = any> {
11
+ /**
12
+ * Contains the Headers object associated with the response.
13
+ */
14
+ readonly headers: HttpHeaders;
15
+ /**
16
+ * Contains a Boolean stating whether the response was successful (status in the range 200-299) or not.
17
+ */
18
+ readonly ok: boolean;
19
+ /**
20
+ * Contains the HTTP status codes of the response
21
+ */
22
+ readonly status: number;
23
+ /**
24
+ * Contains the status message corresponding to the HTTP status code in status property
25
+ */
26
+ readonly statusText: string;
27
+ /**
28
+ * Contains the URL of the response
29
+ */
30
+ readonly url: string | null;
31
+ /**
32
+ * Body contents
33
+ */
34
+ readonly body: TBody | null;
35
+ /**
36
+ * Returns true if response has body to be received
37
+ */
38
+ readonly hasBody: boolean;
39
+ constructor(init?: HttpResponseInit);
40
+ clone(update?: HttpResponseInit): HttpResponse;
41
+ }
@@ -0,0 +1,19 @@
1
+ import { HttpHeaders } from './http-headers.js';
2
+ export class HttpResponse {
3
+ constructor(init) {
4
+ /**
5
+ * Returns true if response has body to be received
6
+ */
7
+ this.hasBody = false;
8
+ this.headers = new HttpHeaders(init?.headers);
9
+ this.status = init?.status || 200;
10
+ this.statusText = init?.statusText || 'OK';
11
+ this.url = init?.url || null;
12
+ this.ok = this.status >= 200 && this.status < 300;
13
+ this.body = init?.body;
14
+ this.hasBody = init?.body != null || !!init?.hasBody;
15
+ }
16
+ clone(update) {
17
+ return new HttpResponse({ ...this, ...update });
18
+ }
19
+ }
@@ -1,6 +1,17 @@
1
+ export * from './http-request-node.js';
2
+ export * from './http-headers.js';
1
3
  export * from './http-request.js';
2
- export * from './enums/http-headers.enum.js';
3
- export * from './enums/http-status.enum.js';
4
+ export * from './http-response.js';
5
+ export * from './http-params.js';
6
+ export * from './http-param-codec.js';
7
+ export * from './enums/http-headers-codes.enum.js';
8
+ export * from './enums/http-status-codes.enum.js';
4
9
  export * from './interfaces/client-http-headers.interface.js';
5
10
  export * from './interfaces/server-http-headers.interface.js';
11
+ export * from './param-codec/date-codec.js';
12
+ export * from './param-codec/boolean-codec.js';
13
+ export * from './param-codec/filter-codec.js';
14
+ export * from './param-codec/integer-codec.js';
15
+ export * from './param-codec/number-codec.js';
16
+ export * from './param-codec/string-codec.js';
6
17
  export * from './utils/normalize-headers.js';
package/esm/http/index.js CHANGED
@@ -1,6 +1,17 @@
1
+ export * from './http-request-node.js';
2
+ export * from './http-headers.js';
1
3
  export * from './http-request.js';
2
- export * from './enums/http-headers.enum.js';
3
- export * from './enums/http-status.enum.js';
4
+ export * from './http-response.js';
5
+ export * from './http-params.js';
6
+ export * from './http-param-codec.js';
7
+ export * from './enums/http-headers-codes.enum.js';
8
+ export * from './enums/http-status-codes.enum.js';
4
9
  export * from './interfaces/client-http-headers.interface.js';
5
10
  export * from './interfaces/server-http-headers.interface.js';
11
+ export * from './param-codec/date-codec.js';
12
+ export * from './param-codec/boolean-codec.js';
13
+ export * from './param-codec/filter-codec.js';
14
+ export * from './param-codec/integer-codec.js';
15
+ export * from './param-codec/number-codec.js';
16
+ export * from './param-codec/string-codec.js';
6
17
  export * from './utils/normalize-headers.js';
@@ -1,4 +1,4 @@
1
- export declare type ClientHttpHeaders = Record<string, string | string[]> & {
1
+ export type ClientHttpHeaders = Record<string, string | string[]> & {
2
2
  accept?: string;
3
3
  'accept-language'?: string;
4
4
  'accept-patch'?: string;
@@ -1 +1 @@
1
- export declare type ServerHttpHeaders = Record<string, string | string[]> & {};
1
+ export type ServerHttpHeaders = Record<string, string | string[]> & {};
@@ -4,7 +4,7 @@
4
4
  import { Readable } from 'stream';
5
5
  import { HttpRequestContent, IHttpRequestContent } from './http-request-content.js';
6
6
  import { HttpResponseContent, IHttpResponseContent } from './http-response-content.js';
7
- declare type Part = {
7
+ type Part = {
8
8
  headers: Record<string, string | string[]>;
9
9
  contentId?: string;
10
10
  content: HttpRequestContent | HttpResponseContent | BatchMultipart;
@@ -1,8 +1,8 @@
1
1
  import Highland from 'highland';
2
2
  import { uid } from 'uid';
3
3
  import { isReadable } from '../../utils/type-guards.js';
4
- import { HttpHeaders } from '../enums/http-headers.enum.js';
5
- import { HttpStatus } from '../enums/http-status.enum.js';
4
+ import { HttpHeaderCodes } from '../enums/http-headers-codes.enum.js';
5
+ import { HttpStatusCodes } from '../enums/http-status-codes.enum.js';
6
6
  import { normalizeHeaders } from '../utils/normalize-headers.js';
7
7
  import { HttpRequestContent } from './http-request-content.js';
8
8
  import { HttpResponseContent } from './http-response-content.js';
@@ -16,11 +16,11 @@ export class BatchMultipart {
16
16
  addRequestPart(content, part) {
17
17
  const headers = {
18
18
  ...normalizeHeaders(part?.headers || {}, true),
19
- [HttpHeaders.Content_Type]: 'application/http',
20
- [HttpHeaders.Content_Transfer_Encoding]: 'binary'
19
+ [HttpHeaderCodes.Content_Type]: 'application/http',
20
+ [HttpHeaderCodes.Content_Transfer_Encoding]: 'binary'
21
21
  };
22
22
  if (part?.contentId)
23
- headers[HttpHeaders.Content_ID] = part.contentId;
23
+ headers[HttpHeaderCodes.Content_ID] = part.contentId;
24
24
  this._parts.push({
25
25
  headers,
26
26
  contentId: part?.contentId,
@@ -31,11 +31,11 @@ export class BatchMultipart {
31
31
  addHttpResponse(content, part) {
32
32
  const headers = {
33
33
  ...normalizeHeaders(part?.headers || {}, true),
34
- [HttpHeaders.Content_Type]: 'application/http',
35
- [HttpHeaders.Content_Transfer_Encoding]: 'binary'
34
+ [HttpHeaderCodes.Content_Type]: 'application/http',
35
+ [HttpHeaderCodes.Content_Transfer_Encoding]: 'binary'
36
36
  };
37
37
  if (part?.contentId)
38
- headers[HttpHeaders.Content_ID] = part.contentId;
38
+ headers[HttpHeaderCodes.Content_ID] = part.contentId;
39
39
  this._parts.push({
40
40
  headers,
41
41
  contentId: part?.contentId,
@@ -46,11 +46,11 @@ export class BatchMultipart {
46
46
  addBatch(batch, part) {
47
47
  const headers = {
48
48
  ...normalizeHeaders(part?.headers || {}, true),
49
- [HttpHeaders.Content_Type]: 'application/http',
50
- [HttpHeaders.Content_Transfer_Encoding]: 'binary'
49
+ [HttpHeaderCodes.Content_Type]: 'application/http',
50
+ [HttpHeaderCodes.Content_Transfer_Encoding]: 'binary'
51
51
  };
52
52
  if (part?.contentId)
53
- headers[HttpHeaders.Content_ID] = part.contentId;
53
+ headers[HttpHeaderCodes.Content_ID] = part.contentId;
54
54
  this._parts.push({
55
55
  headers,
56
56
  contentId: part?.contentId,
@@ -122,7 +122,7 @@ export class BatchMultipart {
122
122
  if (part.content instanceof HttpRequestContent)
123
123
  s += (part.content.method || 'GET').toUpperCase() + ' ' + part.content.url + ' HTTP/1.1' + CRLF;
124
124
  else
125
- s += 'HTTP/1.1 ' + part.content.status + (HttpStatus[part.content.status] || 'Unknown') + CRLF;
125
+ s += 'HTTP/1.1 ' + part.content.status + (HttpStatusCodes[part.content.status] || 'Unknown') + CRLF;
126
126
  if (part.content.headers) {
127
127
  for (const [k, v] of Object.entries(part.content.headers)) {
128
128
  if (v === '' || v == null)
@@ -1,4 +1,4 @@
1
- export declare type IHttpRequestContent = Pick<HttpRequestContent, 'method' | 'url' | 'headers' | 'data'>;
1
+ export type IHttpRequestContent = Pick<HttpRequestContent, 'method' | 'url' | 'headers' | 'data'>;
2
2
  export declare class HttpRequestContent {
3
3
  method: string;
4
4
  url: string;
@@ -1,4 +1,4 @@
1
- export declare type IHttpResponseContent = Pick<HttpResponseContent, 'status' | 'headers' | 'data'>;
1
+ export type IHttpResponseContent = Pick<HttpResponseContent, 'status' | 'headers' | 'data'>;
2
2
  export declare class HttpResponseContent {
3
3
  status: number;
4
4
  headers?: Record<string, string | string[]>;
@@ -0,0 +1,5 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export declare class BooleanCodec extends HttpParamCodec {
3
+ decode(value: string): boolean;
4
+ encode(value: any): string;
5
+ }
@@ -0,0 +1,21 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ const trueValues = ['true', 't', 'yes', 'y', '1'];
3
+ const falseValues = ['false', 'f', 'no', 'n', '0'];
4
+ export class BooleanCodec extends HttpParamCodec {
5
+ decode(value) {
6
+ if (value === '')
7
+ return true;
8
+ // noinspection SuspiciousTypeOfGuard
9
+ if (typeof value === 'boolean')
10
+ return value;
11
+ if (trueValues.includes(value.toLowerCase()))
12
+ return true;
13
+ if (falseValues.includes(value.toLowerCase()))
14
+ return false;
15
+ throw new TypeError(`"${value}" is not a valid boolean`);
16
+ }
17
+ encode(value) {
18
+ return typeof value === 'boolean' ?
19
+ (value ? 'true' : 'false') : '';
20
+ }
21
+ }
@@ -0,0 +1,16 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export interface DateCodecOptions {
3
+ time?: boolean;
4
+ timeZone?: boolean;
5
+ min?: string;
6
+ max?: string;
7
+ }
8
+ export declare class DateCodec extends HttpParamCodec {
9
+ time: boolean;
10
+ timeZone: boolean;
11
+ min?: string;
12
+ max?: string;
13
+ constructor(options?: DateCodecOptions);
14
+ decode(value: string): string;
15
+ encode(value: any): string;
16
+ }
@@ -0,0 +1,40 @@
1
+ /* eslint-disable max-len */
2
+ import { HttpParamCodec } from '../http-param-codec.js';
3
+ // noinspection RegExpUnnecessaryNonCapturingGroup
4
+ const DATE_FORMAT_PATTERN = /^(\d{4})(?:-?(0[1-9]|1[012])(?:-?([123]0|[012][1-9]|31))?)?(?:[T ]?([01][0-9]|2[0-3]):?([0-5][0-9]):?([0-5][0-9])?(?:\.(\d+))?(?:(Z)|(?:([+-])([01]?[0-9]|2[0-3]):?([0-5][0-9])?))?)?$/;
5
+ export class DateCodec extends HttpParamCodec {
6
+ constructor(options) {
7
+ super();
8
+ this.max = options?.max ? coerceToDateString(options.max) : undefined;
9
+ this.min = options?.min ? coerceToDateString(options.min) : undefined;
10
+ this.time = options?.time ?? true;
11
+ this.timeZone = options?.timeZone ?? true;
12
+ }
13
+ decode(value) {
14
+ const v = coerceToDateString(value, this.time, this.timeZone);
15
+ if (this.min != null && v < this.min)
16
+ throw new TypeError(`Value must be ${this.min} or greater.`);
17
+ if (this.max != null && v > this.max)
18
+ throw new TypeError(`Value must be ${this.max} or less.`);
19
+ return v;
20
+ }
21
+ encode(value) {
22
+ return coerceToDateString(value, this.time, this.timeZone);
23
+ }
24
+ }
25
+ function coerceToDateString(value, time, timeZone) {
26
+ if (value === '' || value == null)
27
+ return '';
28
+ const m = value.match(DATE_FORMAT_PATTERN);
29
+ if (!m)
30
+ throw new TypeError(`"${value}" is not a valid date.`);
31
+ let v = m[1] + '-' + (m[2] || '01') + '-' + (m[3] || '01');
32
+ if (time) {
33
+ v += 'T' + (m[4] || '00') + ':' + (m[5] || '00') + ':' + (m[6] || '00') +
34
+ (m[7] ? '.' + m[7] : '');
35
+ if (timeZone)
36
+ v += m[8] ? 'Z' :
37
+ (m[9] ? (m[9] + (m[10] || '00') + ':' + (m[11] || '00')) : '');
38
+ }
39
+ return v;
40
+ }
@@ -0,0 +1,6 @@
1
+ import { Ast, Expression } from '../../filter/ast/index.js';
2
+ import { HttpParamCodec } from '../http-param-codec.js';
3
+ export declare class FilterCodec extends HttpParamCodec {
4
+ decode(value: string | Expression): object;
5
+ encode(value: Ast): string;
6
+ }
@@ -0,0 +1,14 @@
1
+ import { Expression } from '../../filter/ast/index.js';
2
+ import { parseFilter } from '../../filter/parse.js';
3
+ import { HttpParamCodec } from '../http-param-codec.js';
4
+ export class FilterCodec extends HttpParamCodec {
5
+ decode(value) {
6
+ if (value instanceof Expression)
7
+ return value;
8
+ return parseFilter(value);
9
+ }
10
+ encode(value) {
11
+ // @ts-ignore
12
+ return value ? '' + value : '';
13
+ }
14
+ }
@@ -0,0 +1,9 @@
1
+ import { NumberCodec, NumberFormatOptions } from './number-codec.js';
2
+ export interface IntegerFormatOptions extends NumberFormatOptions {
3
+ enum?: number[];
4
+ }
5
+ export declare class IntegerCodec extends NumberCodec {
6
+ enum?: number[];
7
+ constructor(options?: IntegerFormatOptions);
8
+ decode(value: string): number;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { NumberCodec } from './number-codec.js';
2
+ export class IntegerCodec extends NumberCodec {
3
+ constructor(options) {
4
+ super(options);
5
+ this.enum = options?.enum;
6
+ }
7
+ decode(value) {
8
+ const v = super.decode(value);
9
+ if (!Number.isInteger(v))
10
+ throw new TypeError(`"${value}" is not a valid integer`);
11
+ if (this.enum && !this.enum.includes(v))
12
+ throw new TypeError(`"${value}" is not one of allowed enum values (${this.enum}).`);
13
+ return v;
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export interface NumberFormatOptions {
3
+ max?: number;
4
+ min?: number;
5
+ }
6
+ export declare class NumberCodec extends HttpParamCodec {
7
+ max?: number;
8
+ min?: number;
9
+ constructor(options?: NumberFormatOptions);
10
+ decode(value: string): number;
11
+ encode(value: any): string;
12
+ }
@@ -0,0 +1,22 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export class NumberCodec extends HttpParamCodec {
3
+ constructor(options) {
4
+ super();
5
+ this.max = options?.max;
6
+ this.min = options?.min;
7
+ }
8
+ decode(value) {
9
+ // noinspection SuspiciousTypeOfGuard
10
+ const v = typeof value === 'number' ? value : parseFloat(value);
11
+ if (isNaN(v))
12
+ throw new TypeError(`"${value}" is not a valid number`);
13
+ if (this.min != null && v < this.min)
14
+ throw new TypeError(`Value must be ${this.min} or greater.`);
15
+ if (this.max != null && v > this.max)
16
+ throw new TypeError(`Value must be ${this.max} or less.`);
17
+ return v;
18
+ }
19
+ encode(value) {
20
+ return typeof value === 'number' ? '' + value : '';
21
+ }
22
+ }
@@ -0,0 +1,14 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export interface StringFormatOptions {
3
+ maxLength?: number;
4
+ minLength?: number;
5
+ enum?: string[];
6
+ }
7
+ export declare class StringCodec extends HttpParamCodec {
8
+ maxLength?: number;
9
+ minLength?: number;
10
+ enum?: string[];
11
+ constructor(options?: StringFormatOptions);
12
+ decode(value: string): string;
13
+ encode(value: any): string;
14
+ }
@@ -0,0 +1,21 @@
1
+ import { HttpParamCodec } from '../http-param-codec.js';
2
+ export class StringCodec extends HttpParamCodec {
3
+ constructor(options) {
4
+ super();
5
+ this.maxLength = options?.maxLength;
6
+ this.minLength = options?.minLength;
7
+ this.enum = options?.enum;
8
+ }
9
+ decode(value) {
10
+ if (this.minLength != null && value.length < this.minLength)
11
+ throw new TypeError(`Value must be at least ${this.minLength} character${this.minLength > 1 ? 's' : ''} long.`);
12
+ if (this.maxLength != null && value.length > this.maxLength)
13
+ throw new TypeError(`Value can be up to ${this.maxLength} character${this.maxLength > 1 ? 's' : ''} long.`);
14
+ if (this.enum && !this.enum.includes(value))
15
+ throw new TypeError(`"${value}" is not one of allowed enum values (${this.enum}).`);
16
+ return value;
17
+ }
18
+ encode(value) {
19
+ return value == null ? '' : '' + value;
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ export declare function encodeURIParam(v: string): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Encode input string with standard encodeURIComponent and then un-encode specific characters.
3
+ */
4
+ const ENCODING_REGEX = /%(\d[a-f0-9])/gi;
5
+ const ENCODING_REPLACEMENTS = {
6
+ '2C': ',',
7
+ '2F': '/',
8
+ '24': '$',
9
+ '3A': ':',
10
+ '3B': ';',
11
+ '3D': '=',
12
+ '3F': '?',
13
+ '40': '@'
14
+ };
15
+ export function encodeURIParam(v) {
16
+ return encodeURIComponent(v).replace(ENCODING_REGEX, (s, t) => ENCODING_REPLACEMENTS[t] ?? s);
17
+ }
@@ -1,5 +1,5 @@
1
- import { HttpHeaders } from '../enums/http-headers.enum.js';
2
- const knownKeys = Object.keys(HttpHeaders);
1
+ import { HttpHeaderCodes } from '../enums/http-headers-codes.enum.js';
2
+ const knownKeys = Object.keys(HttpHeaderCodes);
3
3
  const knownKeysLower = knownKeys.map(x => x.toLowerCase());
4
4
  export function normalizeHeaders(headers, normalCase) {
5
5
  if (!headers)
@@ -1,15 +1,15 @@
1
1
  import { FallbackLng, Formatter as I18nextFormatter, i18n, InitOptions as I18nextInitOptions, Resource as I18nextResource, TFunction as I18nextTFunction, TOptions } from 'i18next';
2
2
  import * as I18next from 'i18next';
3
3
  import { Type } from 'ts-gems';
4
- export declare type BaseI18n = Type<I18next.i18n>;
4
+ export type BaseI18n = Type<I18next.i18n>;
5
5
  export declare const BaseI18n: BaseI18n;
6
- export declare type DeepTranslateOptions = TOptions & {
6
+ export type DeepTranslateOptions = TOptions & {
7
7
  ignore?: (input: any, inst: i18n) => boolean;
8
8
  };
9
- export declare type InitCallback = I18next.Callback;
10
- export declare type TranslateFunction = I18nextTFunction;
11
- export declare type Formatter = I18nextFormatter;
12
- export declare type LanguageResource = I18nextResource;
9
+ export type InitCallback = I18next.Callback;
10
+ export type TranslateFunction = I18nextTFunction;
11
+ export type Formatter = I18nextFormatter;
12
+ export type LanguageResource = I18nextResource;
13
13
  export type { FallbackLng };
14
14
  export interface InitOptions extends I18nextInitOptions {
15
15
  resourceDirs?: string[];