@opra/common 0.22.0 → 0.23.1

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 (181) hide show
  1. package/browser.js +957 -1566
  2. package/cjs/document/api-document.js +7 -3
  3. package/cjs/document/data-type/api-field.js +2 -2
  4. package/cjs/document/data-type/complex-type.js +17 -63
  5. package/cjs/document/data-type/data-type.js +0 -9
  6. package/cjs/document/data-type/enum-type.js +2 -8
  7. package/cjs/document/data-type/mapped-type.js +0 -36
  8. package/cjs/document/data-type/simple-type.js +2 -8
  9. package/cjs/document/data-type/union-type.js +1 -37
  10. package/cjs/document/index.js +2 -0
  11. package/cjs/document/resource/collection.js +75 -32
  12. package/cjs/document/resource/singleton.js +31 -20
  13. package/cjs/document/resource/storage.js +6 -20
  14. package/cjs/document/utils/generate-codec.js +39 -0
  15. package/cjs/exception/http-errors/bad-request.error.js +2 -3
  16. package/cjs/exception/http-errors/failed-dependency.error.js +2 -3
  17. package/cjs/exception/http-errors/forbidden.error.js +2 -3
  18. package/cjs/exception/http-errors/internal-server.error.js +2 -3
  19. package/cjs/exception/http-errors/method-not-allowed.error.js +2 -3
  20. package/cjs/exception/http-errors/not-acceptable.error.js +2 -3
  21. package/cjs/exception/http-errors/not-found.error.js +2 -3
  22. package/cjs/exception/http-errors/unauthorized.error.js +2 -3
  23. package/cjs/exception/http-errors/unprocessable-entity.error.js +2 -2
  24. package/cjs/exception/opra-exception.js +48 -33
  25. package/cjs/exception/resource-errors/resource-not-found.error.js +2 -3
  26. package/cjs/exception/wrap-exception.js +16 -16
  27. package/cjs/helpers/index.js +1 -1
  28. package/cjs/helpers/is-url-string.js +14 -0
  29. package/cjs/helpers/object-utils.js +2 -2
  30. package/cjs/helpers/responsive-map.js +4 -4
  31. package/cjs/helpers/type-guards.js +15 -3
  32. package/cjs/http/index.js +2 -9
  33. package/cjs/http/opra-url-path.js +251 -0
  34. package/cjs/{url → http}/opra-url.js +53 -109
  35. package/cjs/i18n/i18n.js +1 -1
  36. package/cjs/index.js +0 -2
  37. package/cjs/schema/opra-schema.ns.js +1 -1
  38. package/cjs/schema/resource/operation.interface.js +2 -0
  39. package/esm/document/api-document.js +9 -5
  40. package/esm/document/data-type/api-field.js +2 -2
  41. package/esm/document/data-type/complex-type.js +13 -59
  42. package/esm/document/data-type/data-type.js +0 -9
  43. package/esm/document/data-type/enum-type.js +2 -8
  44. package/esm/document/data-type/mapped-type.js +0 -36
  45. package/esm/document/data-type/simple-type.js +2 -8
  46. package/esm/document/data-type/union-type.js +1 -37
  47. package/esm/document/index.js +2 -0
  48. package/esm/document/resource/collection.js +75 -32
  49. package/esm/document/resource/singleton.js +31 -20
  50. package/esm/document/resource/storage.js +6 -20
  51. package/esm/document/utils/generate-codec.js +33 -0
  52. package/esm/exception/http-errors/bad-request.error.js +2 -3
  53. package/esm/exception/http-errors/failed-dependency.error.js +2 -3
  54. package/esm/exception/http-errors/forbidden.error.js +2 -3
  55. package/esm/exception/http-errors/internal-server.error.js +2 -3
  56. package/esm/exception/http-errors/method-not-allowed.error.js +2 -3
  57. package/esm/exception/http-errors/not-acceptable.error.js +2 -3
  58. package/esm/exception/http-errors/not-found.error.js +2 -3
  59. package/esm/exception/http-errors/unauthorized.error.js +2 -3
  60. package/esm/exception/http-errors/unprocessable-entity.error.js +2 -2
  61. package/esm/exception/opra-exception.js +47 -32
  62. package/esm/exception/resource-errors/resource-not-found.error.js +2 -3
  63. package/esm/exception/wrap-exception.js +16 -16
  64. package/esm/helpers/index.js +1 -1
  65. package/esm/helpers/is-url-string.js +9 -0
  66. package/esm/helpers/object-utils.js +2 -2
  67. package/esm/helpers/responsive-map.js +4 -4
  68. package/esm/helpers/type-guards.js +11 -2
  69. package/esm/http/index.js +2 -9
  70. package/esm/http/opra-url-path.js +246 -0
  71. package/esm/{url → http}/opra-url.js +53 -109
  72. package/esm/i18n/i18n.js +2 -2
  73. package/esm/index.js +0 -2
  74. package/esm/schema/opra-schema.ns.js +1 -1
  75. package/esm/schema/resource/operation.interface.js +1 -0
  76. package/package.json +5 -5
  77. package/types/document/api-document.d.ts +4 -1
  78. package/types/document/data-type/complex-type.d.ts +7 -12
  79. package/types/document/data-type/data-type.d.ts +0 -6
  80. package/types/document/data-type/enum-type.d.ts +2 -4
  81. package/types/document/data-type/mapped-type.d.ts +1 -5
  82. package/types/document/data-type/simple-type.d.ts +2 -4
  83. package/types/document/data-type/union-type.d.ts +1 -5
  84. package/types/document/index.d.ts +2 -0
  85. package/types/document/interfaces/collection-resource.interface.d.ts +10 -0
  86. package/types/document/interfaces/singleton-resource.interface.d.ts +7 -0
  87. package/types/document/interfaces/storage-resource.interface.d.ts +8 -0
  88. package/types/document/resource/collection.d.ts +41 -35
  89. package/types/document/resource/resource.d.ts +1 -0
  90. package/types/document/resource/singleton.d.ts +24 -21
  91. package/types/document/resource/storage.d.ts +14 -17
  92. package/types/document/utils/generate-codec.d.ts +10 -0
  93. package/types/exception/error-issue.d.ts +2 -1
  94. package/types/exception/http-errors/bad-request.error.d.ts +2 -1
  95. package/types/exception/http-errors/failed-dependency.error.d.ts +2 -1
  96. package/types/exception/http-errors/forbidden.error.d.ts +2 -1
  97. package/types/exception/http-errors/internal-server.error.d.ts +2 -1
  98. package/types/exception/http-errors/method-not-allowed.error.d.ts +2 -1
  99. package/types/exception/http-errors/not-acceptable.error.d.ts +2 -1
  100. package/types/exception/http-errors/not-found.error.d.ts +2 -1
  101. package/types/exception/http-errors/unauthorized.error.d.ts +2 -1
  102. package/types/exception/http-errors/unprocessable-entity.error.d.ts +2 -1
  103. package/types/exception/opra-exception.d.ts +13 -8
  104. package/types/exception/wrap-exception.d.ts +1 -1
  105. package/types/helpers/index.d.ts +1 -1
  106. package/types/helpers/is-url-string.d.ts +2 -0
  107. package/types/helpers/object-utils.d.ts +1 -1
  108. package/types/helpers/type-guards.d.ts +3 -0
  109. package/types/http/index.d.ts +2 -9
  110. package/types/http/opra-url-path.d.ts +54 -0
  111. package/types/{url → http}/opra-url.d.ts +9 -13
  112. package/types/index.d.ts +0 -2
  113. package/types/schema/data-type/complex-type.interface.d.ts +1 -1
  114. package/types/schema/opra-schema.ns.d.ts +1 -1
  115. package/types/schema/resource/collection.interface.d.ts +29 -8
  116. package/types/schema/resource/operation.interface.d.ts +3 -0
  117. package/types/schema/resource/singleton.interface.d.ts +5 -5
  118. package/types/schema/resource/storage.interface.d.ts +42 -5
  119. package/cjs/helpers/is-url.js +0 -8
  120. package/cjs/http/codecs/boolean-codec.js +0 -24
  121. package/cjs/http/codecs/date-codec.js +0 -41
  122. package/cjs/http/codecs/filter-codec.js +0 -17
  123. package/cjs/http/codecs/integer-codec.js +0 -19
  124. package/cjs/http/codecs/number-codec.js +0 -24
  125. package/cjs/http/codecs/string-codec.js +0 -23
  126. package/cjs/http/http-params.js +0 -353
  127. package/cjs/http/multipart/batch-multipart.js +0 -170
  128. package/cjs/http/multipart/http-request-content.js +0 -17
  129. package/cjs/http/multipart/http-response-content.js +0 -14
  130. package/cjs/http/multipart/index.js +0 -2
  131. package/cjs/url/index.js +0 -8
  132. package/cjs/url/opra-url-path-component.js +0 -30
  133. package/cjs/url/opra-url-path.js +0 -155
  134. package/cjs/url/utils/decode-path-component.js +0 -41
  135. package/cjs/url/utils/encode-path-component.js +0 -27
  136. package/cjs/utils/path-utils.js +0 -24
  137. package/esm/helpers/is-url.js +0 -4
  138. package/esm/http/codecs/boolean-codec.js +0 -20
  139. package/esm/http/codecs/date-codec.js +0 -37
  140. package/esm/http/codecs/filter-codec.js +0 -13
  141. package/esm/http/codecs/integer-codec.js +0 -15
  142. package/esm/http/codecs/number-codec.js +0 -20
  143. package/esm/http/codecs/string-codec.js +0 -19
  144. package/esm/http/http-params.js +0 -348
  145. package/esm/http/multipart/batch-multipart.js +0 -170
  146. package/esm/http/multipart/http-request-content.js +0 -17
  147. package/esm/http/multipart/http-response-content.js +0 -14
  148. package/esm/http/multipart/index.js +0 -2
  149. package/esm/url/index.js +0 -5
  150. package/esm/url/opra-url-path-component.js +0 -26
  151. package/esm/url/opra-url-path.js +0 -151
  152. package/esm/url/utils/decode-path-component.js +0 -37
  153. package/esm/url/utils/encode-path-component.js +0 -22
  154. package/esm/utils/path-utils.js +0 -19
  155. package/types/helpers/is-url.d.ts +0 -1
  156. package/types/http/codecs/boolean-codec.d.ts +0 -5
  157. package/types/http/codecs/date-codec.d.ts +0 -16
  158. package/types/http/codecs/filter-codec.d.ts +0 -6
  159. package/types/http/codecs/integer-codec.d.ts +0 -11
  160. package/types/http/codecs/number-codec.d.ts +0 -14
  161. package/types/http/codecs/string-codec.d.ts +0 -16
  162. package/types/http/http-params.d.ts +0 -114
  163. package/types/http/interfaces/client-http-headers.interface.d.ts +0 -65
  164. package/types/http/interfaces/server-http-headers.interface.d.ts +0 -1
  165. package/types/http/multipart/batch-multipart.d.ts +0 -0
  166. package/types/http/multipart/http-request-content.d.ts +0 -0
  167. package/types/http/multipart/http-response-content.d.ts +0 -0
  168. package/types/http/multipart/index.d.ts +0 -0
  169. package/types/schema/resource/endpoint.interface.d.ts +0 -29
  170. package/types/url/index.d.ts +0 -5
  171. package/types/url/opra-url-path-component.d.ts +0 -15
  172. package/types/url/opra-url-path.d.ts +0 -36
  173. package/types/url/utils/decode-path-component.d.ts +0 -5
  174. package/types/url/utils/encode-path-component.d.ts +0 -1
  175. package/types/utils/path-utils.d.ts +0 -2
  176. /package/cjs/{http/interfaces/client-http-headers.interface.js → document/interfaces/collection-resource.interface.js} +0 -0
  177. /package/cjs/{http/interfaces/server-http-headers.interface.js → document/interfaces/singleton-resource.interface.js} +0 -0
  178. /package/cjs/{schema/resource/endpoint.interface.js → document/interfaces/storage-resource.interface.js} +0 -0
  179. /package/esm/{http/interfaces/client-http-headers.interface.js → document/interfaces/collection-resource.interface.js} +0 -0
  180. /package/esm/{http/interfaces/server-http-headers.interface.js → document/interfaces/singleton-resource.interface.js} +0 -0
  181. /package/esm/{schema/resource/endpoint.interface.js → document/interfaces/storage-resource.interface.js} +0 -0
@@ -11,10 +11,9 @@ export class ForbiddenError extends OpraException {
11
11
  super(...arguments);
12
12
  this.status = 403;
13
13
  }
14
- setIssue(issue) {
15
- super.setIssue({
14
+ init(issue) {
15
+ super.init({
16
16
  message: translate('error:FORBIDDEN', 'You are not authorized to perform this action'),
17
- severity: 'error',
18
17
  code: 'FORBIDDEN',
19
18
  ...issue
20
19
  });
@@ -9,10 +9,9 @@ export class InternalServerError extends OpraException {
9
9
  super(...arguments);
10
10
  this.status = 500;
11
11
  }
12
- setIssue(issue) {
13
- super.setIssue({
12
+ init(issue) {
13
+ super.init({
14
14
  message: translate('error:INTERNAL_SERVER_ERROR', 'Internal server error'),
15
- severity: 'error',
16
15
  code: 'INTERNAL_SERVER_ERROR',
17
16
  ...issue
18
17
  });
@@ -10,10 +10,9 @@ export class MethodNotAllowedError extends OpraException {
10
10
  super(...arguments);
11
11
  this.status = 405;
12
12
  }
13
- setIssue(issue) {
14
- super.setIssue({
13
+ init(issue) {
14
+ super.init({
15
15
  message: translate('error:METHOD_NOT_ALLOWED', 'Method not allowed'),
16
- severity: 'error',
17
16
  code: 'METHOD_NOT_ALLOWED',
18
17
  ...issue
19
18
  });
@@ -10,10 +10,9 @@ export class NotAcceptableError extends OpraException {
10
10
  super(...arguments);
11
11
  this.status = 406;
12
12
  }
13
- setIssue(issue) {
14
- super.setIssue({
13
+ init(issue) {
14
+ super.init({
15
15
  message: translate('error:NOT_ACCEPTABLE', 'Not Acceptable'),
16
- severity: 'error',
17
16
  code: 'NOT_ACCEPTABLE',
18
17
  ...issue
19
18
  });
@@ -13,10 +13,9 @@ export class NotFoundError extends OpraException {
13
13
  super(...arguments);
14
14
  this.status = 404;
15
15
  }
16
- setIssue(issue) {
17
- super.setIssue({
16
+ init(issue) {
17
+ super.init({
18
18
  message: translate('error:NOT_FOUND', 'Not found'),
19
- severity: 'error',
20
19
  code: 'NOT_FOUND',
21
20
  ...issue
22
21
  });
@@ -10,10 +10,9 @@ export class UnauthorizedError extends OpraException {
10
10
  super(...arguments);
11
11
  this.status = 401;
12
12
  }
13
- setIssue(issue) {
14
- super.setIssue({
13
+ init(issue) {
14
+ super.init({
15
15
  message: translate('error:UNAUTHORIZED', 'You have not been authenticated to perform this action'),
16
- severity: 'error',
17
16
  code: 'UNAUTHORIZED',
18
17
  ...issue
19
18
  });
@@ -9,8 +9,8 @@ export class UnprocessableEntityError extends OpraException {
9
9
  super(...arguments);
10
10
  this.status = 422;
11
11
  }
12
- setIssue(issue) {
13
- super.setIssue({
12
+ init(issue) {
13
+ super.init({
14
14
  message: translate('error:UNPROCESSABLE_ENTITY', 'Unprocessable entity'),
15
15
  severity: 'error',
16
16
  code: 'UNPROCESSABLE_ENTITY',
@@ -1,52 +1,67 @@
1
+ import { omitUndefined } from '../helpers/index.js';
1
2
  import { i18n } from '../i18n/index.js';
3
+ const inDevelopment = (process.env.NODE_ENV || '').startsWith('dev');
2
4
  /**
3
5
  * Defines the base Opra exception, which is handled by the default Exceptions Handler.
4
6
  */
5
7
  export class OpraException extends Error {
6
- constructor(issue, cause) {
7
- super('');
8
+ constructor(issue, arg1, arg2) {
9
+ super('Unknown error');
8
10
  this.status = 500;
9
- this._initName();
11
+ let cause = arg1 && arg1 instanceof Error ? arg1 : undefined;
12
+ this.status = (typeof arg1 === 'number' ? arg1 : Number(arg2)) || 500;
10
13
  if (issue instanceof Error)
11
14
  cause = issue;
12
- if (cause) {
15
+ // noinspection SuspiciousTypeOfGuard
16
+ if (cause && cause instanceof Error) {
13
17
  this.cause = cause;
14
18
  if (cause.stack)
15
19
  this.stack = cause.stack;
16
20
  }
17
- this._init(issue || cause || 'Unknown error');
18
- this.message = i18n.deep(this.issue.message);
19
- }
20
- get issue() {
21
- return this._issue;
22
- }
23
- setIssue(issue) {
24
- this._issue = {
25
- message: 'Unknown error',
26
- severity: 'error',
27
- ...issue,
28
- };
21
+ if (typeof issue === 'string')
22
+ this.initString(issue);
23
+ else if (issue instanceof Error)
24
+ this.initError(issue);
25
+ else if (issue && typeof issue === 'object')
26
+ this.init(issue);
27
+ this.message = this.message || this.constructor.name;
29
28
  }
30
29
  setStatus(status) {
31
30
  this.status = status;
32
31
  return this;
33
32
  }
34
- _initName() {
35
- this.name = this.constructor.name;
33
+ toString() {
34
+ return i18n.deep(this.message);
36
35
  }
37
- _init(issue) {
38
- if (issue instanceof Error) {
39
- if (typeof issue.status === 'number')
40
- this.status = issue.status;
41
- else if (typeof issue.getStatus === 'function')
42
- this.status = issue.getStatus();
43
- this.setIssue({ message: issue.message });
44
- }
45
- else if (typeof issue === 'object') {
46
- this.setIssue(issue);
47
- }
48
- else {
49
- this.setIssue({ message: String(issue) });
50
- }
36
+ toJSON() {
37
+ return omitUndefined({
38
+ message: this.message,
39
+ severity: this.severity,
40
+ system: this.system,
41
+ code: this.code,
42
+ details: this.details,
43
+ stack: inDevelopment ? this.stack?.split('\n') : undefined
44
+ }, true);
45
+ }
46
+ init(issue) {
47
+ this.message = issue.message || this.constructor.name;
48
+ this.severity = issue.severity || 'error';
49
+ this.system = issue.system;
50
+ this.code = issue.code;
51
+ this.details = issue.details;
52
+ }
53
+ initString(issue) {
54
+ this.message = String(issue || '') || this.constructor.name;
55
+ this.severity = 'error';
56
+ this.code = this.constructor.name;
57
+ }
58
+ initError(issue) {
59
+ if (typeof issue.status === 'number')
60
+ this.status = issue.status;
61
+ else if (typeof issue.getStatus === 'function')
62
+ this.status = issue.getStatus();
63
+ this.message = issue.message;
64
+ this.severity = issue.severity || 'error';
65
+ this.code = issue.code || (issue.constructor.name);
51
66
  }
52
67
  }
@@ -7,14 +7,13 @@ import { OpraException } from '../opra-exception.js';
7
7
  export class ResourceNotFoundError extends OpraException {
8
8
  constructor(resource, keyValue, cause) {
9
9
  super({
10
- message: translate(`error:RESOURCE_NOT_FOUND`, { resource: resource + (keyValue ? '@' + keyValue : '') }, `The resource '{{resource}}' could not be found`),
10
+ message: translate(`error:RESOURCE_NOT_FOUND`, { resource: resource + (keyValue ? '@' + keyValue : '') }, `The resource '{{resource}}' not found`),
11
11
  severity: 'error',
12
12
  code: 'RESOURCE_NOT_FOUND',
13
13
  details: {
14
14
  resource,
15
15
  key: keyValue
16
16
  }
17
- }, cause);
18
- this.status = 404;
17
+ }, cause, 404);
19
18
  }
20
19
  }
@@ -7,32 +7,32 @@ import { NotFoundError } from './http-errors/not-found.error.js';
7
7
  import { UnauthorizedError } from './http-errors/unauthorized.error.js';
8
8
  import { UnprocessableEntityError } from './http-errors/unprocessable-entity.error.js';
9
9
  import { OpraException } from './opra-exception.js';
10
- export function wrapException(e) {
11
- if (e instanceof OpraException)
12
- return e;
10
+ export function wrapException(error) {
11
+ if (error instanceof OpraException)
12
+ return error;
13
13
  let status = 500;
14
- if (typeof e.status === 'number')
15
- status = e.status;
16
- else if (typeof e.getStatus === 'function')
17
- status = e.getStatus();
14
+ if (typeof error.status === 'number')
15
+ status = error.status;
16
+ else if (typeof error.getStatus === 'function')
17
+ status = error.getStatus();
18
18
  switch (status) {
19
19
  case 400:
20
- return new BadRequestError(e);
20
+ return new BadRequestError(error);
21
21
  case 401:
22
- return new UnauthorizedError(e);
22
+ return new UnauthorizedError(error);
23
23
  case 403:
24
- return new ForbiddenError(e);
24
+ return new ForbiddenError(error);
25
25
  case 404:
26
- return new NotFoundError(e);
26
+ return new NotFoundError(error);
27
27
  case 405:
28
- return new MethodNotAllowedError(e);
28
+ return new MethodNotAllowedError(error);
29
29
  case 406:
30
- return new NotAcceptableError(e);
30
+ return new NotAcceptableError(error);
31
31
  case 422:
32
- return new UnprocessableEntityError(e);
32
+ return new UnprocessableEntityError(error);
33
33
  case 424:
34
- return new FailedDependencyError(e);
34
+ return new FailedDependencyError(error);
35
35
  default:
36
- return new FailedDependencyError(e);
36
+ return new FailedDependencyError(error);
37
37
  }
38
38
  }
@@ -1,6 +1,6 @@
1
1
  export * from './function-utils.js';
2
2
  export * from './get-stack-filename.js';
3
- export * from './is-url.js';
3
+ export * from './is-url-string.js';
4
4
  export * from './mixin-utils.js';
5
5
  export * from './object-utils.js';
6
6
  export * from './path-to-object-tree.js';
@@ -0,0 +1,9 @@
1
+ import { URL } from 'url';
2
+ const URL_PATTERN = /^(https?:\/\/.)[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/i;
3
+ export function isUrlString(url) {
4
+ return URL_PATTERN.test(url);
5
+ }
6
+ export const isAbsoluteUrl = (urlString) => {
7
+ return !urlString.includes('://') &&
8
+ (new URL(urlString, 'http://tempuri.org/')).host !== 'tempuri.org';
9
+ };
@@ -12,13 +12,13 @@ export function cloneObject(obj, jsonOnly) {
12
12
  }
13
13
  });
14
14
  }
15
- export function omitUndefined(obj) {
15
+ export function omitUndefined(obj, recursive) {
16
16
  if (!(obj && typeof obj === 'object'))
17
17
  return obj;
18
18
  for (const k of Object.keys(obj)) {
19
19
  if (obj[k] === undefined)
20
20
  delete obj[k];
21
- else if (typeof obj[k] === 'object')
21
+ else if (recursive && typeof obj[k] === 'object')
22
22
  omitUndefined(obj[k]);
23
23
  }
24
24
  return obj;
@@ -2,10 +2,10 @@ var _a, _b, _c, _d;
2
2
  function isMap(v) {
3
3
  return v && typeof v.forEach === 'function';
4
4
  }
5
- const kKeyMap = Symbol('kKeyMap');
6
- const kKeyOrder = Symbol('kKeyOrder');
7
- const kWellKnownKeys = Symbol('kWellKnownKeys');
8
- const kOptions = Symbol('kOptions');
5
+ const kKeyMap = Symbol.for('kKeyMap');
6
+ const kKeyOrder = Symbol.for('kKeyOrder');
7
+ const kWellKnownKeys = Symbol.for('kWellKnownKeys');
8
+ const kOptions = Symbol.for('kOptions');
9
9
  /**
10
10
  * A Map implementation that supports case-insensitivity and ordered keys
11
11
  */
@@ -11,13 +11,15 @@ export function isStream(stream) {
11
11
  }
12
12
  export function isReadable(x) {
13
13
  return isStream(x)
14
- && x.readable !== false
15
14
  && typeof x._read === 'function'
16
15
  && typeof x._readableState === 'object';
17
16
  }
17
+ export function isWritable(x) {
18
+ return isStream(x)
19
+ && typeof x._write === 'function';
20
+ }
18
21
  export function isReadableStream(x) {
19
22
  return isStream(x)
20
- && x.readable !== false
21
23
  && typeof x.getReader === 'function'
22
24
  && typeof x.pipeThrough === 'function'
23
25
  && typeof x.pipeTo === 'function';
@@ -38,6 +40,13 @@ export function isFormData(x) {
38
40
  }
39
41
  export function isURL(x) {
40
42
  return x !== null
43
+ && typeof x == 'object'
41
44
  && typeof x.host === 'string'
42
45
  && typeof x.href === 'string';
43
46
  }
47
+ export function isIterable(x) {
48
+ return Symbol.iterator in x;
49
+ }
50
+ export function isAsyncIterable(x) {
51
+ return Symbol.asyncIterator in x;
52
+ }
package/esm/http/index.js CHANGED
@@ -1,12 +1,5 @@
1
- export * from './http-params.js';
1
+ export * from './opra-url.js';
2
+ export * from './opra-url-path.js';
2
3
  export * from './enums/http-headers-codes.enum.js';
3
4
  export * from './enums/http-status-codes.enum.js';
4
5
  export * from './enums/http-status-messages.js';
5
- export * from './interfaces/client-http-headers.interface.js';
6
- export * from './interfaces/server-http-headers.interface.js';
7
- export * from './codecs/date-codec.js';
8
- export * from './codecs/boolean-codec.js';
9
- export * from './codecs/filter-codec.js';
10
- export * from './codecs/integer-codec.js';
11
- export * from './codecs/number-codec.js';
12
- export * from './codecs/string-codec.js';
@@ -0,0 +1,246 @@
1
+ var _a;
2
+ import { splitString, tokenize } from 'fast-tokenizer';
3
+ import isPlainObject from 'putil-isplainobject';
4
+ const nodeInspectCustom = Symbol.for('nodejs.util.inspect.custom');
5
+ const kLength = Symbol.for('kLength');
6
+ const pathComponentRegEx = /^([^/?#:@]+)(?:@([^/?#:]*))?(?:::(.*))?$/;
7
+ const decimalPattern = /^[+-]?\d+(\.\d+)?$/;
8
+ const booleanPattern = /^true|false$/;
9
+ /**
10
+ * @class OpraURLPath
11
+ */
12
+ export class OpraURLPath {
13
+ constructor(...init) {
14
+ this[_a] = 0;
15
+ this._resolve(init.filter(x => x));
16
+ }
17
+ get length() {
18
+ return this[kLength];
19
+ }
20
+ resolve(...items) {
21
+ this._resolve(items);
22
+ return this;
23
+ }
24
+ join(...items) {
25
+ this._resolve(items, true);
26
+ return this;
27
+ }
28
+ isRelativeTo(basePath) {
29
+ basePath = basePath instanceof OpraURLPath ? basePath : new OpraURLPath(basePath);
30
+ let i;
31
+ for (i = 0; i < basePath.length; i++) {
32
+ if (String(this[i]) !== String(basePath[i]))
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ forEach(callback) {
38
+ let i = 0;
39
+ for (const item of this.values()) {
40
+ callback.call(this, item, i++, this);
41
+ }
42
+ }
43
+ values() {
44
+ const arr = new Array(this.length);
45
+ for (let i = 0; i < this.length; i++)
46
+ arr[i] = this[i];
47
+ return arr.values();
48
+ }
49
+ toString() {
50
+ const v = Array.from(this).join('/');
51
+ return v ? '/' + v : '';
52
+ }
53
+ /* istanbul ignore next */
54
+ [(_a = kLength, nodeInspectCustom)]() {
55
+ return `(UrlPath [${this.toString()}])`;
56
+ }
57
+ [Symbol.iterator]() {
58
+ return this.values();
59
+ }
60
+ _resolve(items, join) {
61
+ let paths = (Array.isArray(items) ? items : [items]).map(item => {
62
+ if (typeof item === 'object' && !(item instanceof OpraURLPath || item instanceof OpraURLPathComponent))
63
+ item = new OpraURLPathComponent(item);
64
+ item = String(item);
65
+ // Remove url parts coming after path (query, hash parts)
66
+ if (item.includes('?'))
67
+ item = splitString(item, {
68
+ delimiters: '?',
69
+ quotes: true,
70
+ brackets: true,
71
+ keepBrackets: true,
72
+ keepQuotes: true
73
+ })[0];
74
+ if (item.includes('#'))
75
+ item = splitString(item, {
76
+ delimiters: '#',
77
+ quotes: true,
78
+ brackets: true,
79
+ keepBrackets: true,
80
+ keepQuotes: true
81
+ })[0];
82
+ return join ? removeLeadingSeparator(item) : item;
83
+ });
84
+ const oldLength = this.length;
85
+ let n = 0;
86
+ if (!join) {
87
+ for (n = paths.length - 1; n >= 0; n--) {
88
+ if (String(items[n]).startsWith('/'))
89
+ break;
90
+ }
91
+ if (n > 0)
92
+ paths = paths.slice(n);
93
+ }
94
+ const newPath = paths[0]?.startsWith('/') ? [] : Array.from(this).map(String);
95
+ for (let i = 0; i < paths.length; i++) {
96
+ const pathTokenizer = tokenize(paths[i], { delimiters: '/', quotes: true, brackets: true });
97
+ for (const x of pathTokenizer) {
98
+ if (!x)
99
+ continue;
100
+ if (x.startsWith('.')) {
101
+ if (x === '.')
102
+ continue;
103
+ if (x === '..') {
104
+ newPath.pop();
105
+ continue;
106
+ }
107
+ throw new TypeError('Invalid path string');
108
+ }
109
+ newPath.push(x);
110
+ }
111
+ }
112
+ for (let i = 0; i < newPath.length; i++) {
113
+ this[i] = OpraURLPathComponent.parse(newPath[i]);
114
+ }
115
+ for (let i = newPath.length; i < oldLength; i++) {
116
+ delete this[i];
117
+ }
118
+ this[kLength] = newPath.length;
119
+ }
120
+ static join(...items) {
121
+ const instance = new OpraURLPath();
122
+ instance.join(...items);
123
+ return instance;
124
+ }
125
+ static resolve(...items) {
126
+ return new OpraURLPath(...items);
127
+ }
128
+ static relative(source, basePath) {
129
+ source = source instanceof OpraURLPath ? source : new OpraURLPath(source);
130
+ basePath = basePath instanceof OpraURLPath ? basePath : new OpraURLPath(basePath);
131
+ let i;
132
+ for (i = 0; i < basePath.length; i++) {
133
+ if (String(source[i]) !== String(basePath[i]))
134
+ return;
135
+ }
136
+ return new OpraURLPath(Array.from(source).slice(i).join('/'));
137
+ }
138
+ }
139
+ /**
140
+ *
141
+ * @class OpraURLPathComponent
142
+ */
143
+ class OpraURLPathComponent {
144
+ constructor(init) {
145
+ this.resource = init.resource;
146
+ this.key = init.key;
147
+ this.args = init.args;
148
+ this.typeCast = init.typeCast;
149
+ }
150
+ toString() {
151
+ let out = encodeURIComponent(this.resource).replace(/%24/, '$');
152
+ if (this.key) {
153
+ if (typeof this.key === 'object' && isPlainObject(this.key)) {
154
+ const arr = [];
155
+ for (const k of Object.keys(this.key)) {
156
+ let v = this.key[k];
157
+ if (typeof v === 'number' || typeof v === 'boolean')
158
+ v = String(v);
159
+ else
160
+ v = '"' + encodeURIComponent(String(v)) + '"';
161
+ arr.push(encodeURIComponent(k) + '=' + v);
162
+ }
163
+ out += '@' + arr.join(';');
164
+ }
165
+ else
166
+ out += '@' + encodeURIComponent(String(this.key));
167
+ }
168
+ if (this.args) {
169
+ const arr = [];
170
+ for (const k of Object.keys(this.args)) {
171
+ arr.push(encodeURIComponent(k) + '=' + encodeURIComponent(String(this.args[k])));
172
+ }
173
+ out += '(' + arr.join(';') + ')';
174
+ }
175
+ if (this.typeCast)
176
+ out += '::' + encodeURIComponent(this.typeCast);
177
+ return out;
178
+ }
179
+ /* istanbul ignore next */
180
+ [nodeInspectCustom]() {
181
+ return this.toString();
182
+ }
183
+ /**
184
+ * Factory method.
185
+ * @param input
186
+ */
187
+ static parse(input) {
188
+ const m = pathComponentRegEx.exec(input);
189
+ if (!m)
190
+ throw Object.assign(new TypeError('Invalid Opra URL'), {
191
+ code: 'ERR_INVALID_OPRA_URL',
192
+ input,
193
+ });
194
+ let key;
195
+ if (m[2]) {
196
+ const s = decodeURIComponent(m[2]);
197
+ const b = splitString(s, { delimiters: ';', quotes: true, escape: false, keepQuotes: true, keepBrackets: true });
198
+ for (const n of b) {
199
+ const c = splitString(n, { delimiters: '=', quotes: true, escape: false, keepQuotes: true, keepBrackets: true });
200
+ if ((b.length > 1 && c.length < 2) ||
201
+ (key &&
202
+ (c.length >= 2 && typeof key !== 'object') ||
203
+ (c.length < 2 && typeof key === 'object')))
204
+ throw Object.assign(new TypeError('Invalid Opra URL. name:value pair required for multiple key format'), {
205
+ pathComponent: input,
206
+ code: 'ERR_INVALID_OPRA_URL'
207
+ });
208
+ if (c.length >= 2) {
209
+ key = key || {};
210
+ const k = c.shift() || '';
211
+ let v = c.join('=');
212
+ if (decimalPattern.test(v))
213
+ v = Number(v);
214
+ else if (booleanPattern.test(v))
215
+ v = Boolean(v);
216
+ else if (v.startsWith('"') && v.endsWith('"'))
217
+ v = v.substring(1, v.length - 1);
218
+ else if (v.startsWith("'") && v.endsWith("'"))
219
+ v = v.substring(1, v.length - 1);
220
+ key[k] = v;
221
+ }
222
+ else {
223
+ if (decimalPattern.test(c[0]))
224
+ key = Number(c[0]);
225
+ else if (booleanPattern.test(c[0]))
226
+ key = Boolean(c[0]);
227
+ else
228
+ key = c[0];
229
+ }
230
+ }
231
+ return new OpraURLPathComponent({
232
+ resource: decodeURIComponent(m[1]),
233
+ key,
234
+ typeCast: m[3] ? decodeURIComponent(m[3]) : undefined
235
+ });
236
+ }
237
+ return new OpraURLPathComponent({
238
+ resource: decodeURIComponent(m[1]),
239
+ typeCast: m[3] ? decodeURIComponent(m[3]) : undefined
240
+ });
241
+ }
242
+ }
243
+ function removeLeadingSeparator(s) {
244
+ const m = /^\/*(.*)/.exec(s);
245
+ return m?.[1] || s;
246
+ }