@openeo/js-client 2.1.0 → 2.4.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.
package/src/connection.js CHANGED
@@ -26,12 +26,22 @@ class Connection {
26
26
  /**
27
27
  * Creates a new Connection.
28
28
  *
29
- * @param {string} baseUrl - URL to the back-end.
29
+ * @param {string} baseUrl - The versioned URL or the back-end instance.
30
30
  * @param {Options} [options={}] - Additional options for the connection.
31
+ * @param {?string} [url=null] - User-provided URL of the backend connected to.
31
32
  */
32
- constructor(baseUrl, options = {}) {
33
+ constructor(baseUrl, options = {}, url = null) {
33
34
  /**
34
- * URL of the backend connected to.
35
+ * User-provided URL of the backend connected to.
36
+ *
37
+ * `null` if not given and the connection was directly made to a versioned instance of the back-end.
38
+ *
39
+ * @protected
40
+ * @type {string | null}
41
+ */
42
+ this.url = url;
43
+ /**
44
+ * The versioned URL or the back-end instance.
35
45
  *
36
46
  * @protected
37
47
  * @type {string}
@@ -41,31 +51,23 @@ class Connection {
41
51
  * Auth Provider cache
42
52
  *
43
53
  * @protected
44
- * @type {?Array.<AuthProvider>}
54
+ * @type {Array.<AuthProvider> | null}
45
55
  */
46
56
  this.authProviderList = null;
47
57
  /**
48
58
  * Current auth provider
49
59
  *
50
60
  * @protected
51
- * @type {?AuthProvider}
61
+ * @type {AuthProvider | null}
52
62
  */
53
63
  this.authProvider = null;
54
64
  /**
55
65
  * Capability cache
56
66
  *
57
67
  * @protected
58
- * @type {?Capabilities}
68
+ * @type {Capabilities | null}
59
69
  */
60
70
  this.capabilitiesObject = null;
61
- /**
62
- * Process cache
63
- *
64
- * @protected
65
- * @type {ProcessRegistry}
66
- */
67
- this.processes = new ProcessRegistry([], Boolean(options.addNamespaceToProcess));
68
- this.processes.listeners.push((...args) => this.emit('processesChanged', ...args));
69
71
  /**
70
72
  * Listeners for events.
71
73
  *
@@ -80,12 +82,21 @@ class Connection {
80
82
  * @type {Options}
81
83
  */
82
84
  this.options = options;
85
+ /**
86
+ * Process cache
87
+ *
88
+ * @protected
89
+ * @type {ProcessRegistry}
90
+ */
91
+ this.processes = new ProcessRegistry([], Boolean(options.addNamespaceToProcess));
92
+ this.processes.listeners.push((...args) => this.emit('processesChanged', ...args));
83
93
  }
84
94
 
85
95
  /**
86
96
  * Initializes the connection by requesting the capabilities.
87
97
  *
88
98
  * @async
99
+ * @protected
89
100
  * @returns {Promise<Capabilities>} Capabilities
90
101
  */
91
102
  async init() {
@@ -95,14 +106,52 @@ class Connection {
95
106
  }
96
107
 
97
108
  /**
98
- * Returns the URL of the back-end currently connected to.
109
+ * Refresh the cache for processes.
99
110
  *
100
- * @returns {string} The URL or the back-end.
111
+ * @async
112
+ * @protected
113
+ * @returns {Promise}
114
+ */
115
+ async refreshProcessCache() {
116
+ if (this.processes.count() === 0) {
117
+ return;
118
+ }
119
+ let promises = this.processes.namespaces().map(namespace => {
120
+ let fn = () => Promise.resolve();
121
+ if (namespace === 'user') {
122
+ if (!this.isAuthenticated()) {
123
+ fn = () => (this.processes.remove(null, 'user') ? Promise.resolve() : Promise.reject(new Error("Can't clear user processes")));
124
+ }
125
+ else if (this.capabilities().hasFeature('listUserProcesses')) {
126
+ fn = () => this.listUserProcesses();
127
+ }
128
+ }
129
+ else if (this.capabilities().hasFeature('listProcesses')) {
130
+ fn = () => this.listProcesses(namespace);
131
+ }
132
+ return fn().catch(error => console.warn(`Could not update processes for namespace '${namespace}' due to an error: ${error.message}`));
133
+ });
134
+ return await Promise.all(promises);
135
+ }
136
+
137
+ /**
138
+ * Returns the URL of the versioned back-end instance currently connected to.
139
+ *
140
+ * @returns {string} The versioned URL or the back-end instance.
101
141
  */
102
142
  getBaseUrl() {
103
143
  return this.baseUrl;
104
144
  }
105
145
 
146
+ /**
147
+ * Returns the user-provided URL of the back-end currently connected to.
148
+ *
149
+ * @returns {string} The URL or the back-end.
150
+ */
151
+ getUrl() {
152
+ return this.url || this.baseUrl;
153
+ }
154
+
106
155
  /**
107
156
  * Returns the capabilities of the back-end.
108
157
  *
@@ -241,6 +290,25 @@ class Connection {
241
290
  }
242
291
  }
243
292
 
293
+ /**
294
+ * Normalisation of the namespace to a value that is compatible with the OpenEO specs - EXPERIMENTAL.
295
+ *
296
+ * This is required to support UDP that are shared as public. These can only be executed with providing the full URL
297
+ * (e.g. https://<backend>/processes/<namespace>/<process_id>) as the namespace value in the processing graph. For other
298
+ * parts of the API (such as the listing of the processes, only the name of the namespace is required.
299
+ *
300
+ * This function will extract the short name of the namespace from a shareable URL.
301
+ *
302
+ * @protected
303
+ * @param {?string} namespace - Namespace of the process
304
+ * @returns {?string}
305
+ */
306
+ normalizeNamespace(namespace) {
307
+ // The pattern in https://github.com/Open-EO/openeo-api/pull/348 doesn't include the double colon yet - the regexp may change in the future
308
+ const matches = namespace.match( /^https?:\/\/.*\/processes\/(@?[\w\-.~:]+)\/?/i);
309
+ return matches && matches.length > 1 ? matches[1] : namespace;
310
+ }
311
+
244
312
  /**
245
313
  * List processes available on the back-end.
246
314
  *
@@ -259,7 +327,7 @@ class Connection {
259
327
  if (!namespace) {
260
328
  namespace = 'backend';
261
329
  }
262
- let path = (namespace === 'backend') ? '/processes' : `/processes/${namespace}`;
330
+ let path = (namespace === 'backend') ? '/processes' : `/processes/${this.normalizeNamespace(namespace)}`;
263
331
  let response = await this._get(path);
264
332
 
265
333
  if (!Utils.isObject(response.data) || !Array.isArray(response.data.processes)) {
@@ -291,7 +359,7 @@ class Connection {
291
359
  await this.listProcesses();
292
360
  }
293
361
  else {
294
- let response = await this._get(`/processes/${namespace}/${processId}`);
362
+ let response = await this._get(`/processes/${this.normalizeNamespace(namespace)}/${processId}`);
295
363
  if (!Utils.isObject(response.data) || typeof response.data.id !== 'string') {
296
364
  throw new Error('Invalid response received for process');
297
365
  }
@@ -492,6 +560,8 @@ class Connection {
492
560
  this.authProvider = null;
493
561
  }
494
562
  this.emit('authProviderChanged', this.authProvider);
563
+ // Update process cache on auth changes: https://github.com/Open-EO/openeo-js-client/issues/55
564
+ this.refreshProcessCache();
495
565
  }
496
566
 
497
567
  /**
@@ -547,12 +617,12 @@ class Connection {
547
617
  );
548
618
  }
549
619
 
550
-
551
620
  /**
552
621
  * A callback that is executed on upload progress updates.
553
622
  *
554
623
  * @callback uploadStatusCallback
555
624
  * @param {number} percentCompleted - The percent (0-100) completed.
625
+ * @param {UserFile} file - The file object corresponding to the callback.
556
626
  */
557
627
 
558
628
  /**
@@ -567,15 +637,16 @@ class Connection {
567
637
  * @param {*} source - The source, see method description for details.
568
638
  * @param {?string} [targetPath=null] - The target path on the server, relative to the user workspace. Defaults to the file name of the source file.
569
639
  * @param {?uploadStatusCallback} [statusCallback=null] - Optionally, a callback that is executed on upload progress updates.
640
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the upload process.
570
641
  * @returns {Promise<UserFile>}
571
642
  * @throws {Error}
572
643
  */
573
- async uploadFile(source, targetPath = null, statusCallback = null) {
644
+ async uploadFile(source, targetPath = null, statusCallback = null, abortController = null) {
574
645
  if (targetPath === null) {
575
646
  targetPath = Environment.fileNameForUpload(source);
576
647
  }
577
648
  let file = await this.getFile(targetPath);
578
- return await file.uploadFile(source, statusCallback);
649
+ return await file.uploadFile(source, statusCallback, abortController);
579
650
  }
580
651
 
581
652
  /**
@@ -692,9 +763,10 @@ class Connection {
692
763
  * @param {Process} process - A user-defined process.
693
764
  * @param {?string} [plan=null] - The billing plan to use for this computation.
694
765
  * @param {?number} [budget=null] - The maximum budget allowed to spend for this computation.
766
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the processing request.
695
767
  * @returns {Promise<SyncResult>} - An object with the data and some metadata.
696
768
  */
697
- async computeResult(process, plan = null, budget = null) {
769
+ async computeResult(process, plan = null, budget = null, abortController = null) {
698
770
  let requestBody = this._normalizeUserProcess(
699
771
  process,
700
772
  {
@@ -702,7 +774,7 @@ class Connection {
702
774
  budget: budget
703
775
  }
704
776
  );
705
- let response = await this._post('/result', requestBody, Environment.getResponseType());
777
+ let response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
706
778
  let syncResult = {
707
779
  data: response.data,
708
780
  costs: null,
@@ -753,10 +825,11 @@ class Connection {
753
825
  * @param {string} targetPath - The target, see method description for details.
754
826
  * @param {?string} [plan=null] - The billing plan to use for this computation.
755
827
  * @param {?number} [budget=null] - The maximum budget allowed to spend for this computation.
828
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the processing request.
756
829
  * @throws {Error}
757
830
  */
758
- async downloadResult(process, targetPath, plan = null, budget = null) {
759
- let response = await this.computeResult(process, plan, budget);
831
+ async downloadResult(process, targetPath, plan = null, budget = null, abortController = null) {
832
+ let response = await this.computeResult(process, plan, budget, abortController);
760
833
  // @ts-ignore
761
834
  await Environment.saveToFile(response.data, targetPath);
762
835
  }
@@ -801,7 +874,7 @@ class Connection {
801
874
  throw new Error("Response did not contain a Job ID. Job has likely been created, but may not show up yet.");
802
875
  }
803
876
  let job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
804
- if (this.capabilitiesObject.hasFeature('describeJob')) {
877
+ if (this.capabilities().hasFeature('describeJob')) {
805
878
  return await job.describeJob();
806
879
  }
807
880
  else {
@@ -867,7 +940,7 @@ class Connection {
867
940
  throw new Error("Response did not contain a Service ID. Service has likely been created, but may not show up yet.");
868
941
  }
869
942
  let service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
870
- if (this.capabilitiesObject.hasFeature('describeService')) {
943
+ if (this.capabilities().hasFeature('describeService')) {
871
944
  return service.describeService();
872
945
  }
873
946
  else {
@@ -936,17 +1009,19 @@ class Connection {
936
1009
  * @param {string} path
937
1010
  * @param {*} body
938
1011
  * @param {string} responseType - Response type according to axios, defaults to `json`.
1012
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the request.
939
1013
  * @returns {Promise<AxiosResponse>}
940
1014
  * @throws {Error}
941
1015
  * @see https://github.com/axios/axios#request-config
942
1016
  */
943
- async _post(path, body, responseType) {
944
- return await this._send({
1017
+ async _post(path, body, responseType, abortController = null) {
1018
+ let options = {
945
1019
  method: 'post',
946
1020
  responseType: responseType,
947
1021
  url: path,
948
1022
  data: body
949
- });
1023
+ };
1024
+ return await this._send(options, abortController);
950
1025
  }
951
1026
 
952
1027
  /**
@@ -1032,11 +1107,12 @@ class Connection {
1032
1107
  *
1033
1108
  * @async
1034
1109
  * @param {object.<string, *>} options
1110
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the request.
1035
1111
  * @returns {Promise<AxiosResponse>}
1036
1112
  * @throws {Error}
1037
1113
  * @see https://github.com/axios/axios
1038
1114
  */
1039
- async _send(options) {
1115
+ async _send(options, abortController = null) {
1040
1116
  options.baseURL = this.baseUrl;
1041
1117
  if (this.isAuthenticated() && (typeof options.authorization === 'undefined' || options.authorization === true)) {
1042
1118
  if (!options.headers) {
@@ -1047,6 +1123,9 @@ class Connection {
1047
1123
  if (!options.responseType) {
1048
1124
  options.responseType = 'json';
1049
1125
  }
1126
+ if (abortController) {
1127
+ options.signal = abortController.signal;
1128
+ }
1050
1129
 
1051
1130
  try {
1052
1131
  return await axios(options);
package/src/job.js CHANGED
@@ -44,7 +44,7 @@ class Job extends BaseEntity {
44
44
  * The process chain to be executed.
45
45
  * @public
46
46
  * @readonly
47
- * @type {Process}
47
+ * @type {?Process}
48
48
  */
49
49
  this.process = undefined;
50
50
  /**
@@ -52,35 +52,35 @@ class Job extends BaseEntity {
52
52
  * One of "created", "queued", "running", "canceled", "finished" or "error".
53
53
  * @public
54
54
  * @readonly
55
- * @type {string}
55
+ * @type {?string}
56
56
  */
57
57
  this.status = undefined;
58
58
  /**
59
59
  * Indicates the process of a running batch job in percent.
60
60
  * @public
61
61
  * @readonly
62
- * @type {number}
62
+ * @type {?number}
63
63
  */
64
64
  this.progress = undefined;
65
65
  /**
66
66
  * Date and time of creation, formatted as a RFC 3339 date-time.
67
67
  * @public
68
68
  * @readonly
69
- * @type {string}
69
+ * @type {?string}
70
70
  */
71
71
  this.created = undefined;
72
72
  /**
73
73
  * Date and time of the last status change, formatted as a RFC 3339 date-time.
74
74
  * @public
75
75
  * @readonly
76
- * @type {string}
76
+ * @type {?string}
77
77
  */
78
78
  this.updated = undefined;
79
79
  /**
80
80
  * The billing plan to process and charge the batch job with.
81
81
  * @public
82
82
  * @readonly
83
- * @type {string}
83
+ * @type {?string}
84
84
  */
85
85
  this.plan = undefined;
86
86
  /**
@@ -78,7 +78,7 @@ class OidcProvider extends AuthProvider {
78
78
  /**
79
79
  * The client ID to use for authentication.
80
80
  *
81
- * @type {?string}
81
+ * @type {string | null}
82
82
  */
83
83
  this.clientId = null;
84
84
 
@@ -105,6 +105,13 @@ class OidcProvider extends AuthProvider {
105
105
  */
106
106
  this.scopes = Array.isArray(options.scopes) && options.scopes.length > 0 ? options.scopes : ['openid'];
107
107
 
108
+ /**
109
+ * The scope that is used to request a refresh token.
110
+ *
111
+ * @type {string}
112
+ */
113
+ this.refreshTokenScope = "offline_access";
114
+
108
115
  /**
109
116
  * Any additional links.
110
117
  *
@@ -132,8 +139,8 @@ class OidcProvider extends AuthProvider {
132
139
  * Adds a listener to one of the following events:
133
140
  *
134
141
  * - AccessTokenExpiring: Raised prior to the access token expiring.
135
- * - accessTokenExpired: Raised after the access token has expired.
136
- * - silentRenewError: Raised when the automatic silent renew has failed.
142
+ * - AccessTokenExpired: Raised after the access token has expired.
143
+ * - SilentRenewError: Raised when the automatic silent renew has failed.
137
144
  *
138
145
  * @param {string} event
139
146
  * @param {Function} callback
@@ -161,17 +168,20 @@ class OidcProvider extends AuthProvider {
161
168
  *
162
169
  * Supported only in Browser environments.
163
170
  *
171
+ * @async
164
172
  * @param {object.<string, *>} [options={}] - Object with authentication options.
173
+ * @param {boolean} [requestRefreshToken=false] - If set to `true`, adds a scope to request a refresh token.
165
174
  * @returns {Promise<void>}
166
175
  * @throws {Error}
167
176
  * @see https://github.com/IdentityModel/oidc-client-js/wiki#other-optional-settings
177
+ * @see {OidcProvider#refreshTokenScope}
168
178
  */
169
- async login(options = {}) {
179
+ async login(options = {}, requestRefreshToken = false) {
170
180
  if (!this.issuer || typeof this.issuer !== 'string') {
171
181
  throw new Error("No Issuer URL available for OpenID Connect");
172
182
  }
173
183
 
174
- this.manager = new Oidc.UserManager(this.getOptions(options));
184
+ this.manager = new Oidc.UserManager(this.getOptions(options, requestRefreshToken));
175
185
  this.addListener('UserLoaded', async () => this.setUser(await this.manager.getUser()), 'js-client');
176
186
  this.addListener('AccessTokenExpired', () => this.setUser(null), 'js-client');
177
187
  if (OidcProvider.uiMethod === 'popup') {
@@ -216,15 +226,22 @@ class OidcProvider extends AuthProvider {
216
226
  *
217
227
  * @protected
218
228
  * @param {object.<string, *>} options
229
+ * @param {boolean} [requestRefreshToken=false] - If set to `true`, adds a scope to request a refresh token.
219
230
  * @returns {object.<string, *>}
231
+ * @see {OidcProvider#refreshTokenScope}
220
232
  */
221
- getOptions(options = {}) {
233
+ getOptions(options = {}, requestRefreshToken = false) {
222
234
  let response_type = this.getResponseType();
235
+ let scope = this.scopes.slice(0);
236
+ if (requestRefreshToken && !scope.includes(this.refreshTokenScope)) {
237
+ scope.push(this.refreshTokenScope);
238
+ }
239
+
223
240
  return Object.assign({
224
241
  client_id: this.clientId,
225
242
  redirect_uri: OidcProvider.redirectUrl,
226
243
  authority: this.issuer.replace('/.well-known/openid-configuration', ''),
227
- scope: this.scopes.join(' '),
244
+ scope,
228
245
  validateSubOnSilentRenew: true,
229
246
  response_type,
230
247
  response_mode: response_type.includes('code') ? 'query' : 'fragment'
package/src/openeo.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const axios = require('axios').default;
2
+ const { AbortController } = require("node-abort-controller");
2
3
  const Utils = require('@openeo/js-commons/src/utils');
3
4
  const Versions = require('@openeo/js-commons/src/versions');
4
5
 
@@ -50,6 +51,7 @@ class OpenEO {
50
51
  */
51
52
  static async connect(url, options = {}) {
52
53
  let wellKnownUrl = Utils.normalizeUrl(url, '/.well-known/openeo');
54
+ let versionedUrl = url;
53
55
  let response = null;
54
56
  try {
55
57
  response = await axios.get(wellKnownUrl, {timeout: 5000});
@@ -64,14 +66,16 @@ class OpenEO {
64
66
  if (Utils.isObject(response)) {
65
67
  let version = Versions.findLatest(response.data.versions, true, MIN_API_VERSION, MAX_API_VERSION);
66
68
  if (version !== null) {
67
- url = version.url;
69
+ versionedUrl = version.url;
68
70
  }
69
71
  else {
70
72
  throw new Error("Server not supported. Client only supports the API versions between " + MIN_API_VERSION + " and " + MAX_API_VERSION);
71
73
  }
72
74
  }
73
75
 
74
- return await OpenEO.connectDirect(url, options);
76
+ let connection = await OpenEO.connectDirect(versionedUrl, options);
77
+ connection.url = url;
78
+ return connection;
75
79
  }
76
80
 
77
81
  /**
@@ -106,7 +110,7 @@ class OpenEO {
106
110
  * @returns {string} Version number (according to SemVer).
107
111
  */
108
112
  static clientVersion() {
109
- return "2.1.0";
113
+ return "2.4.0";
110
114
  }
111
115
 
112
116
  }
@@ -114,6 +118,7 @@ class OpenEO {
114
118
  OpenEO.Environment = require('./env');
115
119
 
116
120
  module.exports = {
121
+ AbortController,
117
122
  AuthProvider,
118
123
  BasicProvider,
119
124
  Capabilities,
package/src/service.js CHANGED
@@ -39,55 +39,55 @@ class Service extends BaseEntity {
39
39
  * The process chain to be executed.
40
40
  * @public
41
41
  * @readonly
42
- * @type {Process}
42
+ * @type {?Process}
43
43
  */
44
44
  this.process = undefined;
45
45
  /**
46
46
  * URL at which the secondary web service is accessible
47
47
  * @public
48
48
  * @readonly
49
- * @type {string}
49
+ * @type {?string}
50
50
  */
51
51
  this.url = undefined;
52
52
  /**
53
53
  * Web service type (protocol / standard) that is exposed.
54
54
  * @public
55
55
  * @readonly
56
- * @type {string}
56
+ * @type {?string}
57
57
  */
58
58
  this.type = undefined;
59
59
  /**
60
60
  * @public
61
61
  * @readonly
62
- * @type {boolean}
62
+ * @type {?boolean}
63
63
  */
64
64
  this.enabled = undefined;
65
65
  /**
66
66
  * Map of configuration settings, i.e. the setting names supported by the secondary web service combined with actual values.
67
67
  * @public
68
68
  * @readonly
69
- * @type {object.<string, *>}
69
+ * @type {?object.<string, *>}
70
70
  */
71
71
  this.configuration = undefined;
72
72
  /**
73
73
  * Additional attributes of the secondary web service, e.g. available layers for a WMS based on the bands in the underlying GeoTiff.
74
74
  * @public
75
75
  * @readonly
76
- * @type {object.<string, *>}
76
+ * @type {?object.<string, *>}
77
77
  */
78
78
  this.attributes = undefined;
79
79
  /**
80
80
  * Date and time of creation, formatted as a RFC 3339 date-time.
81
81
  * @public
82
82
  * @readonly
83
- * @type {string}
83
+ * @type {?string}
84
84
  */
85
85
  this.created = undefined;
86
86
  /**
87
87
  * The billing plan to process and charge the service with.
88
88
  * @public
89
89
  * @readonly
90
- * @type {string}
90
+ * @type {?string}
91
91
  */
92
92
  this.plan = undefined;
93
93
  /**
package/src/userfile.js CHANGED
@@ -90,10 +90,11 @@ class UserFile extends BaseEntity {
90
90
  * @async
91
91
  * @param {*} source - The source, see method description for details.
92
92
  * @param {?uploadStatusCallback} statusCallback - Optionally, a callback that is executed on upload progress updates.
93
+ * @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the upload process.
93
94
  * @returns {Promise<UserFile>}
94
95
  * @throws {Error}
95
96
  */
96
- async uploadFile(source, statusCallback = null) {
97
+ async uploadFile(source, statusCallback = null, abortController = null) {
97
98
  let options = {
98
99
  method: 'put',
99
100
  url: '/files/' + this.path,
@@ -109,7 +110,7 @@ class UserFile extends BaseEntity {
109
110
  };
110
111
  }
111
112
 
112
- let response = await this.connection._send(options);
113
+ let response = await this.connection._send(options, abortController);
113
114
  return this.setAll(response.data);
114
115
  }
115
116
 
@@ -52,7 +52,7 @@ class UserProcess extends BaseEntity {
52
52
  * A list of categories.
53
53
  * @public
54
54
  * @readonly
55
- * @type {Array.<string>}
55
+ * @type {?Array.<string>}
56
56
  */
57
57
  this.categories = undefined;
58
58
  /**
@@ -74,40 +74,40 @@ class UserProcess extends BaseEntity {
74
74
  * Specifies that the process or parameter is deprecated with the potential to be removed in any of the next versions.
75
75
  * @public
76
76
  * @readonly
77
- * @type {boolean}
77
+ * @type {?boolean}
78
78
  */
79
79
  this.deprecated = undefined;
80
80
  /**
81
81
  * Declares the process or parameter to be experimental, which means that it is likely to change or may produce unpredictable behaviour.
82
82
  * @public
83
83
  * @readonly
84
- * @type {boolean}
84
+ * @type {?boolean}
85
85
  */
86
86
  this.experimental = undefined;
87
87
  /**
88
88
  * Declares any exceptions (errors) that might occur during execution of this process.
89
89
  * @public
90
90
  * @readonly
91
- * @type {object.<string, *>}
91
+ * @type {?object.<string, *>}
92
92
  */
93
93
  this.exceptions = undefined;
94
94
  /**
95
95
  * @public
96
96
  * @readonly
97
- * @type {Array.<object.<string, *>>}
97
+ * @type {?Array.<object.<string, *>>}
98
98
  */
99
99
  this.examples = undefined;
100
100
  /**
101
101
  * Links related to this process.
102
102
  * @public
103
103
  * @readonly
104
- * @type {Array.<Link>}
104
+ * @type {?Array.<Link>}
105
105
  */
106
106
  this.links = undefined;
107
107
  /**
108
108
  * @public
109
109
  * @readonly
110
- * @type {object.<string, *>}
110
+ * @type {?object.<string, *>}
111
111
  */
112
112
  this.processGraph = undefined;
113
113
  }