@api-client/core 0.6.3 → 0.6.6

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 (72) hide show
  1. package/build/browser.d.ts +9 -1
  2. package/build/browser.js +8 -0
  3. package/build/browser.js.map +1 -1
  4. package/build/index.d.ts +9 -1
  5. package/build/index.js +8 -0
  6. package/build/index.js.map +1 -1
  7. package/build/src/Platform.d.ts +12 -0
  8. package/build/src/Platform.js +13 -0
  9. package/build/src/Platform.js.map +1 -0
  10. package/build/src/authorization/OAuth2Authorization.d.ts +1 -1
  11. package/build/src/authorization/OidcAuthorization.d.ts +1 -0
  12. package/build/src/authorization/OidcAuthorization.js +3 -0
  13. package/build/src/authorization/OidcAuthorization.js.map +1 -1
  14. package/build/src/authorization/Utils.js +1 -1
  15. package/build/src/authorization/Utils.js.map +1 -1
  16. package/build/src/authorization/lib/SecurityProcessor.d.ts +33 -0
  17. package/build/src/authorization/lib/SecurityProcessor.js +118 -0
  18. package/build/src/authorization/lib/SecurityProcessor.js.map +1 -0
  19. package/build/src/authorization/lib/Utils.d.ts +41 -0
  20. package/build/src/authorization/lib/Utils.js +85 -0
  21. package/build/src/authorization/lib/Utils.js.map +1 -0
  22. package/build/src/lib/transformers/PayloadSerializer.d.ts +6 -3
  23. package/build/src/lib/transformers/PayloadSerializer.js +5 -3
  24. package/build/src/lib/transformers/PayloadSerializer.js.map +1 -1
  25. package/build/src/models/RequestUiMeta.d.ts +2 -2
  26. package/build/src/models/SerializablePayload.js +2 -1
  27. package/build/src/models/SerializablePayload.js.map +1 -1
  28. package/build/src/models/data/DataAssociation.d.ts +76 -0
  29. package/build/src/models/data/DataAssociation.js +151 -0
  30. package/build/src/models/data/DataAssociation.js.map +1 -0
  31. package/build/src/models/data/DataAssociationSchema.d.ts +32 -0
  32. package/build/src/models/data/DataAssociationSchema.js +2 -0
  33. package/build/src/models/data/DataAssociationSchema.js.map +1 -0
  34. package/build/src/models/data/DataEntity.d.ts +195 -0
  35. package/build/src/models/data/DataEntity.js +415 -0
  36. package/build/src/models/data/DataEntity.js.map +1 -0
  37. package/build/src/models/data/DataModel.d.ts +74 -0
  38. package/build/src/models/data/DataModel.js +173 -0
  39. package/build/src/models/data/DataModel.js.map +1 -0
  40. package/build/src/models/data/DataNamespace.d.ts +174 -0
  41. package/build/src/models/data/DataNamespace.js +424 -0
  42. package/build/src/models/data/DataNamespace.js.map +1 -0
  43. package/build/src/models/data/DataProperty.d.ts +159 -0
  44. package/build/src/models/data/DataProperty.js +216 -0
  45. package/build/src/models/data/DataProperty.js.map +1 -0
  46. package/build/src/models/data/DataPropertySchema.d.ts +125 -0
  47. package/build/src/models/data/DataPropertySchema.js +33 -0
  48. package/build/src/models/data/DataPropertySchema.js.map +1 -0
  49. package/build/src/models/legacy/Normalizer.js +1 -1
  50. package/build/src/models/legacy/Normalizer.js.map +1 -1
  51. package/build/src/runtime/store/FilesSdk.d.ts +4 -2
  52. package/build/src/runtime/store/FilesSdk.js +1 -1
  53. package/build/src/runtime/store/FilesSdk.js.map +1 -1
  54. package/package.json +3 -3
  55. package/src/Platform.ts +12 -0
  56. package/src/authorization/OAuth2Authorization.ts +1 -1
  57. package/src/authorization/OidcAuthorization.ts +4 -0
  58. package/src/authorization/Utils.ts +1 -1
  59. package/src/authorization/lib/SecurityProcessor.ts +141 -0
  60. package/src/authorization/lib/Utils.ts +89 -0
  61. package/src/lib/transformers/PayloadSerializer.ts +12 -4
  62. package/src/models/RequestUiMeta.ts +2 -2
  63. package/src/models/SerializablePayload.ts +2 -1
  64. package/src/models/data/DataAssociation.ts +189 -0
  65. package/src/models/data/DataAssociationSchema.ts +32 -0
  66. package/src/models/data/DataEntity.ts +496 -0
  67. package/src/models/data/DataModel.ts +206 -0
  68. package/src/models/data/DataNamespace.ts +503 -0
  69. package/src/models/data/DataProperty.ts +306 -0
  70. package/src/models/data/DataPropertySchema.ts +156 -0
  71. package/src/models/legacy/Normalizer.ts +1 -1
  72. package/src/runtime/store/FilesSdk.ts +5 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The API Client's core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.6.3",
4
+ "version": "0.6.6",
5
5
  "license": "Apache-2.0",
6
6
  "main": "build/index.js",
7
7
  "module": "build/index.js",
@@ -69,8 +69,8 @@
69
69
  "tsc:watch": "tsc --watch",
70
70
  "test:browser": "wtr --playwright --browsers chromium firefox webkit --coverage",
71
71
  "test:browser:watch": "wtr --watch --playwright --browsers chromium",
72
- "test:mocha": "npm run build-ts && mocha",
73
- "test": "npm run test:mocha && npm run test:browser"
72
+ "test:node": "npm run build-ts && mocha",
73
+ "test": "npm run test:node && npm run test:browser"
74
74
  },
75
75
  "husky": {
76
76
  "hooks": {
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether the current platform has the `FormData` interface
3
+ */
4
+ export const hasFormData: boolean = typeof FormData === 'function';
5
+ /**
6
+ * Whether the current platform has Blob interface
7
+ */
8
+ export const hasBlob: boolean = typeof Blob === 'function';
9
+ /**
10
+ * Whether the current platform has the `Buffer` interface.
11
+ */
12
+ export const hasBuffer: boolean = typeof Buffer === 'function';
@@ -159,7 +159,7 @@ export class OAuth2Authorization {
159
159
  * Performs the authorization.
160
160
  * @returns Promise resolved to the token info.
161
161
  */
162
- authorize(): Promise<ITokenInfo> {
162
+ authorize(): Promise<ITokenInfo | any> {
163
163
  return new Promise((resolve, reject) => {
164
164
  this[resolveFunction] = resolve;
165
165
  this[rejectFunction] = reject;
@@ -4,6 +4,10 @@ import { OAuth2Authorization, grantResponseMapping, reportOAuthError, resolveFun
4
4
  import { nonceGenerator } from './Utils.js';
5
5
 
6
6
  export class OidcAuthorization extends OAuth2Authorization {
7
+ authorize(): Promise<(IOidcTokenInfo|IOidcTokenError)[]> {
8
+ return super.authorize();
9
+ }
10
+
7
11
  /**
8
12
  * @returns The parameters to build popup URL.
9
13
  */
@@ -74,7 +74,7 @@ export function camel(name: string): string | undefined {
74
74
  while ((l = name[i])) {
75
75
  if ((l === "_" || l === "-") && i + 1 < name.length) {
76
76
  // eslint-disable-next-line no-param-reassign
77
- name = name.substr(0, i) + name[i + 1].toUpperCase() + name.substr(i + 2);
77
+ name = name.substring(0, i) + name[i + 1].toUpperCase() + name.substring(i + 2);
78
78
  changed = true;
79
79
  }
80
80
  // eslint-disable-next-line no-plusplus
@@ -0,0 +1,141 @@
1
+ import { IBasicAuthorization, IBearerAuthorization, IOAuth2Authorization, IOidcAuthorization, IOidcTokenInfo } from "../../models/Authorization.js";
2
+ import { IRequestAuthorization, RequestAuthorization } from "../../models/RequestAuthorization.js";
3
+ import { IHttpRequest } from "../../models/HttpRequest.js";
4
+ import { Headers } from '../../lib/headers/Headers.js';
5
+ import { UrlProcessor } from "../../lib/parsers/UrlProcessor.js";
6
+ import { UrlEncoder } from "../../lib/parsers/UrlEncoder.js";
7
+ import { hasBuffer } from '../../Platform.js';
8
+ import {
9
+ normalizeType,
10
+ METHOD_BASIC,
11
+ METHOD_BEARER,
12
+ METHOD_OAUTH2,
13
+ METHOD_OIDC,
14
+ } from "./Utils.js";
15
+
16
+ export interface IAuthApplyOptions {
17
+ /**
18
+ * When set it won't change the originating authorization objects.
19
+ * By default it sets the authorization's `enabled` property to `false` after applying the
20
+ * value to the request.
21
+ */
22
+ immutable?: boolean;
23
+ }
24
+
25
+ export class SecurityProcessor {
26
+ /**
27
+ * Applies authorization configuration to the request object.
28
+ */
29
+ static applyAuthorization(request: IHttpRequest, authorization: (IRequestAuthorization | RequestAuthorization)[], opts: IAuthApplyOptions = {}): void {
30
+ if (!Array.isArray(authorization) || !authorization.length) {
31
+ return;
32
+ }
33
+
34
+ for (const auth of authorization) {
35
+ if (!auth.enabled || !auth.config) {
36
+ continue;
37
+ }
38
+
39
+ switch (normalizeType(auth.type)) {
40
+ case METHOD_BASIC:
41
+ SecurityProcessor.applyBasicAuth(request, auth.config as IBasicAuthorization);
42
+ if (!opts.immutable) {
43
+ auth.enabled = false;
44
+ }
45
+ break;
46
+ case METHOD_OAUTH2:
47
+ SecurityProcessor.applyOAuth2(request, auth.config as IOAuth2Authorization);
48
+ if (!opts.immutable) {
49
+ auth.enabled = false;
50
+ }
51
+ break;
52
+ case METHOD_OIDC:
53
+ SecurityProcessor.applyOpenId(request, auth.config as IOidcAuthorization);
54
+ if (!opts.immutable) {
55
+ auth.enabled = false;
56
+ }
57
+ break;
58
+ case METHOD_BEARER:
59
+ SecurityProcessor.applyBearer(request, auth.config as IBearerAuthorization);
60
+ if (!opts.immutable) {
61
+ auth.enabled = false;
62
+ }
63
+ break;
64
+ default:
65
+ }
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Injects basic auth header into the request headers.
71
+ */
72
+ static applyBasicAuth(request: IHttpRequest, config: IBasicAuthorization): void {
73
+ const { username, password } = config;
74
+ if (!username) {
75
+ return;
76
+ }
77
+ const hash = `${username}:${password || ''}`;
78
+ const value = hasBuffer ? Buffer.from(hash).toString('base64') : btoa(hash);
79
+
80
+ const headers = new Headers(request.headers || '');
81
+ headers.append('authorization', `Basic ${value}`);
82
+ request.headers = headers.toString();
83
+ }
84
+
85
+ /**
86
+ * Injects oauth 2 auth header into the request headers.
87
+ */
88
+ static applyOAuth2(request: IHttpRequest, config: IOAuth2Authorization): void {
89
+ const { accessToken, tokenType = 'Bearer', deliveryMethod = 'header', deliveryName = 'authorization' } = config;
90
+ if (!accessToken) {
91
+ return;
92
+ }
93
+ const value = `${tokenType} ${accessToken}`;
94
+ if (deliveryMethod === 'header') {
95
+ const headers = new Headers(request.headers || '');
96
+ headers.append(deliveryName, value);
97
+ request.headers = headers.toString();
98
+ } else if (deliveryMethod === 'query') {
99
+ const { url } = request;
100
+ try {
101
+ const parser = new UrlProcessor(url);
102
+ parser.search.append(UrlEncoder.encodeQueryString(deliveryName, true), UrlEncoder.encodeQueryString(value, true));
103
+ request.url = parser.toString();
104
+ } catch (e) {
105
+ // ...
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Injects OpenID Connect auth header into the request headers.
112
+ */
113
+ static applyOpenId(request: IHttpRequest, config: IOidcAuthorization): void {
114
+ const { accessToken, tokens, tokenInUse } = config;
115
+ if (accessToken) {
116
+ SecurityProcessor.applyOAuth2(request, config);
117
+ } else if (Array.isArray(tokens) && typeof tokenInUse === 'number') {
118
+ const data = tokens[tokenInUse] as IOidcTokenInfo;
119
+ if (data && data.accessToken) {
120
+ const copy = { ...config };
121
+ copy.accessToken = data.accessToken;
122
+ SecurityProcessor.applyOAuth2(request, copy);
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Injects bearer auth header into the request headers.
129
+ */
130
+ static applyBearer(request: IHttpRequest, config: IBearerAuthorization): void {
131
+ const { token } = config;
132
+ if (!token) {
133
+ return;
134
+ }
135
+ const value = `Bearer ${token}`;
136
+
137
+ const headers = new Headers(request.headers || '');
138
+ headers.append('authorization', value);
139
+ request.headers = headers.toString();
140
+ }
141
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Normalizes type name to a string identifier.
3
+ * It casts input to a string and lowercase it.
4
+ * @param type Type value
5
+ * @return Normalized value.
6
+ */
7
+ export const normalizeType = (type?: string): string => String(type).toLowerCase();
8
+
9
+ export const METHOD_BASIC = "basic";
10
+ export const METHOD_BEARER = "bearer";
11
+ export const METHOD_NTLM = "ntlm";
12
+ export const METHOD_DIGEST = "digest";
13
+ export const METHOD_OAUTH2 = "oauth 2";
14
+ export const METHOD_OIDC = "open id";
15
+ export const METHOD_CC = 'client certificate';
16
+ export const CUSTOM_CREDENTIALS = "Custom credentials";
17
+
18
+ /**
19
+ * @param value The value to validate
20
+ * @returns True if the redirect URI can be considered valid.
21
+ */
22
+ export function validateRedirectUri(value: unknown): boolean {
23
+ let result = true;
24
+ if (!value || typeof value !== 'string') {
25
+ result = false;
26
+ }
27
+ // the redirect URI can have any value, especially for installed apps which
28
+ // may use custom schemes. We do very basic sanity check for any script content
29
+ // validation to make sure we are not passing any script.
30
+ if (result && String(value).startsWith('javascript:')) {
31
+ result = false;
32
+ }
33
+ return result;
34
+ }
35
+
36
+ /**
37
+ * Generates client nonce for Digest authorization.
38
+ *
39
+ * @return Generated client nonce.
40
+ */
41
+ export function generateCnonce(): string {
42
+ const characters = 'abcdef0123456789';
43
+ let token = '';
44
+ for (let i = 0; i < 16; i++) {
45
+ const randNum = Math.round(Math.random() * characters.length);
46
+ token += characters.substring(randNum, 1);
47
+ }
48
+ return token;
49
+ }
50
+
51
+ /**
52
+ * Generates `state` parameter for the OAuth2 call.
53
+ *
54
+ * @return Generated state string.
55
+ */
56
+ export function generateState(): string {
57
+ let text = '';
58
+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
59
+ for (let i = 0; i < 6; i++) {
60
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
61
+ }
62
+ return text;
63
+ }
64
+
65
+ /**
66
+ * When defined and the `url` is a relative path staring with `/` then it
67
+ * adds base URI to the path and returns concatenated value.
68
+ *
69
+ * @param url The URL to process
70
+ * @param baseUri Base URI to use.
71
+ * @returns Final URL value.
72
+ */
73
+ export function readUrlValue(url?: string, baseUri?: string): string {
74
+ if (!url) {
75
+ return '';
76
+ }
77
+ const result = String(url);
78
+ if (!baseUri) {
79
+ return result;
80
+ }
81
+ if (result[0] === '/') {
82
+ let uri = baseUri;
83
+ if (uri[uri.length - 1] === '/') {
84
+ uri = uri.substring(0, uri.length - 1);
85
+ }
86
+ return `${uri}${result}`;
87
+ }
88
+ return result;
89
+ }
@@ -1,3 +1,5 @@
1
+ import { hasBlob, hasBuffer, hasFormData } from '../../Platform.js';
2
+
1
3
  export type PayloadTypes = 'string' | 'file' | 'blob' | 'buffer' | 'arraybuffer' | 'formdata' | 'x-www-form-urlencoded';
2
4
  export type DeserializedPayload = string | Blob | File | FormData | Buffer | ArrayBuffer | undefined;
3
5
  export const SupportedPayloadTypes: PayloadTypes[] = ['string', 'file', 'blob', 'buffer', 'arraybuffer', 'formdata', 'x-www-form-urlencoded'];
@@ -17,6 +19,12 @@ export interface IMultipartBody {
17
19
  * When the previous value was a Blob or a Buffer, this will be a serialized payload.
18
20
  */
19
21
  value: string | ISafePayload;
22
+ /**
23
+ * Aside from the `value` which is used to process the Payload, the purpose of this field to to keep
24
+ * the entered by the user string value for the "blob" item. This is primarily handled by the UI
25
+ * and ignored by the HTTP Engine.
26
+ */
27
+ blobText?: string;
20
28
  /**
21
29
  * When `true` this entry represent a file part
22
30
  * @deprecated This is only used for the compatibility with ARC. This information is encoded in the `value`.
@@ -80,10 +88,6 @@ export interface ISafePayload {
80
88
  */
81
89
  export type Payload = string | ISafePayload;
82
90
 
83
- export const hasFormData: boolean = typeof FormData === 'function';
84
- export const hasBlob: boolean = typeof Blob === 'function';
85
- export const hasBuffer: boolean = typeof Buffer === 'function';
86
-
87
91
  export class PayloadSerializer {
88
92
  /**
89
93
  * Checked whether the passed payload can be safely stored in the data store.
@@ -464,6 +468,10 @@ export class PayloadSerializer {
464
468
  form.append(name, value);
465
469
  return;
466
470
  }
471
+ if (value.type === 'string') {
472
+ form.append(name, value.data as string);
473
+ return;
474
+ }
467
475
  if (value.type === 'file') {
468
476
  const file = this.deserializeFile(value);
469
477
  form.append(name, file);
@@ -1,5 +1,5 @@
1
1
  import { IProperty, Property } from './Property.js';
2
- import { IMultipartBody } from '../lib/transformers/PayloadSerializer.js';
2
+ import { IMultipartBody, ISafePayload } from '../lib/transformers/PayloadSerializer.js';
3
3
  import { RequestUiMeta as LegacyRequestUiMeta } from './legacy/request/ArcRequest.js';
4
4
 
5
5
  export const Kind = 'Core#RequestUiMeta';
@@ -70,7 +70,7 @@ export interface IBodyMetaModel {
70
70
  /**
71
71
  * Generated view model.
72
72
  */
73
- viewModel: (IProperty | IMultipartBody | IRawBody)[];
73
+ viewModel: (IProperty | ISafePayload | IMultipartBody | IRawBody)[];
74
74
  }
75
75
 
76
76
  /**
@@ -1,4 +1,5 @@
1
- import { PayloadSerializer, Payload, DeserializedPayload, hasBuffer } from '../lib/transformers/PayloadSerializer.js';
1
+ import { PayloadSerializer, Payload, DeserializedPayload } from '../lib/transformers/PayloadSerializer.js';
2
+ import { hasBuffer } from '../Platform.js';
2
3
 
3
4
  export class SerializablePayload {
4
5
  /**
@@ -0,0 +1,189 @@
1
+ import v4 from '../../lib/uuid.js';
2
+ import { IThing, Thing } from "../Thing.js";
3
+ import { IDataAssociationSchema } from './DataAssociationSchema.js';
4
+ import { DataEntity } from './DataEntity.js';
5
+ import { DataNamespace } from './DataNamespace.js';
6
+
7
+ export const Kind = 'Core#DataAssociation';
8
+
9
+ export interface IDataAssociation {
10
+ kind: typeof Kind;
11
+ /**
12
+ * The key of the namespace.
13
+ */
14
+ key: string;
15
+ /**
16
+ * The data association description.
17
+ */
18
+ info: IThing;
19
+ /**
20
+ * Wether the data association is required.
21
+ */
22
+ required?: boolean;
23
+ /**
24
+ * Whether the data association allows multiple items.
25
+ */
26
+ multiple?: boolean;
27
+ /**
28
+ * The target entity of this association.
29
+ * An association without a target is considered invalid and discarded when processing the values.
30
+ */
31
+ target?: string;
32
+ /**
33
+ * The schema allowing to translate the model into a specific format (like JSON, RAML, XML, etc.)
34
+ */
35
+ schema?: IDataAssociationSchema;
36
+ }
37
+
38
+ export class DataAssociation {
39
+ kind = Kind;
40
+
41
+ key = '';
42
+
43
+ /**
44
+ * The description of the data namespace.
45
+ */
46
+ info: Thing = Thing.fromName('');
47
+
48
+ /**
49
+ * Wether the data association is required.
50
+ */
51
+ required?: boolean;
52
+
53
+ /**
54
+ * Whether the data association allows multiple items.
55
+ */
56
+ multiple?: boolean;
57
+
58
+ /**
59
+ * The target entity of this association.
60
+ * An association without a target is considered invalid and discarded when processing the values.
61
+ */
62
+ target?: string;
63
+
64
+ /**
65
+ * The schema allowing to translate the model into a specific format (like JSON, RAML, XML, etc.)
66
+ *
67
+ * Implementation note, when an entity is removed this property is not changed. The target can't
68
+ * be read but it can be tracked to a deleted entity.
69
+ */
70
+ schema?: IDataAssociationSchema;
71
+
72
+ static fromTarget(root: DataNamespace, target: string): DataAssociation {
73
+ const assoc = new DataAssociation(root);
74
+ assoc.target = target;
75
+ return assoc;
76
+ }
77
+
78
+ static fromName(root: DataNamespace, name: string): DataAssociation {
79
+ const assoc = new DataAssociation(root);
80
+ assoc.info = Thing.fromName(name);
81
+ return assoc;
82
+ }
83
+
84
+ /**
85
+ * @param input The data association definition to restore.
86
+ */
87
+ constructor(protected root: DataNamespace, input?: string | IDataAssociation) {
88
+ let init: IDataAssociation;
89
+ if (typeof input === 'string') {
90
+ init = JSON.parse(input);
91
+ } else if (typeof input === 'object') {
92
+ init = input;
93
+ } else {
94
+ init = {
95
+ kind: Kind,
96
+ key: v4(),
97
+ info: Thing.fromName('').toJSON(),
98
+ };
99
+ }
100
+ this.new(init);
101
+ }
102
+
103
+ new(init: IDataAssociation): void {
104
+ if (!DataAssociation.isDataAssociation(init)) {
105
+ throw new Error(`Not a data association.`);
106
+ }
107
+ const { info, key = v4(), kind = Kind, schema, multiple, required, target } = init;
108
+ this.kind = kind;
109
+ this.key = key;
110
+ if (info) {
111
+ this.info = new Thing(info);
112
+ } else {
113
+ this.info = Thing.fromName('');
114
+ }
115
+ if (schema) {
116
+ this.schema = { ...schema };
117
+ } else {
118
+ this.schema = undefined;
119
+ }
120
+ if (typeof multiple === 'boolean') {
121
+ this.multiple = multiple;
122
+ } else {
123
+ this.multiple = undefined;
124
+ }
125
+ if (typeof required === 'boolean') {
126
+ this.required = required;
127
+ } else {
128
+ this.required = undefined;
129
+ }
130
+ if (typeof target === 'string') {
131
+ this.target = target;
132
+ } else {
133
+ this.target = undefined;
134
+ }
135
+ }
136
+
137
+ static isDataAssociation(input: unknown): boolean {
138
+ const typed = input as IDataAssociation;
139
+ if (!input || typed.kind !== Kind) {
140
+ return false;
141
+ }
142
+ return true;
143
+ }
144
+
145
+ toJSON(): IDataAssociation {
146
+ const result: IDataAssociation = {
147
+ kind: Kind,
148
+ key: this.key,
149
+ info: this.info.toJSON(),
150
+ };
151
+ if (this.schema) {
152
+ result.schema = { ...this.schema };
153
+ }
154
+ if (typeof this.multiple === 'boolean') {
155
+ result.multiple = this.multiple;
156
+ }
157
+ if (typeof this.required === 'boolean') {
158
+ result.required = this.required;
159
+ }
160
+ if (typeof this.target === 'string') {
161
+ result.target = this.target;
162
+ }
163
+ return result;
164
+ }
165
+
166
+ getTarget(): DataEntity | undefined {
167
+ const { root, target } = this;
168
+ if (!target) {
169
+ return undefined;
170
+ }
171
+ return root.definitions.entities.find(i => i.key === target);
172
+ }
173
+
174
+ /**
175
+ * Removes self from the parent entity and the namespace definition.
176
+ */
177
+ remove(): void {
178
+ const { root } = this;
179
+ const entity = root.definitions.entities.find(i => i.associations.some(j => j === this));
180
+ if (entity) {
181
+ const assocIndex = entity.associations.findIndex(i => i === this);
182
+ entity.associations.splice(assocIndex, 1);
183
+ }
184
+ const defIndex = this.root.definitions.associations.findIndex(i => i.key === this.key);
185
+ if (defIndex >= 0) {
186
+ this.root.definitions.associations.splice(defIndex, 1);
187
+ }
188
+ }
189
+ }
@@ -0,0 +1,32 @@
1
+ export interface IDataAssociationSchema {
2
+ /**
3
+ * Whether the target entity should be embedded under the property name.
4
+ * When false, this association is just an information that one entity depend on another.
5
+ * When true, it changes the definition of the schema having this association to
6
+ * add the target schema properties inline with this property.
7
+ *
8
+ * **When true**
9
+ *
10
+ * ```javascript
11
+ * // generated schema for `address` association
12
+ * {
13
+ * "name": "example value",
14
+ * "address": {
15
+ * "city": "example value",
16
+ * ...
17
+ * }
18
+ * }
19
+ * ```
20
+ *
21
+ * **When false**
22
+ *
23
+ * ```javascript
24
+ * // generated schema for `address` association
25
+ * {
26
+ * "name": "example value",
27
+ * "address": "the key of the referenced schema"
28
+ * }
29
+ * ```
30
+ */
31
+ embedded?: boolean;
32
+ }