From e3fd3abb34c14f2ecddd30a2a8e0fa679c44419f Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Wed, 21 Dec 2022 12:05:24 +0100 Subject: [PATCH 01/79] issue-357 : added implementation for put/get ServiceRecordsPolicy Applications should call these methods from ElasticsearchClientService. Fixes #357 Signed-off-by: Martin Sunal --- .../services/ElasticsearchService.js | 129 ++++++++++++++++-- 1 file changed, 117 insertions(+), 12 deletions(-) diff --git a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js index 9fcaadf8..c7ba49f4 100644 --- a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js +++ b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js @@ -8,35 +8,51 @@ const controlConstruct = require('../onfModel/models/ControlConstruct'); const TcpClientInterface = require('../onfModel/models/layerProtocols/TcpClientInterface'); const onfAttributes = require('../onfModel/constants/OnfAttributes'); +/** + * @description This class represents Elasticsearch service running on server. + * Exported is one instance of this class. + */ class ElasticsearchService { - client; - apiKey; + _client; + _apiKey; + /** + * @description This method MUST be called in order to use Elasticsearch client directly. + * There is always one instance of ES client runnning within this class. The client is configured + * with API key, URL and port found in config file. Before returning existing client, this + * method also checks if the API key has not changed. If it had changed, closes the existing + * client, creates a new one and returns it. + * + * @returns Elasticsearch client + */ async getClient() { let newApiKey = await this.getApiKeyAsync(); - if (!newApiKey && !this.apiKey && newApiKey !== this.apiKey) { - this.client.close(); - this.apiKey = undefined; + if (!newApiKey && !this._apiKey && newApiKey !== this._apiKey) { + this._client.close(); + this._apiKey = undefined; } - if (this.apiKey === undefined) { - this.apiKey = newApiKey; - this.client = new Client(await this.configureClient()); - this.client.on('response', (err, result) => { + if (this._apiKey === undefined) { + this._apiKey = newApiKey; + this._client = new Client(await this._configureClient()); + this._client.on('response', (err, result) => { if (err) { console.error(err) } }); } - return this.client; + return this._client; } - async configureClient() { + /** + * @returns configuration options for Elasticsearch client + */ + async _configureClient() { let node = await this.getNodeAsync(); return { node: node, auth: { - apiKey: this.apiKey + apiKey: this._apiKey }, tls: { // required if elasticsearch has a self-signed certificate @@ -45,6 +61,10 @@ class ElasticsearchService { } } + /** + * @description Reads URL, port and remote protocol from TCP LTP of Elasticsearch client + * @returns {Promise} connection string in form: "://
:port" + */ async getNodeAsync() { return new Promise(async function (resolve, reject) { let node = undefined; @@ -107,6 +127,64 @@ class ElasticsearchService { }); } + /** + * @description Creates/updates service records policy object in Elasticsearch instance + * @param {Object} body service records policy + * @returns result of the putLifecycle operation + */ + async putServiceRecordsPolicy(body) { + let client = await this.getClient(); + let policyBody = body["elasticsearch-client-interface-1-0:service-records-policy"]; + let name = policyBody["service-records-policy-name"]; + let description = policyBody["description"]; + let project = policyBody["project"]; + let updatedPhases = this.replaceAllObjKeys(policyBody["phases"], (key) => key.replaceAll("-","_")); + let result = await client.ilm.putLifecycle({ + "policy": name, + "body": { + "policy": { + "_meta": { + "description": description, + "project": project + }, + "phases": updatedPhases + } + } + }); + console.log(`Index lifecycle policy "${name}" is updated.`); + return result; + } + + /** + * @description Fetches service records policy associated with configured index alias. + * @returns {Promise} service records policy + */ + async getServiceRecordsPolicy() { + let indexAlias = await this.getIndexAliasAsync(); + let client = await this.getClient(); + let policy = await client.indices.getSettings({ + "index": indexAlias, + "name": "index.lifecycle.name" + }); + if (Object.keys(policy.body).length === 0) { + return { + "service-records-policy-name": "", + "phases": {} + } + } + let indexName = Object.keys(policy.body)[0]; + let policyName = policy.body[indexName].settings.index.lifecycle.name; + let result = await client.ilm.getLifecycle({ + "policy": policyName + }); + let updatedPhases = this.replaceAllObjKeys(result.body[policyName].policy.phases, (key) => key.replaceAll("_","-")); + let policyDetail = { + "service-records-policy-name": policyName, + "phases": updatedPhases + } + return policyDetail; + } + createResultArray(result) { const resultArray = []; result.body.hits.hits.forEach((item) => { @@ -114,6 +192,33 @@ class ElasticsearchService { }); return resultArray; } + + /** + * @description Modifies recursively object keys using parameter function. + * Used to change hyphens to underscore when reading/writing service policy + * from/to Elasticsearch + * @param {Object} obj Object where keys should be modified + * @param {Function} getNewKey function transforming the key + * @returns {Object} transformed object + */ + replaceAllObjKeys(obj, getNewKey) { + if (Array.isArray(obj)) { + for (let i = 0; i < obj.length; i++) { + this.replaceAllObjKeys(obj[i], getNewKey); + } + } + else if (typeof obj === "object") { + for (const key in obj) { + const newKey = getNewKey(key); + obj[newKey] = obj[key]; + if (key !== newKey) { + delete obj[key]; + } + this.replaceAllObjKeys(obj[newKey], getNewKey); + } + } + return obj; + }; } module.exports = new ElasticsearchService() From eb3fccabd31a0f086c8d3fa2b991606789bb356b Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Wed, 21 Dec 2022 14:23:32 +0100 Subject: [PATCH 02/79] issue-357 : added support for pinging Elasticsearch instance Also renamed service policy methods to match REST API. Fixes #357 Signed-off-by: Martin Sunal --- .../services/ElasticsearchService.js | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js index c7ba49f4..e4622535 100644 --- a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js +++ b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js @@ -8,6 +8,12 @@ const controlConstruct = require('../onfModel/models/ControlConstruct'); const TcpClientInterface = require('../onfModel/models/layerProtocols/TcpClientInterface'); const onfAttributes = require('../onfModel/constants/OnfAttributes'); +const operationalStateEnum = { + AVAILABLE: "elasticsearch-client-interface-1-0:OPERATIONAL_STATE_TYPE_AVAILABLE", + UNAVAILABLE: "elasticsearch-client-interface-1-0:OPERATIONAL_STATE_TYPE_UNAVAILABLE", + NOT_YET_DEFINED: "elasticsearch-client-interface-1-0:OPERATIONAL_STATE_TYPE_NOT_YET_DEFINED" +}; + /** * @description This class represents Elasticsearch service running on server. * Exported is one instance of this class. @@ -129,10 +135,11 @@ class ElasticsearchService { /** * @description Creates/updates service records policy object in Elasticsearch instance + * MUST be used to implement putElasticsearchClientServiceRecordsPolicy REST API method * @param {Object} body service records policy * @returns result of the putLifecycle operation */ - async putServiceRecordsPolicy(body) { + async putElasticsearchClientServiceRecordsPolicy(body) { let client = await this.getClient(); let policyBody = body["elasticsearch-client-interface-1-0:service-records-policy"]; let name = policyBody["service-records-policy-name"]; @@ -157,9 +164,10 @@ class ElasticsearchService { /** * @description Fetches service records policy associated with configured index alias. + * MUST be used to implement getElasticsearchClientServiceRecordsPolicy REST API method * @returns {Promise} service records policy */ - async getServiceRecordsPolicy() { + async getElasticsearchClientServiceRecordsPolicy() { let indexAlias = await this.getIndexAliasAsync(); let client = await this.getClient(); let policy = await client.indices.getSettings({ @@ -219,6 +227,18 @@ class ElasticsearchService { } return obj; }; + + /** + * @description Issues ping to Elasticsearch instance + * MUST be used to implement getElasticsearchClientOperationalState REST API method + * @returns {Promise} AVAILABLE if the ping returns with http status code 200, UNAVAILABLE if not + */ + async getElasticsearchClientOperationalState() { + let client = await this.getClient(); + let result = await client.ping(); + return (result.statusCode === 200) ? + operationalStateEnum.AVAILABLE : operationalStateEnum.UNAVAILABLE; + } } module.exports = new ElasticsearchService() From 0ce351757b80fea995dae5640cbfb42300338b66 Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Wed, 21 Dec 2022 16:33:29 +0100 Subject: [PATCH 03/79] issue-357 : added support for more ES instances Fixes #357 Signed-off-by: Martin Sunal --- .../services/ElasticsearchService.js | 111 ++++++++++++------ 1 file changed, 74 insertions(+), 37 deletions(-) diff --git a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js index e4622535..654543fa 100644 --- a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js +++ b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js @@ -20,8 +20,11 @@ const operationalStateEnum = { */ class ElasticsearchService { - _client; - _apiKey; + _clients + + constructor() { + this._clients = new Map(); + } /** * @description This method MUST be called in order to use Elasticsearch client directly. @@ -29,36 +32,44 @@ class ElasticsearchService { * with API key, URL and port found in config file. Before returning existing client, this * method also checks if the API key has not changed. If it had changed, closes the existing * client, creates a new one and returns it. + * @param {String} uuid optional, UUID of Elasticsearch client. If uuid parameter is missing, it + * assumes, there is exactly one Elasticsearch client configured in the config file. * * @returns Elasticsearch client */ - async getClient() { - let newApiKey = await this.getApiKeyAsync(); - if (!newApiKey && !this._apiKey && newApiKey !== this._apiKey) { - this._client.close(); - this._apiKey = undefined; - } - if (this._apiKey === undefined) { - this._apiKey = newApiKey; - this._client = new Client(await this._configureClient()); - this._client.on('response', (err, result) => { - if (err) { - console.error(err) - } - }); + async getClient(uuid) { + let esUuid = await ElasticsearchService.getElasticsearchClientUuid(uuid); + let newApiKey = await this.getApiKeyAsync(esUuid); + let client = this._clients.get(uuid); + if (client) { + let storedApiKey = client.apiKey; + if (newApiKey !== storedApiKey) { + client.client.close(); + storedApiKey = undefined; + } else { + return client.client; + } } - return this._client; + let storedApiKey = newApiKey; + client = new Client(await this._configureClient(uuid, storedApiKey)); + client.on('response', (err, result) => { + if (err) { + console.error(err) + } + }); + this._clients.set(uuid, { "client": client, "apiKey": storedApiKey }); + return client; } /** * @returns configuration options for Elasticsearch client */ - async _configureClient() { - let node = await this.getNodeAsync(); + async _configureClient(uuid, apiKey) { + let node = await this.getNodeAsync(uuid); return { node: node, auth: { - apiKey: this._apiKey + apiKey: apiKey }, tls: { // required if elasticsearch has a self-signed certificate @@ -67,16 +78,40 @@ class ElasticsearchService { } } + /** + * @description Given uuid, it checks if it matches any Elasticsearch client LTP UUIDs + * from config file, returns an error, if it doesn't. If uuid parameter is missing, it + * assumes, there is exactly one Elasticsearch client configured in the config file. + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns UUID of Elasticsearch client + */ + static async getElasticsearchClientUuid(uuid) { + return new Promise(async function (resolve, reject) { + try { + let uuids = await logicalTerminationPoint.getUuidListForTheProtocolAsync(layerProtocol.layerProtocolNameEnum.ES_CLIENT); + if (uuid !== undefined) { + return (uuids.includes(uuid)) ? resolve(uuid) : reject(new Error(`UUID ${uuid} does not match any Elasticsearch client LTP.`)); + } + if (uuids.length > 1) { + return reject(new Error(`There is more than 1 Elasticsearch client LTP configured. Please specify UUID.`)); + } + resolve(uuids[0]); + } catch (error) { + reject(error); + } + }); + } + /** * @description Reads URL, port and remote protocol from TCP LTP of Elasticsearch client + * @param {String} uuid UUID of Elasticsearch client * @returns {Promise} connection string in form: "://
:port" */ - async getNodeAsync() { + async getNodeAsync(uuid) { return new Promise(async function (resolve, reject) { let node = undefined; try { - let uuid = await logicalTerminationPoint.getUuidListForTheProtocolAsync(layerProtocol.layerProtocolNameEnum.ES_CLIENT); - let serverLtp = await logicalTerminationPoint.getServerLtpListAsync(uuid[0]); + let serverLtp = await logicalTerminationPoint.getServerLtpListAsync(uuid); let httpClient = await controlConstruct.getLogicalTerminationPointAsync(serverLtp[0]); let tcpClient = await logicalTerminationPoint.getServerLtpListAsync(httpClient.uuid); let address = await TcpClientInterface.getRemoteAddressAsync(tcpClient[0]); @@ -90,12 +125,11 @@ class ElasticsearchService { }); } - static async getEsClientConfig() { + static async getEsClientConfig(uuid) { return new Promise(async function (resolve, reject) { let clientConfig; try { - let uuid = await logicalTerminationPoint.getUuidListForTheProtocolAsync(layerProtocol.layerProtocolNameEnum.ES_CLIENT); - let ltp = await controlConstruct.getLogicalTerminationPointAsync(uuid[0]); + let ltp = await controlConstruct.getLogicalTerminationPointAsync(uuid); let lp = ltp[onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL][0]; let esClientPac = lp[onfAttributes.LAYER_PROTOCOL.ES_CLIENT_INTERFACE_PAC]; clientConfig = esClientPac[onfAttributes.ES_CLIENT.CONFIGURATION]; @@ -106,11 +140,11 @@ class ElasticsearchService { }); } - async getApiKeyAsync() { + async getApiKeyAsync(uuid) { return new Promise(async function (resolve, reject) { let apiKey; try { - let esClientConfiguration = await ElasticsearchService.getEsClientConfig(); + let esClientConfiguration = await ElasticsearchService.getEsClientConfig(uuid); let esClientAuth = esClientConfiguration[onfAttributes.ES_CLIENT.AUTH]; apiKey = esClientAuth[onfAttributes.ES_CLIENT.API_KEY]; resolve(apiKey); @@ -120,11 +154,11 @@ class ElasticsearchService { }); } - async getIndexAliasAsync() { + async getIndexAliasAsync(uuid) { return new Promise(async function (resolve, reject) { let indexAlias; try { - let esClientConfiguration = await ElasticsearchService.getEsClientConfig(); + let esClientConfiguration = await ElasticsearchService.getEsClientConfig(uuid); indexAlias = esClientConfiguration[onfAttributes.ES_CLIENT.INDEX_ALIAS]; resolve(indexAlias); } catch (error) { @@ -136,11 +170,12 @@ class ElasticsearchService { /** * @description Creates/updates service records policy object in Elasticsearch instance * MUST be used to implement putElasticsearchClientServiceRecordsPolicy REST API method + * @param {String} uuid optional, UUID of Elasticsearch client * @param {Object} body service records policy * @returns result of the putLifecycle operation */ - async putElasticsearchClientServiceRecordsPolicy(body) { - let client = await this.getClient(); + async putElasticsearchClientServiceRecordsPolicy(uuid, body) { + let client = await this.getClient(uuid); let policyBody = body["elasticsearch-client-interface-1-0:service-records-policy"]; let name = policyBody["service-records-policy-name"]; let description = policyBody["description"]; @@ -165,11 +200,12 @@ class ElasticsearchService { /** * @description Fetches service records policy associated with configured index alias. * MUST be used to implement getElasticsearchClientServiceRecordsPolicy REST API method + * @param {String} uuid optional, UUID of Elasticsearch client * @returns {Promise} service records policy */ - async getElasticsearchClientServiceRecordsPolicy() { - let indexAlias = await this.getIndexAliasAsync(); - let client = await this.getClient(); + async getElasticsearchClientServiceRecordsPolicy(uuid) { + let client = await this.getClient(uuid); + let indexAlias = await this.getIndexAliasAsync(uuid); let policy = await client.indices.getSettings({ "index": indexAlias, "name": "index.lifecycle.name" @@ -231,10 +267,11 @@ class ElasticsearchService { /** * @description Issues ping to Elasticsearch instance * MUST be used to implement getElasticsearchClientOperationalState REST API method + * @param {String} uuid optional, UUID of Elasticsearch client * @returns {Promise} AVAILABLE if the ping returns with http status code 200, UNAVAILABLE if not */ - async getElasticsearchClientOperationalState() { - let client = await this.getClient(); + async getElasticsearchClientOperationalState(uuid) { + let client = await this.getClient(uuid); let result = await client.ping(); return (result.statusCode === 200) ? operationalStateEnum.AVAILABLE : operationalStateEnum.UNAVAILABLE; From d466ee793c845b6bed36a7c36695ae24d44f8ec4 Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Thu, 22 Dec 2022 13:11:09 +0100 Subject: [PATCH 04/79] issue-357 : rearranged methods Fixes #357 Signed-off-by: Martin Sunal --- .../services/ElasticsearchService.js | 478 +++++++++--------- 1 file changed, 243 insertions(+), 235 deletions(-) diff --git a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js index 654543fa..25479ddd 100644 --- a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js +++ b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js @@ -14,268 +14,276 @@ const operationalStateEnum = { NOT_YET_DEFINED: "elasticsearch-client-interface-1-0:OPERATIONAL_STATE_TYPE_NOT_YET_DEFINED" }; +module.exports = { operationalStateEnum } + /** * @description This class represents Elasticsearch service running on server. + * + * Version of Elasticsearch used is 7. + * * Exported is one instance of this class. */ class ElasticsearchService { - _clients + /** + * @private + */ + _clients - constructor() { - this._clients = new Map(); - } + constructor() { + this._clients = new Map(); + } - /** - * @description This method MUST be called in order to use Elasticsearch client directly. - * There is always one instance of ES client runnning within this class. The client is configured - * with API key, URL and port found in config file. Before returning existing client, this - * method also checks if the API key has not changed. If it had changed, closes the existing - * client, creates a new one and returns it. - * @param {String} uuid optional, UUID of Elasticsearch client. If uuid parameter is missing, it - * assumes, there is exactly one Elasticsearch client configured in the config file. - * - * @returns Elasticsearch client - */ - async getClient(uuid) { - let esUuid = await ElasticsearchService.getElasticsearchClientUuid(uuid); - let newApiKey = await this.getApiKeyAsync(esUuid); - let client = this._clients.get(uuid); - if (client) { - let storedApiKey = client.apiKey; - if (newApiKey !== storedApiKey) { - client.client.close(); - storedApiKey = undefined; - } else { - return client.client; - } + /** + * @description This method MUST be called in order to use Elasticsearch client directly. + * There is always one instance of ES client runnning within this class. The client is configured + * with API key, URL and port found in config file. Before returning existing client, this + * method also checks if the API key has not changed. If it had changed, closes the existing + * client, creates a new one and returns it. + * + * Each error coming from Elasticsearch is logged to console. Users of this client MUST handle + * ElasticsearchClientError accordingly. + * + * @param {String} uuid optional, UUID of Elasticsearch client. If uuid parameter is missing, it + * assumes, there is exactly one Elasticsearch client configured in the config file. + * + * @returns {Promise} Elasticsearch client version 7 + */ + async getClient(uuid) { + let esUuid = await getElasticsearchClientUuidAsync(uuid); + let newApiKey = await getApiKeyAsync(esUuid); + let client = this._clients.get(uuid); + if (client) { + let storedApiKey = client.apiKey; + if (newApiKey !== storedApiKey) { + client.client.close(); + storedApiKey = undefined; + } else { + return client.client; } - let storedApiKey = newApiKey; - client = new Client(await this._configureClient(uuid, storedApiKey)); - client.on('response', (err, result) => { - if (err) { - console.error(err) - } - }); - this._clients.set(uuid, { "client": client, "apiKey": storedApiKey }); - return client; } + let storedApiKey = newApiKey; + client = new Client(await configureClientAsync(uuid, storedApiKey)); + client.on('response', (err, result) => { + if (err) { + console.error(`Elasticsearch error occurred: ${err}`); + } + }); + this._clients.set(uuid, { client: client, apiKey: storedApiKey }); + return client; + } - /** - * @returns configuration options for Elasticsearch client - */ - async _configureClient(uuid, apiKey) { - let node = await this.getNodeAsync(uuid); - return { - node: node, - auth: { - apiKey: apiKey - }, - tls: { - // required if elasticsearch has a self-signed certificate - rejectUnauthorized: false - } - } + /** + * @description Issues ping to Elasticsearch instance. Returns operational state UNAVAILABLE + * if a connection error occurs. + * MUST be used to implement getElasticsearchClientOperationalState REST API method + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} AVAILABLE if the ping returns with http status code 200, UNAVAILABLE if not + */ + async getElasticsearchClientOperationalStateAsync(uuid) { + let client = await this.getClient(uuid); + try { + let ping = await client.ping(); + return (ping.statusCode === 200) ? + operationalStateEnum.AVAILABLE : operationalStateEnum.UNAVAILABLE; + } catch (error) { + return operationalStateEnum.UNAVAILABLE; } + } - /** - * @description Given uuid, it checks if it matches any Elasticsearch client LTP UUIDs - * from config file, returns an error, if it doesn't. If uuid parameter is missing, it - * assumes, there is exactly one Elasticsearch client configured in the config file. - * @param {String} uuid optional, UUID of Elasticsearch client - * @returns UUID of Elasticsearch client - */ - static async getElasticsearchClientUuid(uuid) { - return new Promise(async function (resolve, reject) { - try { - let uuids = await logicalTerminationPoint.getUuidListForTheProtocolAsync(layerProtocol.layerProtocolNameEnum.ES_CLIENT); - if (uuid !== undefined) { - return (uuids.includes(uuid)) ? resolve(uuid) : reject(new Error(`UUID ${uuid} does not match any Elasticsearch client LTP.`)); - } - if (uuids.length > 1) { - return reject(new Error(`There is more than 1 Elasticsearch client LTP configured. Please specify UUID.`)); - } - resolve(uuids[0]); - } catch (error) { - reject(error); + /** + * @description Creates/updates service records policy object in Elasticsearch instance + * MUST be used to implement putElasticsearchClientServiceRecordsPolicy REST API method + * @param {String} uuid optional, UUID of Elasticsearch client + * @param {object} body service records policy + * @returns {Promise} result of the putLifecycle operation + */ + async putElasticsearchClientServiceRecordsPolicyAsync(uuid, body) { + let client = await this.getClient(uuid); + let policyBody = body["elasticsearch-client-interface-1-0:service-records-policy"]; + let name = policyBody["service-records-policy-name"]; + let description = policyBody["description"]; + let project = policyBody["project"]; + let updatedPhases = replaceAllObjKeys(policyBody["phases"], (key) => key.replaceAll("-","_")); + let result = await client.ilm.putLifecycle({ + "policy": name, + "body": { + "policy": { + "_meta": { + "description": description, + "project": project + }, + "phases": updatedPhases } - }); - } + } + }); + return result; + } - /** - * @description Reads URL, port and remote protocol from TCP LTP of Elasticsearch client - * @param {String} uuid UUID of Elasticsearch client - * @returns {Promise} connection string in form: "://
:port" - */ - async getNodeAsync(uuid) { - return new Promise(async function (resolve, reject) { - let node = undefined; - try { - let serverLtp = await logicalTerminationPoint.getServerLtpListAsync(uuid); - let httpClient = await controlConstruct.getLogicalTerminationPointAsync(serverLtp[0]); - let tcpClient = await logicalTerminationPoint.getServerLtpListAsync(httpClient.uuid); - let address = await TcpClientInterface.getRemoteAddressAsync(tcpClient[0]); - let port = await TcpClientInterface.getRemotePortAsync(tcpClient[0]); - let remoteProtocol = await TcpClientInterface.getRemoteProtocolAsync(tcpClient[0]); - node = remoteProtocol + "://" + address[onfAttributes.TCP_CLIENT.IP_ADDRESS][onfAttributes.TCP_CLIENT.IPV_4_ADDRESS] + ":" + port; - resolve(node); - } catch (error) { - reject(error); - } - }); + /** + * @description Fetches service records policy associated with configured index alias. + * MUST be used to implement getElasticsearchClientServiceRecordsPolicy REST API method + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} service records policy if the policy exists + */ + async getElasticsearchClientServiceRecordsPolicyAsync(uuid) { + let client = await this.getClient(uuid); + let indexAlias = await getIndexAliasAsync(uuid); + let policy = await client.indices.getSettings({ + "index": indexAlias, + "name": "index.lifecycle.name" + }); + if (Object.keys(policy.body).length === 0) { + return { + "service-records-policy-name": "", + "phases": {} + } } - - static async getEsClientConfig(uuid) { - return new Promise(async function (resolve, reject) { - let clientConfig; - try { - let ltp = await controlConstruct.getLogicalTerminationPointAsync(uuid); - let lp = ltp[onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL][0]; - let esClientPac = lp[onfAttributes.LAYER_PROTOCOL.ES_CLIENT_INTERFACE_PAC]; - clientConfig = esClientPac[onfAttributes.ES_CLIENT.CONFIGURATION]; - resolve(clientConfig); - } catch (error) { - reject(error); - } - }); + let indexName = Object.keys(policy.body)[0]; + let policyName = policy.body[indexName].settings.index.lifecycle.name; + let result = await client.ilm.getLifecycle({ + "policy": policyName + }); + let updatedPhases = replaceAllObjKeys(result.body[policyName].policy.phases, (key) => key.replaceAll("_","-")); + let policyDetail = { + "service-records-policy-name": policyName, + "phases": updatedPhases } + return policyDetail; + } +} - async getApiKeyAsync(uuid) { - return new Promise(async function (resolve, reject) { - let apiKey; - try { - let esClientConfiguration = await ElasticsearchService.getEsClientConfig(uuid); - let esClientAuth = esClientConfiguration[onfAttributes.ES_CLIENT.AUTH]; - apiKey = esClientAuth[onfAttributes.ES_CLIENT.API_KEY]; - resolve(apiKey); - } catch (error) { - reject(error); - } - }); +/** + * Does not perform uuid check. + * @param {String} uuid UUID of Elasticsearch client + * @param {String} apiKey configured API key + * @returns {Promise} configuration options for Elasticsearch client + */ +async function configureClientAsync(uuid, apiKey) { + let node = await getNodeAsync(uuid); + return { + node: node, + auth: { + apiKey: apiKey + }, + tls: { + // required if elasticsearch has a self-signed certificate + rejectUnauthorized: false } + } +} - async getIndexAliasAsync(uuid) { - return new Promise(async function (resolve, reject) { - let indexAlias; - try { - let esClientConfiguration = await ElasticsearchService.getEsClientConfig(uuid); - indexAlias = esClientConfiguration[onfAttributes.ES_CLIENT.INDEX_ALIAS]; - resolve(indexAlias); - } catch (error) { - reject(error); - } - }); +/** + * @description Given uuid, it checks if it matches any Elasticsearch client LTP UUIDs + * from config file, returns an error, if it doesn't. If uuid parameter is missing, it + * assumes, there is exactly one Elasticsearch client configured in the config file. + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} UUID of Elasticsearch client + */ +async function getElasticsearchClientUuidAsync(uuid) { + let uuids = await logicalTerminationPoint.getUuidListForTheProtocolAsync(layerProtocol.layerProtocolNameEnum.ES_CLIENT); + if (uuid !== undefined) { + if(uuids.includes(uuid)) { + return uuid; + } else { + throw new Error(`UUID ${uuid} does not match any Elasticsearch client LTP.`); } + } + if (uuids.length > 1) { + throw new Error(`There is more than 1 Elasticsearch client LTP configured. Please specify UUID.`); + } + return uuids[0]; +} - /** - * @description Creates/updates service records policy object in Elasticsearch instance - * MUST be used to implement putElasticsearchClientServiceRecordsPolicy REST API method - * @param {String} uuid optional, UUID of Elasticsearch client - * @param {Object} body service records policy - * @returns result of the putLifecycle operation - */ - async putElasticsearchClientServiceRecordsPolicy(uuid, body) { - let client = await this.getClient(uuid); - let policyBody = body["elasticsearch-client-interface-1-0:service-records-policy"]; - let name = policyBody["service-records-policy-name"]; - let description = policyBody["description"]; - let project = policyBody["project"]; - let updatedPhases = this.replaceAllObjKeys(policyBody["phases"], (key) => key.replaceAll("-","_")); - let result = await client.ilm.putLifecycle({ - "policy": name, - "body": { - "policy": { - "_meta": { - "description": description, - "project": project - }, - "phases": updatedPhases - } - } - }); - console.log(`Index lifecycle policy "${name}" is updated.`); - return result; - } +/** + * Does not perform uuid check. + * @param {String} uuid UUID of Elasticsearch client + * @returns {Promise} connection string in form: "://
:port" + */ +async function getNodeAsync(uuid) { + let serverLtp = await logicalTerminationPoint.getServerLtpListAsync(uuid); + let httpClient = await controlConstruct.getLogicalTerminationPointAsync(serverLtp[0]); + let tcpClient = await logicalTerminationPoint.getServerLtpListAsync(httpClient.uuid); + let address = await TcpClientInterface.getRemoteAddressAsync(tcpClient[0]); + let port = await TcpClientInterface.getRemotePortAsync(tcpClient[0]); + let remoteProtocol = await TcpClientInterface.getRemoteProtocolAsync(tcpClient[0]); + return remoteProtocol + "://" + address[onfAttributes.TCP_CLIENT.IP_ADDRESS][onfAttributes.TCP_CLIENT.IPV_4_ADDRESS] + ":" + port; +} - /** - * @description Fetches service records policy associated with configured index alias. - * MUST be used to implement getElasticsearchClientServiceRecordsPolicy REST API method - * @param {String} uuid optional, UUID of Elasticsearch client - * @returns {Promise} service records policy - */ - async getElasticsearchClientServiceRecordsPolicy(uuid) { - let client = await this.getClient(uuid); - let indexAlias = await this.getIndexAliasAsync(uuid); - let policy = await client.indices.getSettings({ - "index": indexAlias, - "name": "index.lifecycle.name" - }); - if (Object.keys(policy.body).length === 0) { - return { - "service-records-policy-name": "", - "phases": {} - } - } - let indexName = Object.keys(policy.body)[0]; - let policyName = policy.body[indexName].settings.index.lifecycle.name; - let result = await client.ilm.getLifecycle({ - "policy": policyName - }); - let updatedPhases = this.replaceAllObjKeys(result.body[policyName].policy.phases, (key) => key.replaceAll("_","-")); - let policyDetail = { - "service-records-policy-name": policyName, - "phases": updatedPhases - } - return policyDetail; - } +/** + * Performs uuid check. + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} Elasticsearch client configuration object + */ +async function getEsClientConfigAsync(uuid) { + let esUuid = await getElasticsearchClientUuidAsync(uuid); + let ltp = await controlConstruct.getLogicalTerminationPointAsync(esUuid); + let lp = ltp[onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL][0]; + let esClientPac = lp[onfAttributes.LAYER_PROTOCOL.ES_CLIENT_INTERFACE_PAC]; + return esClientPac[onfAttributes.ES_CLIENT.CONFIGURATION]; +} - createResultArray(result) { - const resultArray = []; - result.body.hits.hits.forEach((item) => { - resultArray.push(item._source); - }); - return resultArray; - } +/** + * Performs uuid check. + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} configured API key for Elasticsearch + */ +async function getApiKeyAsync(uuid) { + let esClientConfiguration = await getEsClientConfigAsync(uuid); + let esClientAuth = esClientConfiguration[onfAttributes.ES_CLIENT.AUTH]; + return esClientAuth[onfAttributes.ES_CLIENT.API_KEY]; +} - /** - * @description Modifies recursively object keys using parameter function. - * Used to change hyphens to underscore when reading/writing service policy - * from/to Elasticsearch - * @param {Object} obj Object where keys should be modified - * @param {Function} getNewKey function transforming the key - * @returns {Object} transformed object - */ - replaceAllObjKeys(obj, getNewKey) { - if (Array.isArray(obj)) { - for (let i = 0; i < obj.length; i++) { - this.replaceAllObjKeys(obj[i], getNewKey); - } - } - else if (typeof obj === "object") { - for (const key in obj) { - const newKey = getNewKey(key); - obj[newKey] = obj[key]; - if (key !== newKey) { - delete obj[key]; - } - this.replaceAllObjKeys(obj[newKey], getNewKey); - } +/** + * @description Modifies recursively object keys using parameter function. + * Used to change hyphens to underscore when reading/writing service policy + * from/to Elasticsearch + * @param {object} obj Object where keys should be modified + * @param {Function} getNewKey function transforming the key + * @returns {object} transformed object + */ +function replaceAllObjKeys(obj, getNewKey) { + if (Array.isArray(obj)) { + for (let i = 0; i < obj.length; i++) { + replaceAllObjKeys(obj[i], getNewKey); + } + } + else if (typeof obj === "object") { + for (const key in obj) { + const newKey = getNewKey(key); + obj[newKey] = obj[key]; + if (key !== newKey) { + delete obj[key]; } - return obj; - }; - - /** - * @description Issues ping to Elasticsearch instance - * MUST be used to implement getElasticsearchClientOperationalState REST API method - * @param {String} uuid optional, UUID of Elasticsearch client - * @returns {Promise} AVAILABLE if the ping returns with http status code 200, UNAVAILABLE if not - */ - async getElasticsearchClientOperationalState(uuid) { - let client = await this.getClient(uuid); - let result = await client.ping(); - return (result.statusCode === 200) ? - operationalStateEnum.AVAILABLE : operationalStateEnum.UNAVAILABLE; + replaceAllObjKeys(obj[newKey], getNewKey); } + } + return obj; +}; + +/** + * Returns index alias from config file. If uuid is present, performs check if + * its an ES client uuid, if it's not present, assumes only one ES client is configured. + * @param {String} uuid optional, UUID of Elasticsearch client + * @returns {Promise} index alias from config file + */ +async function getIndexAliasAsync(uuid) { + let esClientConfiguration = await getEsClientConfigAsync(uuid); + return esClientConfiguration[onfAttributes.ES_CLIENT.INDEX_ALIAS]; +} + +/** + * Helper method, creates Javascript array from Elasticsearch response. + * @param {object} result Elasticsearch response + * @returns {Array} resulting array + */ +module.exports.createResultArray = function createResultArray(result) { + const resultArray = []; + result.body.hits.hits.forEach((item) => { + resultArray.push(item._source); + }); + return resultArray; } +module.exports.getIndexAliasAsync = getIndexAliasAsync module.exports = new ElasticsearchService() From 803ee59babdc63923d5ff2c4d312d884eb37dc45 Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Wed, 28 Dec 2022 11:31:52 +0100 Subject: [PATCH 05/79] issue-300 : added application name check to remaining methods Fixes #300 Signed-off-by: Martin Sunal --- .../basicServices/BasicServicesService.js | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 3e685cb2..0d94509f 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -58,6 +58,12 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi let relayOperationUpdateOperation = body["relay-operation-update-operation"]; let relayServerReplacementOperation = body["relay-server-replacement-operation"]; + const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('PromptForBequeathingDataCausesRequestForBroadcastingInfoAboutServerReplacement'); + if (appNameAndUuidFromForwarding?.applicationName !== applicationName) { + reject(new Error(`The registry-office-application ${applicationName} was not found.`)); + return; + } + /**************************************************************************************** * Prepare logicalTerminationPointConfigurationInput object to * configure logical-termination-point @@ -77,7 +83,7 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping ); - let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.createOrUpdateApplicationInformationAsync( + let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.findAndUpdateApplicationInformationAsync( logicalTerminationPointConfigurationInput ); @@ -804,6 +810,11 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC let fcPortUpdateTopologyOperation = body["topology-operation-fc-port-update"]; let fcPortDeletionTopologyOperation = body["topology-operation-fc-port-deletion"]; + const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('OamRequestCausesLtpUpdateRequest'); + if (appNameAndUuidFromForwarding?.applicationName !== applicationName) { + reject(new Error(`The topology-application ${applicationName} was not found.`)); + return; + } /**************************************************************************************** * Prepare logicalTerminationPointConfigurationInput object to @@ -826,7 +837,7 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping ); - let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.createOrUpdateApplicationInformationAsync( + let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.findAndUpdateApplicationInformationAsync( logicalTerminationPointConfigurationInput ); @@ -949,6 +960,12 @@ exports.registerYourself = function (body, user, originator, xCorrelator, traceI let applicationPort = body["registry-office-port"]; let registerOperation = body["registration-operation"]; + const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('PromptForRegisteringCausesRegistrationRequest'); + if (appNameAndUuidFromForwarding?.applicationName !== applicationName) { + reject(new Error(`The registry-office-application ${applicationName} was not found.`)); + return; + } + /**************************************************************************************** * Prepare logicalTerminationPointConfigurationInput object to * configure logical-termination-point @@ -965,7 +982,7 @@ exports.registerYourself = function (body, user, originator, xCorrelator, traceI operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping ); - let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.createOrUpdateApplicationInformationAsync( + let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.findAndUpdateApplicationInformationAsync( logicalTerminationPointConfigurationInput ); From d1daa5668eeff35d25146f68d6ed9b8f62e2dce2 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Wed, 28 Dec 2022 21:47:47 +0100 Subject: [PATCH 06/79] Support Version 2.0.0 changes for /v1/register-yourself Fixes #487 --- .../onfModel/constants/OnfPaths.js | 2 + .../layerProtocols/HttpClientInterface.js | 23 ++ .../layerProtocols/TcpServerInterface.js | 112 +++++++++- .../basicServices/BasicServicesService.js | 200 ++++++++++++++---- .../services/PrepareForwardingAutomation.js | 40 +++- 5 files changed, 328 insertions(+), 49 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js b/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js index d0ec2f37..02afea7e 100644 --- a/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js +++ b/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js @@ -76,6 +76,7 @@ const TCP_SERVER_INTERFACE_CONFIGURATION = TCP_SERVER_INTERFACE_PAC + "/tcp-serv const TCP_SERVER_IP_ADDRESS = TCP_SERVER_INTERFACE_CONFIGURATION + "/local-address/ipv-4-address"; const TCP_SERVER_DOMAIN_NAME = TCP_SERVER_INTERFACE_CONFIGURATION + "/local-address/domain-name"; const TCP_SERVER_LOCAL_ADDRESS = TCP_SERVER_INTERFACE_CONFIGURATION + "/local-address"; +const TCP_SERVER_LOCAL_PORT = TCP_SERVER_INTERFACE_CONFIGURATION + "/local-port"; /****************************************** ********forwarding-domain************** @@ -133,6 +134,7 @@ module.exports = { TCP_SERVER_IP_ADDRESS, TCP_SERVER_DOMAIN_NAME, TCP_SERVER_LOCAL_ADDRESS, + TCP_SERVER_LOCAL_PORT, FORWARDING_DOMAIN, FORWARDING_CONSTRUCT, FC_PORT, diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/HttpClientInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/HttpClientInterface.js index 71f6864b..11f5cbdf 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/HttpClientInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/HttpClientInterface.js @@ -203,6 +203,29 @@ class HttpClientInterface extends layerProtocol { }); } + /** + * @description This function sets the application name for the http client uuid. + * @param {String} httpClientUuid : the value should be a valid string in the pattern '-\d+-\d+-\d+-http-client-\d+$' + * @param {String} newApplicationName new release number of the http-client-interface . + * @returns {promise} boolean {true|false} + **/ + static setApplicationNameAsync(httpClientUuid, newApplicationName) { + return new Promise(async function (resolve, reject) { + let isUpdated = false; + try { + let applicationNamePath = onfPaths.HTTP_CLIENT_APPLICATION_NAME.replace( + "{uuid}", httpClientUuid); + isUpdated = await fileOperation.writeToDatabaseAsync( + applicationNamePath, + newApplicationName, + false); + resolve(isUpdated); + } catch (error) { + reject(error); + } + }); + } + /** * @description This function creates and returns a new HttpClientInterface. * @param {String} httpClientUuid : http client unique identifier for the new application. diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js index 964b00c6..75fe0ac9 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js @@ -10,6 +10,8 @@ const controlConstruct = require('../ControlConstruct'); const layerProtocol = require('../LayerProtocol'); const onfAttributes = require('../../constants/OnfAttributes'); +const onfPaths = require('../../constants/OnfPaths'); +const fileOperation = require('../../../databaseDriver/JSONDriver'); /** * @extends layerProtocol @@ -71,6 +73,87 @@ class TcpServerInterface extends layerProtocol { localPort); } + /** + * @description This function returns the uuid of the tcpserver for the given protocol. + * @returns {promise} string {uuid} + **/ + static getUuidOfTheProtocol(protocol) { + return new Promise(async function (resolve, reject) { + let tcpServerUuid = {}; + try { + let logicalTerminationPointList = await controlConstruct.getLogicalTerminationPointListAsync( + layerProtocol.layerProtocolNameEnum.TCP_SERVER); + for (let i = 0; i < logicalTerminationPointList.length; i++) { + let logicalTerminationPoint = logicalTerminationPointList[i]; + let _layerProtocol = logicalTerminationPoint["layer-protocol"][0]; + let tcpServerPac = _layerProtocol["tcp-server-interface-1-0:tcp-server-interface-pac"]; + let tcpServerConfiguration = tcpServerPac["tcp-server-interface-configuration"]; + let localProtocol = tcpServerConfiguration["local-protocol"] + if (localProtocol == protocol) { + tcpServerUuid = logicalTerminationPoint["uuid"]; + } + } + resolve(tcpServerUuid); + } catch (error) { + reject(error); + } + }); + } + + /** + * @description This function returns the IpV4 address of the current application. + * @returns {promise} string {localAddress} + **/ + static getLocalAddressOfTheProtocol(protocol) { + return new Promise(async function (resolve, reject) { + let localAddress = {}; + try { + let logicalTerminationPointList = await controlConstruct.getLogicalTerminationPointListAsync( + layerProtocol.layerProtocolNameEnum.TCP_SERVER); + for (let i = 0; i < logicalTerminationPointList.length; i++) { + let logicalTerminationPoint = logicalTerminationPointList[i]; + let _layerProtocol = logicalTerminationPoint["layer-protocol"][0]; + let tcpServerPac = _layerProtocol["tcp-server-interface-1-0:tcp-server-interface-pac"]; + let tcpServerConfiguration = tcpServerPac["tcp-server-interface-configuration"]; + let localProtocol = tcpServerConfiguration["local-protocol"] + if (localProtocol == protocol) { + localAddress = await getConfiguredLocalAddress(tcpServerConfiguration["local-address"]); + } + } + resolve(localAddress); + } catch (error) { + reject(error); + } + }); + } + + /** + * @description This function returns the port where the current application is running. + * @returns {promise} string {localPort} + **/ + static getLocalPortOfTheProtocol(protocol) { + return new Promise(async function (resolve, reject) { + let localPort = undefined; + try { + let logicalTerminationPointList = await controlConstruct.getLogicalTerminationPointListAsync( + layerProtocol.layerProtocolNameEnum.TCP_SERVER); + for (let i = 0; i < logicalTerminationPointList.length; i++) { + let logicalTerminationPoint = logicalTerminationPointList[i]; + let _layerProtocol = logicalTerminationPoint["layer-protocol"][0]; + let tcpServerPac = _layerProtocol["tcp-server-interface-1-0:tcp-server-interface-pac"]; + let tcpServerConfiguration = tcpServerPac["tcp-server-interface-configuration"]; + let localProtocol = tcpServerConfiguration["local-protocol"] + if (localProtocol == protocol) { + localPort = tcpServerConfiguration["local-port"]; + } + } + resolve(localPort); + } catch (error) { + reject(error); + } + }); + } + /** * @description This function returns the IpV4 address of the current application. * @returns {promise} string {localAddress} @@ -126,7 +209,7 @@ class TcpServerInterface extends layerProtocol { let isUpdated = false; try { let addressToBeDeleted = await fileOperation.readFromDatabaseAsync( - onfPaths.TCP_CLIENT_LOCAL_ADDRESS.replace( + onfPaths.TCP_SERVER_LOCAL_ADDRESS.replace( "{uuid}", tcpServerUuid) ); let addressPaths = await getPaths(tcpServerUuid, localAddress, addressToBeDeleted); @@ -150,6 +233,29 @@ class TcpServerInterface extends layerProtocol { }); } + /** + * @description This function modifies the tcp-server local-address. + * @param {String} tcpServerUuid : tcp-server uuid to set tcp-server instance. + * @param {String} localPort : localPort that needs to be modified. + * @returns {promise} boolean {true|false} + **/ + static setLocalPortAsync(tcpServerUuid, localPort) { + return new Promise(async function (resolve, reject) { + let isUpdated = false; + try { + let localPortPath = onfPaths.TCP_SERVER_LOCAL_PORT.replace( + "{uuid}", tcpServerUuid); + isUpdated = await fileOperation.writeToDatabaseAsync( + localPortPath, + localPort, + false); + resolve(isUpdated); + } catch (error) { + reject(error); + } + }); + } + } /** @@ -192,10 +298,10 @@ function getPaths(tcpServerUuid, localAddress, addressToBeDeleted) { localAddressPath = onfPaths.TCP_SERVER_DOMAIN_NAME.replace( "{uuid}", tcpServerUuid); if (!(domainName in addressToBeDeleted)) - pathOfAddressToBeDeleted = onfPaths.TCP_SERVER_IP_ADDRESS.replace( + pathOfAddressToBeDeleted = onfPaths.TCP_SERVER_LOCAL_ADDRESS.replace( "{uuid}", tcpServerUuid); } else { - localAddressPath = onfPaths.TCP_SERVER_IP_ADDRESS.replace( + localAddressPath = onfPaths.TCP_SERVER_LOCAL_ADDRESS.replace( "{uuid}", tcpServerUuid); if (domainName in addressToBeDeleted) pathOfAddressToBeDeleted = onfPaths.TCP_SERVER_DOMAIN_NAME.replace( diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 0d94509f..2407e0be 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -30,7 +30,7 @@ const onfAttributes = require('onf-core-model-ap/applicationPattern/onfModel/con const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriver/JSONDriver'); const controlConstruct = require('onf-core-model-ap/applicationPattern/onfModel/models/ControlConstruct'); -const basicServicesOperationsMapping = require('./BasicServicesOperationsMapping') +const basicServicesOperationsMapping = require('./BasicServicesOperationsMapping'); /** * Embed yourself into the MBH SDN application layer @@ -950,61 +950,129 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC exports.registerYourself = function (body, user, originator, xCorrelator, traceIndicator, customerJourney, operationServerName) { return new Promise(async function (resolve, reject) { try { + let logicalTerminationPointconfigurationStatus; + let forwardingConstructConfigurationStatus; + if (body["registry-office-application"] != undefined) { + /**************************************************************************************** + * Setting up required local variables from the request body + ****************************************************************************************/ - /**************************************************************************************** - * Setting up required local variables from the request body - ****************************************************************************************/ - let applicationName = body["registry-office-application"]; - let releaseNumber = body["registry-office-application-release-number"]; - let applicationAddress = body["registry-office-address"]; - let applicationPort = body["registry-office-port"]; - let registerOperation = body["registration-operation"]; + let registryOfficeApplicationName = body["registry-office-application"]; + let registryOfficeReleaseNumber = body["registry-office-application-release-number"]; + let registryOfficeRegisterOperation = body["registration-operation"]; + let registryOfficeProtocol = body["registry-office-protocol"]; + let registryOfficeAddress = body["registry-office-address"]; + let registryOfficePort = body["registry-office-port"]; - const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('PromptForRegisteringCausesRegistrationRequest'); - if (appNameAndUuidFromForwarding?.applicationName !== applicationName) { - reject(new Error(`The registry-office-application ${applicationName} was not found.`)); - return; - } + // getting values for optional attributes + let httpAddress = body["http-address"]; + let httpPort = body["http-port"]; - /**************************************************************************************** - * Prepare logicalTerminationPointConfigurationInput object to - * configure logical-termination-point - ****************************************************************************************/ - let operationNamesByAttributes = new Map(); - operationNamesByAttributes.set("registration-operation", registerOperation); + let httpsAddress = body["https-address"]; + let httpsPort = body["https-port"]; - let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( - applicationName, - releaseNumber, - applicationAddress, - applicationPort, - operationServerName, - operationNamesByAttributes, - basicServicesOperationsMapping.basicServicesOperationsMapping - ); - let logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.findAndUpdateApplicationInformationAsync( - logicalTerminationPointConfigurationInput - ); + let oldApplicationName = body["preceding-application-name"]; + let oldReleaseNumber = body["preceding-release-number"]; + /**************************************************************************************** + * Prepare logicalTerminationPointConfigurationInput object to + * configure logical-termination-point + ****************************************************************************************/ + // update the registryOffice configuration + const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('PromptForRegisteringCausesRegistrationRequest'); + if (appNameAndUuidFromForwarding?.applicationName !== registryOfficeApplicationName) { + reject(new Error(`The registry-office-application ${registryOfficeApplicationName} was not found.`)); + return; + } + let operationNamesByAttributes = new Map(); + operationNamesByAttributes.set("registration-operation", registryOfficeRegisterOperation); - /**************************************************************************************** - * Prepare attributes to configure forwarding-construct - ****************************************************************************************/ + let tcpObjectList = []; + let tcpObject = formulateTcpObject(registryOfficeProtocol, registryOfficeAddress, registryOfficePort); + tcpObjectList.push(tcpObject); - let forwardingConfigurationInputList = []; - let forwardingConstructConfigurationStatus; - let operationClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.operationClientConfigurationStatusList; + let logicalTerminatinPointConfigurationInput = new LogicalTerminationPointConfigurationInput( + registryOfficeApplicationName, + registryOfficeReleaseNumber, + tcpObjectList, + operationServerName, + operationNamesByAttributes, + basicServicesOperationsMapping.basicServicesOperationsMapping + ); - if (operationClientConfigurationStatusList) { - forwardingConfigurationInputList = await prepareForwardingConfiguration.registerYourself( - operationClientConfigurationStatusList, - registerOperation + logicalTerminationPointconfigurationStatus = await LogicalTerminationPointService.findAndUpdateApplicationInformationAsync( + logicalTerminatinPointConfigurationInput ); - forwardingConstructConfigurationStatus = await ForwardingConfigurationService. + + // update tcp-server configuration if required + let tcpServerWithHttpUpdated = await updateTcpServerDetails("HTTP", httpAddress, httpPort); + if (tcpServerWithHttpUpdated.istcpServerUpdated) { + let configurationStatus = new ConfigurationStatus(tcpServerWithHttpUpdated.tcpServerUuid, '', tcpServerWithHttpUpdated.istcpServerUpdated); + let tcpClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.tcpClientConfigurationStatusList; + tcpClientConfigurationStatusList.push(configurationStatus); + } + + let tcpServerWithHttpsUpdated = await updateTcpServerDetails("HTTPS", httpsAddress, httpsPort); + if (tcpServerWithHttpsUpdated.istcpServerUpdated) { + let configurationStatus = new ConfigurationStatus(tcpServerWithHttpUpdated.tcpServerUuid, '', tcpServerWithHttpUpdated.istcpServerUpdated); + let tcpClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.tcpClientConfigurationStatusList; + tcpClientConfigurationStatusList.push(configurationStatus); + } + + // update old release configuration + let isOldApplicationIsUpdated = false; + let httpUuidOfOldApplication; + + if (oldApplicationName != undefined || oldReleaseNumber != undefined) { + let oldApplicationForwardingTag = "PromptForEmbeddingCausesRequestForBequeathingData"; + let oldApplicationApplicationNameAndHttpClientLtpUuid = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName(oldApplicationForwardingTag); + httpUuidOfOldApplication = oldApplicationApplicationNameAndHttpClientLtpUuid.httpClientLtpUuid; + + if (httpUuidOfOldApplication != undefined) { + if (oldApplicationName != undefined) { + let configuredOldApplicationName = await httpClientInterface.getApplicationNameAsync(httpUuidOfOldApplication); + if (configuredOldApplicationName != oldApplicationName) { + isOldApplicationIsUpdated = await httpClientInterface.setApplicationNameAsync(httpUuidOfOldApplication, oldApplicationName); + } + } + if (oldReleaseNumber != undefined) { + let configuredOldApplicationReleaseNumber = await httpClientInterface.getReleaseNumberAsync(httpUuidOfOldApplication); + if (configuredOldApplicationReleaseNumber != oldReleaseNumber) { + isOldApplicationIsUpdated = await httpClientInterface.setReleaseNumberAsync(httpUuidOfOldApplication, oldReleaseNumber); + } + } + if (isOldApplicationIsUpdated) { + let configurationStatus = new ConfigurationStatus(httpUuidOfOldApplication, '', isOldApplicationIsUpdated); + let tcpClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.tcpClientConfigurationStatusList; + tcpClientConfigurationStatusList.push(configurationStatus); + } + } + } + + + /**************************************************************************************** + * Prepare attributes to configure forwarding-construct + ****************************************************************************************/ + + let forwardingConfigurationInputList = []; + let operationClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.operationClientConfigurationStatusList; + + if (operationClientConfigurationStatusList) { + forwardingConfigurationInputList = await prepareForwardingConfiguration.registerYourself( + operationClientConfigurationStatusList, + registryOfficeRegisterOperation + ); + forwardingConstructConfigurationStatus = await ForwardingConfigurationService. configureForwardingConstructAsync( operationServerName, forwardingConfigurationInputList ); + } + } else { + customerJourney = traceIndicator; + traceIndicator = xCorrelator; + xCorrelator = originator; + user = body; } /**************************************************************************************** @@ -1280,4 +1348,50 @@ async function resolveApplicationNameAndHttpClientLtpUuidFromForwardingName(forw const httpClientLtpUuid = httpLtpUuidList[0]; const applicationName = await httpClientInterface.getApplicationNameAsync(httpClientLtpUuid); return applicationName === undefined ? { applicationName: null, httpClientLtpUuid } : { applicationName, httpClientLtpUuid }; +} + +/** + * @description This function helps to formulate the tcpClient object in the format { protocol : "" , address : "" , port : ""} + * @return {Promise} return the formulated tcpClientObject + **/ +function formulateTcpObject(protocol, address, port) { + let tcpInfoObject; + try { + tcpInfoObject = { + "protocol": protocol, + "address": address, + "port": port + }; + } catch (error) { + console.log("error in formulating tcp object"); + } + return tcpInfoObject; +} + +/** + * @description This function helps to get the APISegment of the operationClient uuid + * @return {Promise} returns the APISegment + **/ +async function updateTcpServerDetails(protocol, address, port) { + let updatedDetails = {}; + let istcpServerUpdated = false; + let tcpServerUuid; + if (address != undefined || port != undefined) { + tcpServerUuid = await tcpServerInterface.getUuidOfTheProtocol(protocol); + if (address != undefined) { + let configuredAddress = await tcpServerInterface.getLocalAddressOfTheProtocol(protocol); + if (configuredAddress != address) { + istcpServerUpdated = await tcpServerInterface.setLocalAddressAsync(tcpServerUuid, address); + } + } + if (port != undefined) { + let configuredPort = await tcpServerInterface.getLocalPortOfTheProtocol(protocol); + if (configuredPort != port) { + istcpServerUpdated = await tcpServerInterface.setLocalPortAsync(tcpServerUuid, port); + } + } + } + updatedDetails.tcpServerUuid = tcpServerUuid; + updatedDetails.istcpServerUpdated = istcpServerUpdated; + return updatedDetails; } \ No newline at end of file diff --git a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js index 9a27380d..39719fae 100644 --- a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js @@ -70,12 +70,46 @@ exports.registerYourself = function (logicalTerminationPointconfigurationStatus, let registrationApplicationForwardingName = "PromptForRegisteringCausesRegistrationRequest"; let registrationApplicationContext; let registrationApplicationRequestBody = {}; + let tcpServerList = []; registrationApplicationRequestBody.applicationName = await httpServerInterface.getApplicationNameAsync(); - registrationApplicationRequestBody.applicationReleaseNumber = await httpServerInterface.getReleaseNumberAsync(); - registrationApplicationRequestBody.applicationAddress = await tcpServerInterface.getLocalAddress(); - registrationApplicationRequestBody.applicationPort = await tcpServerInterface.getLocalPort(); + registrationApplicationRequestBody.releaseNumber = await httpServerInterface.getReleaseNumberAsync(); registrationApplicationRequestBody.embeddingOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-001"); registrationApplicationRequestBody.clientUpdateOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-007"); + registrationApplicationRequestBody.operationClientUpdateOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-011"); + + // formulate the tcp-server-list + let tcpHttpAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("http"); + let tcpHttpPort = await tcpServerInterface.getLocalPortOfTheProtocol("http"); + if(tcpHttpAddress!=undefined && tcpHttpPort!=undefined){ + if("ipv-4-address" in tcpHttpAddress){ + tcpHttpAddress = { + "ip-address": tcpHttpAddress + } + } + let tcpServer = { + protocol : "HTTP", + port : tcpHttpPort, + address : tcpHttpAddress + } + tcpServerList.push(tcpServer); + } + let tcpHttpsAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("https"); + let tcpHttpsPort = await tcpServerInterface.getLocalPortOfTheProtocol("https"); + if(tcpHttpsAddress!=undefined && tcpHttpsPort!=undefined){ + if("ipv-4-address" in tcpHttpsAddress){ + tcpHttpsAddress = { + "ip-address": tcpHttpsAddress + } + } + let tcpServer = { + protocol : "HTTPS", + port : tcpHttpsPort, + address : tcpHttpsAddress + } + tcpServerList.push(tcpServer); + } + + registrationApplicationRequestBody.tcpServerList = tcpServerList; registrationApplicationRequestBody = onfFormatter.modifyJsonObjectKeysToKebabCase(registrationApplicationRequestBody); forwardingAutomation = new forwardingConstructAutomationInput( registrationApplicationForwardingName, From 14fd4df617dbe2741462c33ef021ca4c53f9f79c Mon Sep 17 00:00:00 2001 From: Prathiba Date: Wed, 28 Dec 2022 22:22:40 +0100 Subject: [PATCH 07/79] Implementation to be updated in BasicServices for the Generic representation mechanism Fixes #349 --- .../layerProtocols/TcpServerInterface.js | 2 +- .../basicServices/BasicServicesService.js | 262 +++++++++--------- .../services/PrepareForwardingAutomation.js | 8 +- 3 files changed, 129 insertions(+), 143 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js index 75fe0ac9..1556d7d5 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js @@ -298,7 +298,7 @@ function getPaths(tcpServerUuid, localAddress, addressToBeDeleted) { localAddressPath = onfPaths.TCP_SERVER_DOMAIN_NAME.replace( "{uuid}", tcpServerUuid); if (!(domainName in addressToBeDeleted)) - pathOfAddressToBeDeleted = onfPaths.TCP_SERVER_LOCAL_ADDRESS.replace( + pathOfAddressToBeDeleted = onfPaths.TCP_SERVER_IP_ADDRESS.replace( "{uuid}", tcpServerUuid); } else { localAddressPath = onfPaths.TCP_SERVER_LOCAL_ADDRESS.replace( diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 2407e0be..90be5c23 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -31,6 +31,7 @@ const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriv const controlConstruct = require('onf-core-model-ap/applicationPattern/onfModel/models/ControlConstruct'); const basicServicesOperationsMapping = require('./BasicServicesOperationsMapping'); +const genericRepresentation = require('onf-core-model-ap-bs/basicServices/GenericRepresentation'); /** * Embed yourself into the MBH SDN application layer @@ -104,10 +105,10 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi relayOperationUpdateOperation ); forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - configureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + configureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); } /**************************************************************************************** @@ -174,10 +175,10 @@ exports.endSubscription = function (body, user, originator, xCorrelator, traceIn subscriptionOperation ); let forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - unConfigureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + unConfigureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); /**************************************************************************************** * Prepare attributes to automate forwarding-construct @@ -260,63 +261,19 @@ exports.informAboutApplication = function (user, originator, xCorrelator, traceI * customerJourney String Holds information supporting customer’s journey to which the execution applies * returns inline_response_200_5 **/ -exports.informAboutApplicationInGenericRepresentation = function (user, originator, xCorrelator, traceIndicator, customerJourney) { +exports.informAboutApplicationInGenericRepresentation = function (user, originator, xCorrelator, traceIndicator, customerJourney, operationServerName) { return new Promise(async function (resolve, reject) { let response = {}; try { /**************************************************************************************** * Preparing consequent-action-list for response body ****************************************************************************************/ - let consequentActionList = []; - let protocol = "http"; - - let localAddress = await tcpServerInterface.getLocalAddress(); - let localPort = await tcpServerInterface.getLocalPort(); - let baseUrl = protocol + "://" + localAddress + ":" + localPort - - let controlConstructUuid = await fileOperation.readFromDatabaseAsync(onfPaths.CONTROL_CONSTRUCT_UUID); - - let releaseHistoryOperationServerUuid = controlConstructUuid + "-op-s-2004"; - let releaseHistoryOperationName = await operationServerInterface.getOperationNameAsync( - releaseHistoryOperationServerUuid); - - let LabelForReleaseHistory = "Release History"; - let requestForReleaseHistory = baseUrl + releaseHistoryOperationName; - let consequentActionForReleaseHistory = new consequentAction( - LabelForReleaseHistory, - requestForReleaseHistory, - false - ); - consequentActionList.push(consequentActionForReleaseHistory); - - let LabelForAPIDocumentation = "API Documentation"; - let requestForAPIDocumentation = baseUrl + "/docs"; - let consequentActionForAPIDocumentation = new consequentAction( - LabelForAPIDocumentation, - requestForAPIDocumentation, - true - ); - consequentActionList.push(consequentActionForAPIDocumentation); + let consequentActionList = await genericRepresentation.getConsequentActionList(operationServerName); /**************************************************************************************** * Preparing response-value-list for response body ****************************************************************************************/ - let responseValueList = []; - - let httpServerCapability = await httpServerInterface.getHttpServerCapabilityAsync(); - - Object.entries(httpServerCapability).map(entry => { - let key = onfAttributeFormatter.modifyKebabCaseToLowerCamelCase(entry[0]); - let value = entry[1]; - if (key != "releaseList") { - let reponseValue = new responseValue( - key, - value, - typeof value - ); - responseValueList.push(reponseValue); - } - }); + let responseValueList = await genericRepresentation.getResponseValueList(operationServerName); /**************************************************************************************** * Setting 'application/json' response body @@ -325,7 +282,6 @@ exports.informAboutApplicationInGenericRepresentation = function (user, originat consequentActionList, responseValueList }); - } catch (error) { console.log(error); } @@ -333,7 +289,7 @@ exports.informAboutApplicationInGenericRepresentation = function (user, originat if (Object.keys(response).length > 0) { resolve(response[Object.keys(response)[0]]); } else { - reject(); + resolve(); } }); @@ -386,38 +342,19 @@ exports.informAboutReleaseHistory = function (user, originator, xCorrelator, tra * customerJourney String Holds information supporting customer’s journey to which the execution applies * returns inline_response_200_7 **/ -exports.informAboutReleaseHistoryInGenericRepresentation = function (user, originator, xCorrelator, traceIndicator, customerJourney) { +exports.informAboutReleaseHistoryInGenericRepresentation = function (user, originator, xCorrelator, traceIndicator, customerJourney, operationServerName) { return new Promise(async function (resolve, reject) { let response = {}; try { /**************************************************************************************** * Preparing consequent-action-list for response body ****************************************************************************************/ - let consequentActionList = []; + let consequentActionList = await genericRepresentation.getConsequentActionList(operationServerName); /**************************************************************************************** * Preparing response-value-list for response body ****************************************************************************************/ - let responseValueList = []; - let releaseList = await httpServerInterface.getReleaseListAsync(); - - for (let i = 0; i < releaseList.length; i++) { - - let release = releaseList[i]; - - let releaseNumber = release[onfAttributes.HTTP_SERVER.RELEASE_NUMBER]; - let releaseDate = release[onfAttributes.HTTP_SERVER.RELEASE_DATE]; - let changes = release[onfAttributes.HTTP_SERVER.CHANGES]; - let releaseDateAndChanges = releaseDate + " - " + changes; - - let reponseValue = new responseValue( - releaseNumber, - releaseDateAndChanges, - typeof releaseDateAndChanges - ); - - responseValueList.push(reponseValue); - } + let responseValueList = await genericRepresentation.getResponseValueList(operationServerName); /**************************************************************************************** * Setting 'application/json' response body @@ -429,13 +366,13 @@ exports.informAboutReleaseHistoryInGenericRepresentation = function (user, origi } catch (error) { console.log(error); } + if (Object.keys(response).length > 0) { resolve(response[Object.keys(response)[0]]); } else { resolve(); } }); - } @@ -504,10 +441,10 @@ exports.inquireOamRequestApprovals = function (body, user, originator, xCorrelat oamApprovalOperation ); forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - configureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + configureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); } /**************************************************************************************** @@ -554,7 +491,7 @@ exports.listLtpsAndFcs = function (user, originator, xCorrelator, traceIndicator let controlConstructUrl = onfPaths.CONTROL_CONSTRUCT; let controlConstruct = await fileOperation.readFromDatabaseAsync(controlConstructUrl); let logicalterminationpoint = controlConstruct[onfAttributes.FC_PORT.LOGICAL_TERMINATION_POINT] - + for (let i = 0; i < logicalterminationpoint.length; i++) { let layerprotocol = logicalterminationpoint[i][onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL] for (let j = 0; j < layerprotocol.length; j++) { @@ -654,10 +591,10 @@ exports.redirectOamRequestInformation = function (body, user, originator, xCorre oamLogOperation ); forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - configureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + configureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); } /**************************************************************************************** @@ -750,10 +687,10 @@ exports.redirectServiceRequestInformation = function (body, user, originator, xC serviceLogOperation ); forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - configureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + configureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); } /**************************************************************************************** @@ -792,7 +729,7 @@ exports.redirectServiceRequestInformation = function (body, user, originator, xC * no response value expected for this operation **/ exports.redirectTopologyChangeInformation = function (body, user, originator, xCorrelator, traceIndicator, customerJourney, operationServerName) { - let response = {}; + let response = {}; return new Promise(async function (resolve, reject) { try { @@ -861,10 +798,10 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC fcPortDeletionTopologyOperation ); forwardingConstructConfigurationStatus = await ForwardingConfigurationService. - configureForwardingConstructAsync( - operationServerName, - forwardingConfigurationInputList - ); + configureForwardingConstructAsync( + operationServerName, + forwardingConfigurationInputList + ); } /**************************************************************************************** @@ -883,43 +820,42 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC customerJourney ); - let forwrdingContructResponse = await controlConstruct.getForwardingDomainListAsync() - let serverclientinterfacepac; - let controlConstructUrl = onfPaths.CONTROL_CONSTRUCT; - let controlConstructcompleteResponse = await fileOperation.readFromDatabaseAsync(controlConstructUrl); - let controluuid = controlConstructcompleteResponse['uuid'] - let logicalterminationpoint = await fileOperation.readFromDatabaseAsync( - onfPaths.LOGICAL_TERMINATION_POINT - ); - for (let i = 0; i < logicalterminationpoint.length; i++) { - let layerprotocol = logicalterminationpoint[i][onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL] - for (let j = 0; j < layerprotocol.length; j++) { - let layerProtocalName = layerprotocol[j]['layer-protocol-name'] - if(layerProtocalName == 'operation-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_OPERATION_LAYER'){ - let operationclientinterfacepac = layerprotocol[j][onfAttributes.LAYER_PROTOCOL.OPERATION_CLIENT_INTERFACE_PAC] - let clientconfiguration = operationclientinterfacepac[onfAttributes.OPERATION_CLIENT.CONFIGURATION] - if(clientconfiguration !== undefined){ - delete clientconfiguration['operation-key']; - } - } - else if(layerProtocalName == 'operation-server-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_OPERATION_LAYER'){ - serverclientinterfacepac = layerprotocol[j][onfAttributes.LAYER_PROTOCOL.OPERATION_SERVER_INTERFACE_PAC] - let serverconfiguration = serverclientinterfacepac[onfAttributes. OPERATION_SERVER.CONFIGURATION] - if(serverconfiguration !== undefined){ - delete serverconfiguration['operation-key']; - } - } + let forwrdingContructResponse = await controlConstruct.getForwardingDomainListAsync() + let serverclientinterfacepac; + let controlConstructUrl = onfPaths.CONTROL_CONSTRUCT; + let controlConstructcompleteResponse = await fileOperation.readFromDatabaseAsync(controlConstructUrl); + let controluuid = controlConstructcompleteResponse['uuid'] + let logicalterminationpoint = await fileOperation.readFromDatabaseAsync( + onfPaths.LOGICAL_TERMINATION_POINT + ); + for (let i = 0; i < logicalterminationpoint.length; i++) { + let layerprotocol = logicalterminationpoint[i][onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL] + for (let j = 0; j < layerprotocol.length; j++) { + let layerProtocalName = layerprotocol[j]['layer-protocol-name'] + if (layerProtocalName == 'operation-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_OPERATION_LAYER') { + let operationclientinterfacepac = layerprotocol[j][onfAttributes.LAYER_PROTOCOL.OPERATION_CLIENT_INTERFACE_PAC] + let clientconfiguration = operationclientinterfacepac[onfAttributes.OPERATION_CLIENT.CONFIGURATION] + if (clientconfiguration !== undefined) { + delete clientconfiguration['operation-key']; + } + } else if (layerProtocalName == 'operation-server-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_OPERATION_LAYER') { + serverclientinterfacepac = layerprotocol[j][onfAttributes.LAYER_PROTOCOL.OPERATION_SERVER_INTERFACE_PAC] + let serverconfiguration = serverclientinterfacepac[onfAttributes.OPERATION_SERVER.CONFIGURATION] + if (serverconfiguration !== undefined) { + delete serverconfiguration['operation-key']; + } + } + } } - } - let controlConstructResponse = { - "core-model-1-4:control-construct":{ - "uuid" : controluuid, - "logical-termination-point": logicalterminationpoint, - "forwarding-domain" : forwrdingContructResponse - } + let controlConstructResponse = { + "core-model-1-4:control-construct": { + "uuid": controluuid, + "logical-termination-point": logicalterminationpoint, + "forwarding-domain": forwrdingContructResponse + } }; - /**************************************************************************************** + /**************************************************************************************** * Setting 'application/json' response body ****************************************************************************************/ response['application/json'] = controlConstructResponse; @@ -1018,7 +954,7 @@ exports.registerYourself = function (body, user, originator, xCorrelator, traceI let tcpClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.tcpClientConfigurationStatusList; tcpClientConfigurationStatusList.push(configurationStatus); } - + // update old release configuration let isOldApplicationIsUpdated = false; let httpUuidOfOldApplication; @@ -1099,6 +1035,50 @@ exports.registerYourself = function (body, user, originator, xCorrelator, traceI } +/** + * Starts application in generic representation + * + * user String User identifier from the system starting the service call + * originator String 'Identification for the system consuming the API, as defined in [/core-model-1-4:control-construct/logical-termination-point={uuid}/layer-protocol=0/http-client-interface-1-0:http-client-interface-pac/http-client-interface-configuration/application-name]' + * xCorrelator String UUID for the service execution flow that allows to correlate requests and responses + * traceIndicator String Sequence of request numbers along the flow + * customerJourney String Holds information supporting customer’s journey to which the execution applies + * returns genericRepresentation + **/ +exports.startApplicationInGenericRepresentation = function (user, originator, xCorrelator, traceIndicator, customerJourney, operationServerName) { + return new Promise(async function (resolve, reject) { + let response = {}; + try { + /**************************************************************************************** + * Preparing consequent-action-list for response body + ****************************************************************************************/ + let consequentActionList = await genericRepresentation.getConsequentActionList(operationServerName); + + /**************************************************************************************** + * Preparing response-value-list for response body + ****************************************************************************************/ + let responseValueList = await genericRepresentation.getResponseValueList(operationServerName); + + /**************************************************************************************** + * Setting 'application/json' response body + ****************************************************************************************/ + response['application/json'] = onfAttributeFormatter.modifyJsonObjectKeysToKebabCase({ + consequentActionList, + responseValueList + }); + } catch (error) { + console.log(error); + } + + if (Object.keys(response).length > 0) { + resolve(response[Object.keys(response)[0]]); + } else { + resolve(); + } + }); +} + + /** * Allows updating connection data of a serving application * @@ -1136,9 +1116,9 @@ exports.updateClient = function (body, user, originator, xCorrelator, traceIndic if (isOldApplicationExists) { /**************************************************************************************** - * Prepare logicalTerminationPointConfigurationInput object to - * configure logical-termination-point - ****************************************************************************************/ + * Prepare logicalTerminationPointConfigurationInput object to + * configure logical-termination-point + ****************************************************************************************/ let operationNamesByAttributes = []; let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( @@ -1329,7 +1309,7 @@ async function resolveApplicationNameAndHttpClientLtpUuidFromForwardingName(forw if (forwardingConstruct === undefined) { return null; } - + let fcPortOutputDirectionLogicalTerminationPointList = []; const fcPortList = forwardingConstruct[onfAttributes.FORWARDING_CONSTRUCT.FC_PORT]; for (const fcPort of fcPortList) { @@ -1347,7 +1327,13 @@ async function resolveApplicationNameAndHttpClientLtpUuidFromForwardingName(forw const httpLtpUuidList = await LogicalTerminationPoint.getServerLtpListAsync(opLtpUuid); const httpClientLtpUuid = httpLtpUuidList[0]; const applicationName = await httpClientInterface.getApplicationNameAsync(httpClientLtpUuid); - return applicationName === undefined ? { applicationName: null, httpClientLtpUuid } : { applicationName, httpClientLtpUuid }; + return applicationName === undefined ? { + applicationName: null, + httpClientLtpUuid + } : { + applicationName, + httpClientLtpUuid + }; } /** diff --git a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js index 39719fae..09adfe4c 100644 --- a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js @@ -78,8 +78,8 @@ exports.registerYourself = function (logicalTerminationPointconfigurationStatus, registrationApplicationRequestBody.operationClientUpdateOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-011"); // formulate the tcp-server-list - let tcpHttpAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("http"); - let tcpHttpPort = await tcpServerInterface.getLocalPortOfTheProtocol("http"); + let tcpHttpAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("HTTP"); + let tcpHttpPort = await tcpServerInterface.getLocalPortOfTheProtocol("HTTP"); if(tcpHttpAddress!=undefined && tcpHttpPort!=undefined){ if("ipv-4-address" in tcpHttpAddress){ tcpHttpAddress = { @@ -93,8 +93,8 @@ exports.registerYourself = function (logicalTerminationPointconfigurationStatus, } tcpServerList.push(tcpServer); } - let tcpHttpsAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("https"); - let tcpHttpsPort = await tcpServerInterface.getLocalPortOfTheProtocol("https"); + let tcpHttpsAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("HTTPS"); + let tcpHttpsPort = await tcpServerInterface.getLocalPortOfTheProtocol("HTTPS"); if(tcpHttpsAddress!=undefined && tcpHttpsPort!=undefined){ if("ipv-4-address" in tcpHttpsAddress){ tcpHttpsAddress = { From 4c9415695df11ec850b74b4313dad3f4e3373dd0 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Wed, 28 Dec 2022 22:35:32 +0100 Subject: [PATCH 08/79] Support Version 2.0.0 changes for /v1/inform-about-application Fixes #490 --- server/basicServices/basicServices/BasicServicesService.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 90be5c23..4079f021 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -227,11 +227,7 @@ exports.informAboutApplication = function (user, originator, xCorrelator, traceI let key = entry[0]; let value = entry[1]; if (key != onfAttributes.HTTP_SERVER.RELEASE_LIST) { - if (key === onfAttributes.HTTP_SERVER.RELEASE_NUMBER) { - applicationInformation['application-release-number'] = value; - } else { - applicationInformation[key] = value; - } + applicationInformation[key] = value; } }); From c4f4e380968df16c95cd7f501cfeab78276e58e4 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Thu, 29 Dec 2022 08:40:17 +0100 Subject: [PATCH 09/79] Support Version 2.0.0 changes for /v1/embed-yourself Fixes #492 --- .../layerProtocols/TcpServerInterface.js | 24 ++++++- .../basicServices/BasicServicesService.js | 71 ++++++++++++++++--- .../services/PrepareForwardingAutomation.js | 29 ++++---- 3 files changed, 99 insertions(+), 25 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js index 1556d7d5..44e47d71 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface.js @@ -154,6 +154,28 @@ class TcpServerInterface extends layerProtocol { }); } + /** + * @description This function returns the protocol of the current application. + * @returns {promise} string {localProtocol} + **/ + static getLocalProtocol() { + return new Promise(async function (resolve, reject) { + let localProtocol = {}; + try { + let logicalTerminationPointList = await controlConstruct.getLogicalTerminationPointListAsync( + layerProtocol.layerProtocolNameEnum.TCP_SERVER); + let logicalTerminationPoint = logicalTerminationPointList[0]; + let _layerProtocol = logicalTerminationPoint["layer-protocol"][0]; + let tcpServerPac = _layerProtocol["tcp-server-interface-1-0:tcp-server-interface-pac"]; + let tcpServerConfiguration = tcpServerPac["tcp-server-interface-configuration"]; + localProtocol = tcpServerConfiguration["local-protocol"]; + resolve(localProtocol); + } catch (error) { + reject(error); + } + }); + } + /** * @description This function returns the IpV4 address of the current application. * @returns {promise} string {localAddress} @@ -244,7 +266,7 @@ class TcpServerInterface extends layerProtocol { let isUpdated = false; try { let localPortPath = onfPaths.TCP_SERVER_LOCAL_PORT.replace( - "{uuid}", tcpServerUuid); + "{uuid}", tcpServerUuid); isUpdated = await fileOperation.writeToDatabaseAsync( localPortPath, localPort, diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 4079f021..6ae6d7a3 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -4,7 +4,7 @@ const LogicalTerminationPoint = require('onf-core-model-ap/applicationPattern/on const LogicalTerminationPointConfigurationInput = require('onf-core-model-ap/applicationPattern/onfModel/services/models/logicalTerminationPoint/ConfigurationInputWithMapping'); const LogicalTerminationPointService = require('onf-core-model-ap/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices'); const LogicalTerminationPointConfigurationStatus = require('onf-core-model-ap/applicationPattern/onfModel/services/models/logicalTerminationPoint/ConfigurationStatus'); -const layerProtocol = require('onf-core-model-ap/applicationPattern/onfModel/models/LayerProtocol'); +const LayerProtocol = require('onf-core-model-ap/applicationPattern/onfModel/models/LayerProtocol'); const FcPort = require('onf-core-model-ap/applicationPattern/onfModel/models/FcPort'); const ForwardingDomain = require('onf-core-model-ap/applicationPattern/onfModel/models/ForwardingDomain'); @@ -16,13 +16,12 @@ const ConfigurationStatus = require('onf-core-model-ap/applicationPattern/onfMod const httpServerInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/HttpServerInterface'); const tcpServerInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface'); +const tcpClientInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/TcpClientInterface'); const operationServerInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/OperationServerInterface'); const operationClientInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface'); const httpClientInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/HttpClientInterface'); const onfAttributeFormatter = require('onf-core-model-ap/applicationPattern/onfModel/utility/OnfAttributeFormatter'); -const consequentAction = require('onf-core-model-ap/applicationPattern/rest/server/responseBody/ConsequentAction'); -const responseValue = require('onf-core-model-ap/applicationPattern/rest/server/responseBody/ResponseValue'); const onfPaths = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfPaths'); const onfAttributes = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfAttributes'); @@ -53,12 +52,18 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi ****************************************************************************************/ let applicationName = body["registry-office-application"]; let releaseNumber = body["registry-office-application-release-number"]; + let applicationProtocol = body["registry-office-protocol"]; let applicationAddress = body["registry-office-address"]; let applicationPort = body["registry-office-port"]; let deregisterOperation = body["deregistration-operation"]; let relayOperationUpdateOperation = body["relay-operation-update-operation"]; let relayServerReplacementOperation = body["relay-server-replacement-operation"]; + + let oldReleaseProtocol = body["old-release-protocol"]; + let oldReleaseAddress = body["old-release-address"]; + let oldReleasePort = body["old-release-port"]; + const appNameAndUuidFromForwarding = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName('PromptForBequeathingDataCausesRequestForBroadcastingInfoAboutServerReplacement'); if (appNameAndUuidFromForwarding?.applicationName !== applicationName) { reject(new Error(`The registry-office-application ${applicationName} was not found.`)); @@ -75,11 +80,14 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi operationNamesByAttributes.set("relay-server-replacement-operation", relayServerReplacementOperation); operationNamesByAttributes.set("relay-operation-update-operation", relayOperationUpdateOperation); + let tcpObjectList = []; + let tcpObject = formulateTcpObject(applicationProtocol, applicationAddress, applicationPort); + tcpObjectList.push(tcpObject); + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( applicationName, releaseNumber, - applicationAddress, - applicationPort, + tcpObjectList, operationServerName, operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping @@ -88,6 +96,35 @@ exports.embedYourself = function (body, user, originator, xCorrelator, traceIndi logicalTerminationPointConfigurationInput ); + let isOldApplicationTcpClientUpdated = false; + let oldApplicationTcpClientUuid; + let oldApplicationForwardingTag = "PromptForEmbeddingCausesRequestForBequeathingData"; + let oldApplicationApplicationNameAndHttpClientLtpUuid = await resolveApplicationNameAndHttpClientLtpUuidFromForwardingName(oldApplicationForwardingTag); + let httpUuidOfOldApplication = oldApplicationApplicationNameAndHttpClientLtpUuid.httpClientLtpUuid; + + if (httpUuidOfOldApplication != undefined) { + let tcpClientUuidList = await LogicalTerminationPoint.getServerLtpListAsync(httpUuidOfOldApplication); + if (tcpClientUuidList != undefined) { + oldApplicationTcpClientUuid = tcpClientUuidList[0]; + let tcpClientProtocolOfOldApplication = await tcpClientInterface.getRemoteProtocolAsync(oldApplicationTcpClientUuid); + if (oldReleaseProtocol != tcpClientProtocolOfOldApplication) { + isOldApplicationTcpClientUpdated = await tcpClientInterface.setRemoteProtocolAsync(oldApplicationTcpClientUuid, oldReleaseProtocol); + } + let tcpClientAddressOfOldApplication = await tcpClientInterface.getRemoteAddressAsync(oldApplicationTcpClientUuid); + if (oldReleaseAddress != tcpClientAddressOfOldApplication) { + isOldApplicationTcpClientUpdated = await tcpClientInterface.setRemoteAddressAsync(oldApplicationTcpClientUuid, oldReleaseAddress); + } + let tcpClientPortOfOldApplication = await tcpClientInterface.getRemotePortAsync(oldApplicationTcpClientUuid); + if (oldReleasePort != tcpClientPortOfOldApplication) { + isOldApplicationTcpClientUpdated = await tcpClientInterface.setRemotePortAsync(oldApplicationTcpClientUuid, oldReleasePort); + } + } + } + if (isOldApplicationTcpClientUpdated) { + let configurationStatus = new ConfigurationStatus(oldApplicationTcpClientUuid, '', isOldApplicationTcpClientUpdated); + let tcpClientConfigurationStatusList = logicalTerminationPointconfigurationStatus.tcpClientConfigurationStatusList; + tcpClientConfigurationStatusList.push(configurationStatus); + } /**************************************************************************************** * Prepare attributes to configure forwarding-construct @@ -486,16 +523,30 @@ exports.listLtpsAndFcs = function (user, originator, xCorrelator, traceIndicator ****************************************************************************************/ let controlConstructUrl = onfPaths.CONTROL_CONSTRUCT; let controlConstruct = await fileOperation.readFromDatabaseAsync(controlConstructUrl); + delete controlConstruct['profile-collection']; let logicalterminationpoint = controlConstruct[onfAttributes.FC_PORT.LOGICAL_TERMINATION_POINT] for (let i = 0; i < logicalterminationpoint.length; i++) { let layerprotocol = logicalterminationpoint[i][onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL] for (let j = 0; j < layerprotocol.length; j++) { - let operationclientinterfacepac = layerprotocol[j][onfAttributes.LAYER_PROTOCOL.OPERATION_CLIENT_INTERFACE_PAC] - if (operationclientinterfacepac !== undefined) { - let detailedloggingison = operationclientinterfacepac[onfAttributes.OPERATION_CLIENT.CONFIGURATION] - if (detailedloggingison !== undefined) { - delete detailedloggingison['detailed-logging-is-on']; + let layerProtocolInstance = layerprotocol[j]; + let layerProtocolName = layerProtocolInstance[onfAttributes.LAYER_PROTOCOL.LAYER_PROTOCOL_NAME]; + if (layerProtocolName == LayerProtocol.layerProtocolNameEnum.OPERATION_CLIENT) { + let operationclientinterfacepac = layerProtocolInstance[onfAttributes.LAYER_PROTOCOL.OPERATION_CLIENT_INTERFACE_PAC]; + if (operationclientinterfacepac !== undefined) { + let operationClientConfiguration = operationclientinterfacepac[onfAttributes.OPERATION_CLIENT.CONFIGURATION]; + if (operationClientConfiguration !== undefined) { + delete operationClientConfiguration['detailed-logging-is-on']; + delete operationClientConfiguration['operation-key']; + } + } + } else if (layerProtocolName == LayerProtocol.layerProtocolNameEnum.OPERATION_SERVER) { + let operationServerinterfacepac = layerProtocolInstance[onfAttributes.LAYER_PROTOCOL.OPERATION_SERVER_INTERFACE_PAC]; + if (operationServerinterfacepac !== undefined) { + let operationServerConfiguration = operationServerinterfacepac[onfAttributes.OPERATION_SERVER.CONFIGURATION]; + if (operationServerConfiguration !== undefined) { + delete operationServerConfiguration['operation-key']; + } } } } diff --git a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js index 09adfe4c..f98579ab 100644 --- a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js @@ -26,6 +26,7 @@ exports.embedYourself = function (logicalTerminationPointconfigurationStatus, fo let bequeathYourDataAndDieRequestBody = {}; bequeathYourDataAndDieRequestBody.newApplicationName = await httpServerInterface.getApplicationNameAsync(); bequeathYourDataAndDieRequestBody.newApplicationRelease = await httpServerInterface.getReleaseNumberAsync(); + bequeathYourDataAndDieRequestBody.newApplicationProtocol = await tcpServerInterface.getLocalProtocol(); bequeathYourDataAndDieRequestBody.newApplicationAddress = await tcpServerInterface.getLocalAddress(); bequeathYourDataAndDieRequestBody.newApplicationPort = await tcpServerInterface.getLocalPort(); bequeathYourDataAndDieRequestBody = onfFormatter.modifyJsonObjectKeysToKebabCase(bequeathYourDataAndDieRequestBody); @@ -76,35 +77,35 @@ exports.registerYourself = function (logicalTerminationPointconfigurationStatus, registrationApplicationRequestBody.embeddingOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-001"); registrationApplicationRequestBody.clientUpdateOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-007"); registrationApplicationRequestBody.operationClientUpdateOperation = await operationServerInterface.getOperationNameAsync(controlConstructUuid + "-op-s-bm-011"); - + // formulate the tcp-server-list let tcpHttpAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("HTTP"); let tcpHttpPort = await tcpServerInterface.getLocalPortOfTheProtocol("HTTP"); - if(tcpHttpAddress!=undefined && tcpHttpPort!=undefined){ - if("ipv-4-address" in tcpHttpAddress){ + if (tcpHttpAddress != undefined && tcpHttpPort != undefined) { + if ("ipv-4-address" in tcpHttpAddress) { tcpHttpAddress = { "ip-address": tcpHttpAddress - } + } } let tcpServer = { - protocol : "HTTP", - port : tcpHttpPort, - address : tcpHttpAddress + protocol: "HTTP", + port: tcpHttpPort, + address: tcpHttpAddress } tcpServerList.push(tcpServer); } let tcpHttpsAddress = await tcpServerInterface.getLocalAddressOfTheProtocol("HTTPS"); let tcpHttpsPort = await tcpServerInterface.getLocalPortOfTheProtocol("HTTPS"); - if(tcpHttpsAddress!=undefined && tcpHttpsPort!=undefined){ - if("ipv-4-address" in tcpHttpsAddress){ + if (tcpHttpsAddress != undefined && tcpHttpsPort != undefined) { + if ("ipv-4-address" in tcpHttpsAddress) { tcpHttpsAddress = { "ip-address": tcpHttpsAddress - } + } } let tcpServer = { - protocol : "HTTPS", - port : tcpHttpsPort, - address : tcpHttpsAddress + protocol: "HTTPS", + port: tcpHttpsPort, + address: tcpHttpsAddress } tcpServerList.push(tcpServer); } @@ -145,7 +146,7 @@ exports.endSubscription = function (logicalTerminationPointconfigurationStatus, let forwardingConstructAutomationList = []; try { - /*********************************************************************************** + /*********************************************************************************** * forwardings for application layer topology ************************************************************************************/ let applicationLayerTopologyForwardingInputList = await prepareALTForwardingAutomation.getALTUnConfigureForwardingAutomationInputAsync( From 965b1d804b976482ce1a76a1ec36f1f2242de39b Mon Sep 17 00:00:00 2001 From: Prathiba Date: Thu, 29 Dec 2022 22:25:36 +0100 Subject: [PATCH 10/79] Support Version 2.0.0 changes for /v1/redirect-topology-change-information Fixes #498 --- .../OperationClientInterface.js | 9 +- ...icalTerminationPointWithMappingServices.js | 155 +++++++++++++++++- .../basicServices/BasicServicesService.js | 13 +- .../services/PrepareForwardingAutomation.js | 20 --- 4 files changed, 164 insertions(+), 33 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js index 21d34ee4..dc57f503 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js @@ -321,13 +321,10 @@ class OperationClientInterface extends layerProtocol { let operationClientUuid = undefined; try { let appUuid = await controlConstruct.getUuidAsync(); - let releaseNumber = await httpClientInterface.getReleaseNumberAsync(httpClientUuid); - let applicationName = await httpClientInterface.getApplicationNameAsync(httpClientUuid); - let releaseNumberUuidFormat = releaseNumber.replace(/\./g, "-"); - - let applicationNameUuidFormat = applicationName.replace(/[a-z]/g, "").toLowerCase(); + let applicationNameUuidFormat = httpClientUuid.split("-")[6]; + let releaseNumberUuidFormat = httpClientUuid.split("-")[7] + "-" + httpClientUuid.split("-")[8] + "-" + httpClientUuid.split("-")[9]; operationClientUuid = appUuid + "-op-c-" + apiSegment + "-" + - applicationNameUuidFormat + "-" + releaseNumberUuidFormat + "-" + sequence; + applicationNameUuidFormat + "-" + releaseNumberUuidFormat + "-" + sequence; resolve(operationClientUuid); } catch (error) { reject(error); diff --git a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js index 64bfb576..c52531ec 100644 --- a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js +++ b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js @@ -65,7 +65,7 @@ exports.findAndUpdateApplicationInformationAsync = function (logicalTerminationP applicationName ); if (isApplicationExists) { - logicalTerminationPointConfigurationStatus = await updateLogicalTerminationPointInstanceGroupAsync( + logicalTerminationPointConfigurationStatus = await findAndUpdateLogicalTerminationPointInstanceGroupAsync( logicalTerminationPointConfigurationInput ); } @@ -289,6 +289,60 @@ function updateLogicalTerminationPointInstanceGroupAsync(logicalTerminationPoint } +/** + * @description This function configures the existing logical-termination-point to the latest values. + * Also incase if the tcp,operation client are not available it will be created. + * @param {String} logicalTerminationPointConfigurationInput : is an instance of + * logicalTerminationPoint/ConfigurationInput class + * @return {Promise} object {LogicalTerminationPointConfigurationStatus} + **/ +function findAndUpdateLogicalTerminationPointInstanceGroupAsync(logicalTerminationPointConfigurationInput) { + return new Promise(async function (resolve, reject) { + + let logicalTerminationPointConfigurationStatus; + let httpClientConfigurationStatus; + let tcpClientConfigurationStatusList = []; + let operationClientConfigurationStatusList = []; + + let applicationName = logicalTerminationPointConfigurationInput.applicationName; + let releaseNumber = logicalTerminationPointConfigurationInput.releaseNumber; + let tcpList = logicalTerminationPointConfigurationInput.tcpList; + let operationServerName = logicalTerminationPointConfigurationInput.operationServerName; + let operationNamesByAttributes = logicalTerminationPointConfigurationInput.operationNamesByAttributes; + let operationsMapping = logicalTerminationPointConfigurationInput.operationsMapping; + + try { + let httpClientUuid = await httpClientInterface.getHttpClientUuidAsync( + applicationName + ); + tcpClientConfigurationStatusList = await findAndUpdateTcpClientInterface( + httpClientUuid, + tcpList + ); + operationClientConfigurationStatusList = await findAndUpdateOperationClientInterface( + httpClientUuid, + operationServerName, + operationNamesByAttributes, + operationsMapping + ); + httpClientConfigurationStatus = await updateHttpClientInterface( + httpClientUuid, + releaseNumber, + ) + logicalTerminationPointConfigurationStatus = new LogicalTerminationPointConfigurationStatus( + operationClientConfigurationStatusList, + httpClientConfigurationStatus, + tcpClientConfigurationStatusList + ); + + resolve(logicalTerminationPointConfigurationStatus); + } catch (error) { + reject(error); + } + }); +} + + /** * @description This function creates a http client interface. * @param {String} applicationName name of the client application @@ -415,6 +469,52 @@ function createOrUpdateTcpClientInterface(httpClientUuid, tcpList) { } }); } + +/** + * @description This function creates or updates a tcp client interface. + * @param {String} httpClientUuid :uuid of the http-client, the value should be a valid string + * in the pattern '-\d+-\d+-\d+-http-c-\d+$' + * @param {String} remoteIpV4Address where the application is installed + * @param {String} remotePort where the application is running + * @return {Promise} object {configurationStatus} + **/ +function findAndUpdateTcpClientInterface(httpClientUuid, tcpList) { + return new Promise(async function (resolve, reject) { + let configurationStatusList = []; + try { + // for find and update , there will be only a single instance avilable in the tcpList + let tcpInfo = tcpList[0]; + let remoteProtocol = tcpInfo.protocol; + let remotePort = tcpInfo.port; + let remoteIpV4Address = tcpInfo.address; + let serverLtpList = await logicalTerminationPoint.getServerLtpListAsync(httpClientUuid); + if (serverLtpList != undefined && serverLtpList.length <= 0) { + let configurationStatus = await createTcpClientInterface( + httpClientUuid, + remoteIpV4Address, + remotePort, + remoteProtocol + ); + configurationStatusList.push(configurationStatus); + } else { + let tcpClientUuid = serverLtpList[0]; + let configurationStatus = await updateTcpClientInterface( + tcpClientUuid, + remoteIpV4Address, + remotePort, + remoteProtocol + ); + configurationStatusList.push(configurationStatus); + + } + resolve(configurationStatusList); + } catch (error) { + reject(error); + } + }); +} + + /** * @description This function creates a tcp client interface. * @param {String} httpClientUuid :uuid of the http-client, the value should be a valid string @@ -585,6 +685,7 @@ function updateOperationClientInterface(operationClientUuid, operationName) { } }); } + /** * @description This function creates or updates a operation client interfaces for the provided input operation name list. * @param {String} httpClientUuid : uuid of the http-client, the value should be a valid string @@ -634,4 +735,56 @@ function createOrUpdateOperationClientInterface(httpClientUuid, operationServerN reject(error); } }); +} + + +/** + * @description This function creates or updates a operation client interfaces for the provided input operation name list. + * @param {String} httpClientUuid : uuid of the http-client, the value should be a valid string + * in the pattern '-\d+-\d+-\d+-http-c-\d+$' + * @param {String} operationServerName : caller operation + * @param {Map} operationNamesByAttributes : map of the client operation attributes (key) with client operation names (value) + * @param {Object} operationsMapping : map of hardcoded context values for operations + * @return {Promise} object {configurationStatusList} + **/ +function findAndUpdateOperationClientInterface(httpClientUuid, operationServerName, operationNamesByAttributes, operationsMapping) { + return new Promise(async function (resolve, reject) { + let configurationStatusList = []; + try { + for (let operationItem of operationNamesByAttributes) { + let configurationStatus; + let operationClientNewName = operationItem[1]; + let operationAttribute = operationItem[0]; + let value = operationsMapping[operationServerName][operationAttribute]; + let operationClientUuid = await operationClientInterface.generateOperationClientUuidAsync( + httpClientUuid, + value["api-segment"], + value["sequence"] + ); + let operationClientOldName = await operationClientInterface.getOperationNameAsync(operationClientUuid); + if (operationClientOldName === undefined) { + configurationStatus = await createOperationClientInterface( + httpClientUuid, + operationClientNewName, + operationClientUuid + ); + } else if (operationClientOldName !== operationClientNewName) { + configurationStatus = await updateOperationClientInterface( + operationClientUuid, + operationClientNewName + ); + } else { + configurationStatus = new ConfigurationStatus( + operationClientUuid, + '', + false + ); + } + configurationStatusList.push(configurationStatus); + } + resolve(configurationStatusList); + } catch (error) { + reject(error); + } + }); } \ No newline at end of file diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 6ae6d7a3..bdd711c3 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -785,9 +785,9 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC ****************************************************************************************/ let applicationName = body["topology-application"]; let releaseNumber = body["topology-application-release-number"]; - let applicationAddress = body["topology-application-address"]['ip-address']['ipv-4-address'] + let applicationAddress = body["topology-application-address"]; let applicationPort = body["topology-application-port"]; - let applicationUpdateTopologyOperation = body["topology-operation-application-update"]; + let applicationProtocol = body["topology-application-protocol"]; let ltpUpdateTopologyOperation = body["topology-operation-ltp-update"]; let ltpDeletionTopologyOperation = body["topology-operation-ltp-deletion"]; let fcUpdateTopologyOperation = body["topology-operation-fc-update"]; @@ -805,18 +805,20 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC * configure logical-termination-point ****************************************************************************************/ let operationNamesByAttributes = new Map(); - operationNamesByAttributes.set("topology-operation-application-update", applicationUpdateTopologyOperation); operationNamesByAttributes.set("topology-operation-ltp-update", ltpUpdateTopologyOperation); operationNamesByAttributes.set("topology-operation-ltp-deletion", ltpDeletionTopologyOperation); operationNamesByAttributes.set("topology-operation-fc-update", fcUpdateTopologyOperation); operationNamesByAttributes.set("topology-operation-fc-port-update", fcPortUpdateTopologyOperation); operationNamesByAttributes.set("topology-operation-fc-port-deletion", fcPortDeletionTopologyOperation); + let tcpObjectList = []; + let tcpObject = formulateTcpObject(applicationProtocol, applicationAddress, applicationPort); + tcpObjectList.push(tcpObject); + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( applicationName, releaseNumber, - applicationAddress, - applicationPort, + tcpObjectList, operationServerName, operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping @@ -837,7 +839,6 @@ exports.redirectTopologyChangeInformation = function (body, user, originator, xC if (operationClientConfigurationStatusList) { forwardingConfigurationInputList = await prepareForwardingConfiguration.redirectTopologyChangeInformation( operationClientConfigurationStatusList, - applicationUpdateTopologyOperation, ltpUpdateTopologyOperation, ltpDeletionTopologyOperation, fcUpdateTopologyOperation, diff --git a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js index f98579ab..8136a521 100644 --- a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js @@ -253,26 +253,6 @@ exports.redirectTopologyChangeInformation = function (logicalTerminationPointcon return new Promise(async function (resolve, reject) { let forwardingConstructAutomationList = []; try { - /*********************************************************************************** - * PromptForRedirectingTopologyInformationCausesSendingAnInitialStateToALT - * /v1/update-all-ltps-and-fcs - ************************************************************************************/ - let updateAllLtpsAndFcsForwardingName = "PromptForRedirectingTopologyInformationCausesSendingAnInitialStateToALT"; - let updateAllLtpsAndFcsContext; - let updateAllLtpsAndFcsRequestBody = {}; - let controlConstructUrl = onfPaths.CONTROL_CONSTRUCT; - let controlConstruct = await fileOperation.readFromDatabaseAsync(controlConstructUrl); - controlConstruct = removeAttribute( - controlConstruct, - "operation-key"); - updateAllLtpsAndFcsRequestBody["core-model-1-4:control-construct"] = controlConstruct; - let forwardingAutomation = new forwardingConstructAutomationInput( - updateAllLtpsAndFcsForwardingName, - updateAllLtpsAndFcsRequestBody, - updateAllLtpsAndFcsContext - ); - forwardingConstructAutomationList.push(forwardingAutomation); - /*********************************************************************************** * forwardings for application layer topology ************************************************************************************/ From c7776066394b7d9fbd3d9e51f42176a5e0020704 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Thu, 29 Dec 2022 22:30:51 +0100 Subject: [PATCH 11/79] Support Version 2.0.0 changes for /v1/inquire-oam-request-approvals Fixes #497 --- .../basicServices/basicServices/BasicServicesService.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index bdd711c3..7a01dd7a 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -429,6 +429,7 @@ exports.inquireOamRequestApprovals = function (body, user, originator, xCorrelat ****************************************************************************************/ let applicationName = body["oam-approval-application"]; let releaseNumber = body["oam-approval-application-release-number"]; + let applicationProtocol = body["oam-approval-protocol"]; let applicationAddress = body["oam-approval-address"]; let applicationPort = body["oam-approval-port"]; let oamApprovalOperation = body["oam-approval-operation"]; @@ -446,11 +447,14 @@ exports.inquireOamRequestApprovals = function (body, user, originator, xCorrelat let operationNamesByAttributes = new Map(); operationNamesByAttributes.set("oam-approval-operation", oamApprovalOperation); + let tcpObjectList = []; + let tcpObject = formulateTcpObject(applicationProtocol, applicationAddress, applicationPort); + tcpObjectList.push(tcpObject); + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( applicationName, releaseNumber, - applicationAddress, - applicationPort, + tcpObjectList, operationServerName, operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping From a5f608c0e50bd8e60b057485f52571b457b48df9 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Thu, 29 Dec 2022 22:32:56 +0100 Subject: [PATCH 12/79] Support Version 2.0.0 changes for /v1/redirect-oam-request-information Fixes #496 --- .../basicServices/basicServices/BasicServicesService.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 7a01dd7a..9f5e911c 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -597,6 +597,7 @@ exports.redirectOamRequestInformation = function (body, user, originator, xCorre ****************************************************************************************/ let applicationName = body["oam-log-application"]; let releaseNumber = body["oam-log-application-release-number"]; + let applicationProtocol = body["oam-log-protocol"]; let applicationAddress = body["oam-log-address"]; let applicationPort = body["oam-log-port"]; let oamLogOperation = body["oam-log-operation"]; @@ -614,11 +615,14 @@ exports.redirectOamRequestInformation = function (body, user, originator, xCorre let operationNamesByAttributes = new Map(); operationNamesByAttributes.set("oam-log-operation", oamLogOperation); + let tcpObjectList = []; + let tcpObject = formulateTcpObject(applicationProtocol, applicationAddress, applicationPort); + tcpObjectList.push(tcpObject); + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( applicationName, releaseNumber, - applicationAddress, - applicationPort, + tcpObjectList, operationServerName, operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping From 2df46bb4b89de65ffaed07b623286abdfded3e78 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Thu, 29 Dec 2022 22:34:32 +0100 Subject: [PATCH 13/79] Support Version 2.0.0 changes for /v1/redirect-service-request-information Fixes #495 --- .../basicServices/basicServices/BasicServicesService.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 9f5e911c..92c62047 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -697,6 +697,7 @@ exports.redirectServiceRequestInformation = function (body, user, originator, xC ****************************************************************************************/ let applicationName = body["service-log-application"]; let releaseNumber = body["service-log-application-release-number"]; + let applicationProtocol = body["service-log-protocol"]; let applicationAddress = body["service-log-address"]; let applicationPort = body["service-log-port"]; let serviceLogOperation = body["service-log-operation"]; @@ -714,11 +715,14 @@ exports.redirectServiceRequestInformation = function (body, user, originator, xC let operationNamesByAttributes = new Map(); operationNamesByAttributes.set("service-log-operation", serviceLogOperation); + let tcpObjectList = []; + let tcpObject = formulateTcpObject(applicationProtocol, applicationAddress, applicationPort); + tcpObjectList.push(tcpObject); + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( applicationName, releaseNumber, - applicationAddress, - applicationPort, + tcpObjectList, operationServerName, operationNamesByAttributes, basicServicesOperationsMapping.basicServicesOperationsMapping From 5fa8ef07d483b722845b61512bd498ca2541a5cc Mon Sep 17 00:00:00 2001 From: Prathiba Date: Fri, 30 Dec 2022 07:10:59 +0100 Subject: [PATCH 14/79] Support Version 2.0.0 changes for /v1/update-operation-key Fixes #503 --- .../basicServices/BasicServicesService.js | 21 ++------------- .../services/PrepareForwardingAutomation.js | 27 ------------------- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 92c62047..3e2bf2b2 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -1314,7 +1314,6 @@ exports.updateOperationKey = function (body, user, originator, xCorrelator, trac * get request body ****************************************************************************************/ let operationUuid = body["operation-uuid"]; - let oldOperationKey = body["old-operation-key"]; let newOperationKey = body["new-operation-key"]; /**************************************************************************************** @@ -1322,34 +1321,18 @@ exports.updateOperationKey = function (body, user, originator, xCorrelator, trac ****************************************************************************************/ let isUpdated; if (operationServerInterface.isOperationServer(operationUuid)) { - if (oldOperationKey == await operationServerInterface.getOperationKeyAsync(operationUuid)) { + if (newOperationKey != await operationServerInterface.getOperationKeyAsync(operationUuid)) { isUpdated = await operationServerInterface.setOperationKeyAsync(operationUuid, newOperationKey); } } else if (operationClientInterface.isOperationClient(operationUuid)) { - if (oldOperationKey == await operationClientInterface.getOperationKeyAsync(operationUuid)) { + if (newOperationKey != await operationClientInterface.getOperationKeyAsync(operationUuid)) { isUpdated = await operationClientInterface.setOperationKeyAsync(operationUuid, newOperationKey); } } - let configurationStatus = new ConfigurationStatus(operationUuid, undefined, isUpdated); - let logicalTerminationPointConfigurationStatus = new LogicalTerminationPointConfigurationStatus( - [configurationStatus] - ); /**************************************************************************************** * Prepare attributes to automate forwarding-construct ****************************************************************************************/ - let forwardingAutomationInputList = await prepareForwardingAutomation.updateOperationKey( - logicalTerminationPointConfigurationStatus, - undefined - ); - ForwardingAutomationService.automateForwardingConstructAsync( - operationServerName, - forwardingAutomationInputList, - user, - xCorrelator, - traceIndicator, - customerJourney - ); resolve(); diff --git a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js index 8136a521..046b1993 100644 --- a/server/basicServices/basicServices/services/PrepareForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareForwardingAutomation.js @@ -275,33 +275,6 @@ exports.redirectTopologyChangeInformation = function (logicalTerminationPointcon }); } -exports.updateOperationKey = function (logicalTerminationPointconfigurationStatus, forwardingConstructConfigurationStatus) { - return new Promise(async function (resolve, reject) { - let forwardingConstructAutomationList = []; - try { - - /*********************************************************************************** - * forwardings for application layer topology - ************************************************************************************/ - let applicationLayerTopologyForwardingInputList = await prepareALTForwardingAutomation.getALTForwardingAutomationInputAsync( - logicalTerminationPointconfigurationStatus, - forwardingConstructConfigurationStatus - ); - - if (applicationLayerTopologyForwardingInputList) { - for (let i = 0; i < applicationLayerTopologyForwardingInputList.length; i++) { - let applicationLayerTopologyForwardingInput = applicationLayerTopologyForwardingInputList[i]; - forwardingConstructAutomationList.push(applicationLayerTopologyForwardingInput); - } - } - - resolve(forwardingConstructAutomationList); - } catch (error) { - reject(error); - } - }); -} - exports.updateOperationClient = function (logicalTerminationPointconfigurationStatus, forwardingConstructConfigurationStatus) { return new Promise(async function (resolve, reject) { let forwardingConstructAutomationList = []; From 6d08ce4fc85140aa48d9c98f3f84800c3b06caed Mon Sep 17 00:00:00 2001 From: Prathiba Date: Fri, 30 Dec 2022 11:50:44 +0100 Subject: [PATCH 15/79] Support Version 2.0.0 changes for /v1/update-operation-client Fixes #506 --- .../basicServices/BasicServicesService.js | 43 +++++++++-------- .../PrepareALTForwardingAutomation.js | 48 ++++++++++--------- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 3e2bf2b2..e82af461 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -1242,7 +1242,7 @@ exports.updateOperationClient = function (body, user, originator, xCorrelator, t * get request body ****************************************************************************************/ let applicationName = body["application-name"]; - let applicationReleaseNumber = body["application-release-number"]; + let releaseNumber = body["release-number"]; let oldOperationName = body["old-operation-name"]; let newOperationName = body["new-operation-name"]; @@ -1251,7 +1251,7 @@ exports.updateOperationClient = function (body, user, originator, xCorrelator, t ****************************************************************************************/ let isUpdated; let operationClientUuid - let httpClientUuid = await httpClientInterface.getHttpClientUuidAsync(applicationName, applicationReleaseNumber); + let httpClientUuid = await httpClientInterface.getHttpClientUuidAsync(applicationName, releaseNumber); if (httpClientUuid) { operationClientUuid = await operationClientInterface.getOperationClientUuidAsync(httpClientUuid, oldOperationName); if (operationClientUuid) { @@ -1261,26 +1261,27 @@ exports.updateOperationClient = function (body, user, originator, xCorrelator, t } } - let configurationStatus = new ConfigurationStatus(operationClientUuid, undefined, isUpdated); - - let logicalTerminationPointConfigurationStatus = new LogicalTerminationPointConfigurationStatus( - [configurationStatus] - ); - /**************************************************************************************** - * Prepare attributes to automate forwarding-construct - ****************************************************************************************/ - let forwardingAutomationInputList = await prepareForwardingAutomation.updateOperationClient( - logicalTerminationPointConfigurationStatus - ); - ForwardingAutomationService.automateForwardingConstructAsync( - operationServerName, - forwardingAutomationInputList, - user, - xCorrelator, - traceIndicator, - customerJourney - ); + if (isUpdated) { + let configurationStatus = new ConfigurationStatus(operationClientUuid, undefined, isUpdated); + let logicalTerminationPointConfigurationStatus = new LogicalTerminationPointConfigurationStatus( + [configurationStatus] + ); + /**************************************************************************************** + * Prepare attributes to automate forwarding-construct + ****************************************************************************************/ + let forwardingAutomationInputList = await prepareForwardingAutomation.updateOperationClient( + logicalTerminationPointConfigurationStatus + ); + ForwardingAutomationService.automateForwardingConstructAsync( + operationServerName, + forwardingAutomationInputList, + user, + xCorrelator, + traceIndicator, + customerJourney + ); + } resolve(); } catch (error) { diff --git a/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js index b1a6626a..c0e68e0a 100644 --- a/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js @@ -46,10 +46,10 @@ exports.getALTUnConfigureForwardingAutomationInputAsync = function (logicalTermi let forwardingConstructAutomationList = []; try { - /*********************************************************************************** + /*********************************************************************************** * logical-termination-point related forwarding automation ************************************************************************************/ - let ltpforwardingConstructAutomationInputList = await getLTPUnconfigureForwardingAutomationInputListAsync( + let ltpforwardingConstructAutomationInputList = await getLTPUnconfigureForwardingAutomationInputListAsync( logicalTerminationPointconfigurationStatus ); if (ltpforwardingConstructAutomationInputList) { @@ -104,7 +104,7 @@ function getLTPForwardingAutomationInputListAsync(logicalTerminationPointconfigu let tcpClientForwardingAutomation = tcpClientForwardingAutomationList[i]; forwardingConstructAutomationList.push(tcpClientForwardingAutomation); } - } + } for (let i = 0; i < operationClientForwardingAutomationList.length; i++) { let operationClientForwardingAutomation = operationClientForwardingAutomationList[i]; @@ -140,13 +140,13 @@ function getLTPUnconfigureForwardingAutomationInputListAsync(logicalTerminationP if (httpClientForwardingAutomation) { forwardingConstructAutomationList.push(httpClientForwardingAutomation); } - + if (tcpClientForwardingAutomationList) { for (let i = 0; i < tcpClientForwardingAutomationList.length; i++) { let tcpClientForwardingAutomation = tcpClientForwardingAutomationList[i]; forwardingConstructAutomationList.push(tcpClientForwardingAutomation); } - } + } for (let i = 0; i < operationClientForwardingAutomationList.length; i++) { let operationClientForwardingAutomation = operationClientForwardingAutomationList[i]; @@ -277,7 +277,7 @@ function getUnconfigurableHttpClientForwardingAutomationInputAsync(httpClientCon let httpClientUuid = httpClientConfigurationStatus.uuid; serviceRequestCausesLtpDeletionRequestRequestBody.uuid = httpClientUuid; serviceRequestCausesLtpDeletionRequestRequestBody = onfFormatter - .modifyJsonObjectKeysToKebabCase(serviceRequestCausesLtpDeletionRequestRequestBody) + .modifyJsonObjectKeysToKebabCase(serviceRequestCausesLtpDeletionRequestRequestBody) forwardingAutomation = new forwardingConstructAutomationInput( serviceRequestCausesLtpDeletionRequestForwardingName, serviceRequestCausesLtpDeletionRequestRequestBody, @@ -299,22 +299,24 @@ function getTcpClientForwardingAutomationInputAsync(tcpClientConfigurationStatus let serviceRequestCausesLtpUpdateRequestForwardingName = "ServiceRequestCausesLtpUpdateRequest"; let serviceRequestCausesLtpUpdateRequestContext; let serviceRequestCausesLtpUpdateRequestRequestBody; - for(let i=0;i Date: Fri, 30 Dec 2022 12:48:38 +0100 Subject: [PATCH 16/79] GenericRepresentation consequentActionList to formulate "request" with the tcp-client with "HTTP" information Fixes #505 --- .../basicServices/GenericRepresentation.js | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/server/basicServices/basicServices/GenericRepresentation.js b/server/basicServices/basicServices/GenericRepresentation.js index 21ca6ac8..dc3b4c94 100644 --- a/server/basicServices/basicServices/GenericRepresentation.js +++ b/server/basicServices/basicServices/GenericRepresentation.js @@ -12,6 +12,7 @@ const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriv const onfAttributes = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfAttributes'); const profileCollection = require('onf-core-model-ap/applicationPattern/onfModel/models/ProfileCollection'); const profile = require('onf-core-model-ap/applicationPattern/onfModel/models/Profile'); +const TcpServerInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface'); /** * @description This function returns the consequent action list for the provided operation name. @@ -53,12 +54,18 @@ exports.getConsequentActionList = function (operationName) { * @description This function returns the formulated request for the provided operation name. * @param {String} operationName : operation Name * @returns {promise} String {request} - * TODO : enhance the method to formulate the request after decision is made. **/ function formulateRequest(operationName) { return new Promise(async function (resolve, reject) { try { - let request = operationName; + let protocol = "http"; + let address = await TcpServerInterface.getLocalAddressOfTheProtocol(protocol); + let port = await TcpServerInterface.getLocalPortOfTheProtocol(protocol); + let ipaddressAndPort = await getConfiguredAddress(address) + ":" + port; + if (operationName.indexOf("/") != 0) { + operationName = "/" + operationName + } + let request = protocol + "://" + ipaddressAndPort + operationName; resolve(request); } catch (error) { reject(error); @@ -67,6 +74,32 @@ function formulateRequest(operationName) { } +/** + * @description This function returns the address configured . + * @param {String} address : address of the tcp server . + * @returns {promise} string {address} + **/ +function getConfiguredAddress(address) { + return new Promise(async function (resolve, reject) { + try { + let domainName = onfAttributes.TCP_SERVER.DOMAIN_NAME; + if (domainName in address) { + address = address["domain-name"]; + } else { + address = address[ + onfAttributes.TCP_SERVER.IP_ADDRESS][ + onfAttributes.TCP_SERVER.IPV_4_ADDRESS + ]; + } + resolve(address); + } catch (error) { + reject(error); + } + }); + +} + + /** * @description This function returns the response value list for the provided operation name. * @param {String} operationName : operation Name @@ -95,7 +128,7 @@ exports.getResponseValueList = function (operationName) { let fieldName = ResponseProfileCapability[onfAttributes.RESPONSE_PROFILE.FIELD_NAME]; let value = ResponseProfileConfiguration[onfAttributes.RESPONSE_PROFILE.VALUE]; let fieldNameReference = fieldName[onfAttributes.RESPONSE_PROFILE.FIELD_NAME_REFERENCE]; - let valueReference = value[onfAttributes.RESPONSE_PROFILE.VALUE_REFERENCE]; + let valueReference = value[onfAttributes.RESPONSE_PROFILE.VALUE_REFERENCE]; if (fieldNameReference !== undefined) { responseInstanceFieldName = await fileOperation.readFromDatabaseAsync(fieldNameReference); } else { From 852d66afebadf92265a4697ca99d23b39e100990 Mon Sep 17 00:00:00 2001 From: Vanitha Valluripalli Date: Fri, 30 Dec 2022 13:49:25 +0100 Subject: [PATCH 17/79] Made modifications to fetch information from tcp server instance --- .../basicServices/GenericRepresentation.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/server/basicServices/basicServices/GenericRepresentation.js b/server/basicServices/basicServices/GenericRepresentation.js index dc3b4c94..c58c466f 100644 --- a/server/basicServices/basicServices/GenericRepresentation.js +++ b/server/basicServices/basicServices/GenericRepresentation.js @@ -10,6 +10,7 @@ const ActionProfile = require('onf-core-model-ap/applicationPattern/onfModel/mod const responseProfile = require('onf-core-model-ap/applicationPattern/onfModel/models/profile/responseProfile'); const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriver/JSONDriver'); const onfAttributes = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfAttributes'); +const onfPaths = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfPaths'); const profileCollection = require('onf-core-model-ap/applicationPattern/onfModel/models/ProfileCollection'); const profile = require('onf-core-model-ap/applicationPattern/onfModel/models/Profile'); const TcpServerInterface = require('onf-core-model-ap/applicationPattern/onfModel/models/layerProtocols/TcpServerInterface'); @@ -58,14 +59,19 @@ exports.getConsequentActionList = function (operationName) { function formulateRequest(operationName) { return new Promise(async function (resolve, reject) { try { - let protocol = "http"; - let address = await TcpServerInterface.getLocalAddressOfTheProtocol(protocol); - let port = await TcpServerInterface.getLocalPortOfTheProtocol(protocol); - let ipaddressAndPort = await getConfiguredAddress(address) + ":" + port; - if (operationName.indexOf("/") != 0) { - operationName = "/" + operationName + let protocol = "HTTP"; + let tcpServerUuid = await TcpServerInterface.getUuidOfTheProtocol(protocol); + let tcpServerConfiguration = await fileOperation.readFromDatabaseAsync( + onfPaths.TCP_SERVER_INTERFACE_CONFIGURATION.replace( + "{uuid}", tcpServerUuid) + ); + let address = await getConfiguredAddress(tcpServerConfiguration["local-address"]); + let port = tcpServerConfiguration["local-port"]; + let ipaddressAndPort = address + ":" + port; + if(operationName.indexOf("/") != 0) { + operationName = "/"+ operationName } - let request = protocol + "://" + ipaddressAndPort + operationName; + let request = (protocol.toLowerCase()) + "://" + ipaddressAndPort + operationName; resolve(request); } catch (error) { reject(error); @@ -87,7 +93,6 @@ function getConfiguredAddress(address) { address = address["domain-name"]; } else { address = address[ - onfAttributes.TCP_SERVER.IP_ADDRESS][ onfAttributes.TCP_SERVER.IPV_4_ADDRESS ]; } @@ -128,7 +133,7 @@ exports.getResponseValueList = function (operationName) { let fieldName = ResponseProfileCapability[onfAttributes.RESPONSE_PROFILE.FIELD_NAME]; let value = ResponseProfileConfiguration[onfAttributes.RESPONSE_PROFILE.VALUE]; let fieldNameReference = fieldName[onfAttributes.RESPONSE_PROFILE.FIELD_NAME_REFERENCE]; - let valueReference = value[onfAttributes.RESPONSE_PROFILE.VALUE_REFERENCE]; + let valueReference = value[onfAttributes.RESPONSE_PROFILE.VALUE_REFERENCE]; if (fieldNameReference !== undefined) { responseInstanceFieldName = await fileOperation.readFromDatabaseAsync(fieldNameReference); } else { From 195f7ccadeacbb1f9d849036e396e966612b67f5 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Fri, 30 Dec 2022 16:45:19 +0100 Subject: [PATCH 18/79] /v1/update-client should transfer the operation-clients from current-release to future-release Fixes #509 --- ...icalTerminationPointWithMappingServices.js | 34 ++++++++ .../basicServices/BasicServicesService.js | 80 ++++++++++++------- 2 files changed, 85 insertions(+), 29 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js index c52531ec..db83a252 100644 --- a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js +++ b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js @@ -17,6 +17,40 @@ const LogicalTerminationPointConfigurationStatus = require('./models/logicalTerm const ConfigurationStatus = require('./models/ConfigurationStatus'); const TcpClientInterface = require('../models/layerProtocols/TcpClientInterface'); +/** + * @description This function find a application in the same or different release and updates the http, + * operation and tcp client if require. + * @param {String} logicalTerminationPointConfigurationInput : is an instance of + * logicalTerminationPoint/ConfigurationInput class + * + * @return {Promise} object {logicalTerminationPoint/ConfigurationStatus} + **/ +exports.createOrUpdateApplicationAndReleaseInformationAsync = function (logicalTerminationPointConfigurationInput) { + return new Promise(async function (resolve, reject) { + let logicalTerminationPointConfigurationStatus; + try { + let applicationName = logicalTerminationPointConfigurationInput.applicationName; + let releaseNumber = logicalTerminationPointConfigurationInput.releaseNumber; + let isApplicationExists = await httpClientInterface.isApplicationExists( + applicationName, + releaseNumber + ); + if (!isApplicationExists) { + logicalTerminationPointConfigurationStatus = await createLogicalTerminationPointInstanceGroupAsync( + logicalTerminationPointConfigurationInput + ); + } else { + logicalTerminationPointConfigurationStatus = await updateLogicalTerminationPointInstanceGroupAsync( + logicalTerminationPointConfigurationInput + ); + } + resolve(logicalTerminationPointConfigurationStatus) + } catch (error) { + reject(error); + } + }); +} + /** * @description This function find a application in the same or different release and updates the http, * operation and tcp client if require. diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index e82af461..3d0d56cb 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -1157,40 +1157,62 @@ exports.updateClient = function (body, user, originator, xCorrelator, traceIndic /**************************************************************************************** * get request body ****************************************************************************************/ - let applicationName = body["application-name"]; - let oldApplicationReleaseNumber = body["old-application-release-number"]; - let newApplicationReleaseNumber = body["new-application-release-number"]; - let newApplicationAddress = body["new-application-address"]; - let newApplicationPort = body["new-application-port"]; + let currentApplicationName = body["current-application-name"]; + let currentReleaseNumber = body["current-release-number"]; + let futureApplicationName = body["future-application-name"]; + let futureReleaseNumber = body["future-release-number"]; + let futureProtocol = body["future-protocol"]; + let futureAddress = body["future-address"]; + let futurePort = body["future-port"]; /**************************************************************************************** - * perform bussiness logic + * Prepare logicalTerminationPointConfigurationInput object to + * configure logical-termination-point ****************************************************************************************/ - let logicalTerminationPointConfigurationStatus; - let isOldApplicationExists = false; + let operationNamesByAttributes = new Map(); - let httpClientUuid = await httpClientInterface.getHttpClientUuidAsync(applicationName, oldApplicationReleaseNumber); - if (httpClientUuid) { - isOldApplicationExists = true; - } + let tcpObjectList = []; + let tcpObject = formulateTcpObject(futureProtocol, futureAddress, futurePort); + tcpObjectList.push(tcpObject); - if (isOldApplicationExists) { - /**************************************************************************************** - * Prepare logicalTerminationPointConfigurationInput object to - * configure logical-termination-point - ****************************************************************************************/ + let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( + futureApplicationName, + futureReleaseNumber, + tcpObjectList, + operationServerName, + operationNamesByAttributes, + basicServicesOperationsMapping.basicServicesOperationsMapping + ); + let logicalTerminationPointConfigurationStatus = await LogicalTerminationPointService.createOrUpdateApplicationAndReleaseInformationAsync( + logicalTerminationPointConfigurationInput + ); - let operationNamesByAttributes = []; - let logicalTerminationPointConfigurationInput = new LogicalTerminationPointConfigurationInput( - applicationName, - newApplicationReleaseNumber, - newApplicationAddress, - newApplicationPort, - operationNamesByAttributes - ); - logicalTerminationPointConfigurationStatus = await LogicalTerminationPointService.createOrUpdateApplicationInformationAsync( - logicalTerminationPointConfigurationInput - ); + /******************************************************************************************************* + * bussiness logic to transfer the operation-client instances from current-release to future-release + *******************************************************************************************************/ + + let httpClientUuidOfOldApplication = await httpClientInterface.getHttpClientUuidAsync(currentApplicationName, currentReleaseNumber); + if (httpClientUuidOfOldApplication) { + let clientLtpsOfOldApplication = await LogicalTerminationPoint.getClientLtpListAsync(httpClientUuidOfOldApplication); + if (clientLtpsOfOldApplication != undefined && clientLtpsOfOldApplication.length > 0) { + await LogicalTerminationPoint.setClientLtpListAsync( + httpClientUuidOfOldApplication, + [] + ); + let httpClientUuidOfnewApplication = await httpClientInterface.getHttpClientUuidAsync(futureApplicationName, futureReleaseNumber); + if (httpClientUuidOfnewApplication) { + let existingLtpsOfNewRelease = await LogicalTerminationPoint.getClientLtpListAsync(httpClientUuidOfnewApplication); + + for (let i = 0; i < clientLtpsOfOldApplication.length; i++) { + let operationClientLtpOfOldApplication = clientLtpsOfOldApplication[i]; + existingLtpsOfNewRelease.push(operationClientLtpOfOldApplication); + } + await LogicalTerminationPoint.setClientLtpListAsync( + httpClientUuidOfnewApplication, + existingLtpsOfNewRelease + ); + } + } } /**************************************************************************************** @@ -1198,7 +1220,7 @@ exports.updateClient = function (body, user, originator, xCorrelator, traceIndic ****************************************************************************************/ let forwardingAutomationInputList = await prepareForwardingAutomation.updateClient( logicalTerminationPointConfigurationStatus, undefined, - applicationName + futureApplicationName ); ForwardingAutomationService.automateForwardingConstructAsync( operationServerName, From 5cdd92ae044366039ae2e5a803140d7f72f7ba21 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Mon, 2 Jan 2023 12:46:04 +0100 Subject: [PATCH 19/79] Resolve the problem in method findAndUpdateLogicalTerminationPoint to considers both release-number and application-name Fixes #511 --- ...icalTerminationPointWithMappingServices.js | 57 ++++++++++++++++++- server/applicationPattern/package.json | 2 +- server/basicServices/package.json | 4 +- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js index db83a252..45b1eaf1 100644 --- a/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js +++ b/server/applicationPattern/applicationPattern/onfModel/services/LogicalTerminationPointWithMappingServices.js @@ -40,7 +40,7 @@ exports.createOrUpdateApplicationAndReleaseInformationAsync = function (logicalT logicalTerminationPointConfigurationInput ); } else { - logicalTerminationPointConfigurationStatus = await updateLogicalTerminationPointInstanceGroupAsync( + logicalTerminationPointConfigurationStatus = await findAndUpdateLogicalTerminationPointApplicationAndReleaseInstanceGroupAsync( logicalTerminationPointConfigurationInput ); } @@ -58,6 +58,8 @@ exports.createOrUpdateApplicationAndReleaseInformationAsync = function (logicalT * logicalTerminationPoint/ConfigurationInput class * * @return {Promise} object {logicalTerminationPoint/ConfigurationStatus} + * !!!!!!!!!!!!!!!!!!!!!!!! Please dont delete or update this method, this is utilized by RegisterApplication service in + * RegistryOffice to support creating multiple tcp-client instances !!!!!!!!!!!!!!! **/ exports.createOrUpdateApplicationInformationAsync = function (logicalTerminationPointConfigurationInput) { return new Promise(async function (resolve, reject) { @@ -322,6 +324,59 @@ function updateLogicalTerminationPointInstanceGroupAsync(logicalTerminationPoint }); } +/** + * @description This function configures the existing logical-termination-point to the latest values. + * Also incase if the tcp,operation client are not available it will be created. + * @param {String} logicalTerminationPointConfigurationInput : is an instance of + * logicalTerminationPoint/ConfigurationInput class + * @return {Promise} object {LogicalTerminationPointConfigurationStatus} + **/ +function findAndUpdateLogicalTerminationPointApplicationAndReleaseInstanceGroupAsync(logicalTerminationPointConfigurationInput) { + return new Promise(async function (resolve, reject) { + + let logicalTerminationPointConfigurationStatus; + let httpClientConfigurationStatus; + let tcpClientConfigurationStatusList = []; + let operationClientConfigurationStatusList = []; + + let applicationName = logicalTerminationPointConfigurationInput.applicationName; + let releaseNumber = logicalTerminationPointConfigurationInput.releaseNumber; + let tcpList = logicalTerminationPointConfigurationInput.tcpList; + let operationServerName = logicalTerminationPointConfigurationInput.operationServerName; + let operationNamesByAttributes = logicalTerminationPointConfigurationInput.operationNamesByAttributes; + let operationsMapping = logicalTerminationPointConfigurationInput.operationsMapping; + + try { + let httpClientUuid = await httpClientInterface.getHttpClientUuidAsync( + applicationName,releaseNumber + ); + tcpClientConfigurationStatusList = await findAndUpdateTcpClientInterface( + httpClientUuid, + tcpList + ); + operationClientConfigurationStatusList = await findAndUpdateOperationClientInterface( + httpClientUuid, + operationServerName, + operationNamesByAttributes, + operationsMapping + ); + httpClientConfigurationStatus = await updateHttpClientInterface( + httpClientUuid, + releaseNumber, + ) + logicalTerminationPointConfigurationStatus = new LogicalTerminationPointConfigurationStatus( + operationClientConfigurationStatusList, + httpClientConfigurationStatus, + tcpClientConfigurationStatusList + ); + + resolve(logicalTerminationPointConfigurationStatus); + } catch (error) { + reject(error); + } + }); +} + /** * @description This function configures the existing logical-termination-point to the latest values. diff --git a/server/applicationPattern/package.json b/server/applicationPattern/package.json index 767a6383..ef592613 100644 --- a/server/applicationPattern/package.json +++ b/server/applicationPattern/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap", - "version": "1.0.1", + "version": "2.0.0-alpha", "description": "onf core model application pattern", "main": "index.js", "scripts": { diff --git a/server/basicServices/package.json b/server/basicServices/package.json index e517f987..fb84e070 100644 --- a/server/basicServices/package.json +++ b/server/basicServices/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap-bs", - "version": "1.0.1", + "version": "2.0.0-alpha", "description": "onf core model application pattern", "main": "index.js", "scripts": { @@ -16,7 +16,7 @@ "oas3-tools": "^2.2.3", "randexp": "^0.5.3", "response-time": "^2.3.2", - "onf-core-model-ap": "1.0.1" + "onf-core-model-ap": "2.0.0-alpha" }, "author": "Prathiba Jeevan", "license": "Apache-2.0" From 360911823f6094f7c6b090b596e2056bb4496e4b Mon Sep 17 00:00:00 2001 From: IswaryaaS Date: Mon, 2 Jan 2023 18:31:23 +0530 Subject: [PATCH 20/79] Publish npm package version 2.0.0-alpha.1 - onf-core-model-ap-bs and onf-core-model-ap Fixes #513 --- server/applicationPattern/package.json | 2 +- server/basicServices/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/applicationPattern/package.json b/server/applicationPattern/package.json index ef592613..f2b27d26 100644 --- a/server/applicationPattern/package.json +++ b/server/applicationPattern/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap", - "version": "2.0.0-alpha", + "version": "2.0.0-alpha.1", "description": "onf core model application pattern", "main": "index.js", "scripts": { diff --git a/server/basicServices/package.json b/server/basicServices/package.json index fb84e070..5a81a616 100644 --- a/server/basicServices/package.json +++ b/server/basicServices/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap-bs", - "version": "2.0.0-alpha", + "version": "2.0.0-alpha.1", "description": "onf core model application pattern", "main": "index.js", "scripts": { @@ -16,7 +16,7 @@ "oas3-tools": "^2.2.3", "randexp": "^0.5.3", "response-time": "^2.3.2", - "onf-core-model-ap": "2.0.0-alpha" + "onf-core-model-ap": "2.0.0-alpha.1" }, "author": "Prathiba Jeevan", "license": "Apache-2.0" From 422ddb586330f7348ccd5f4789c1a3c67840f38c Mon Sep 17 00:00:00 2001 From: Dana Sunalova Date: Mon, 2 Jan 2023 16:22:57 +0100 Subject: [PATCH 21/79] Fixed runtime issues with basic services. Wrong imports fixed. Signed-off-by: Dana Sunalova --- server/basicServices/basicServices/BasicServicesService.js | 2 +- server/basicServices/basicServices/GenericRepresentation.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/basicServices/basicServices/BasicServicesService.js b/server/basicServices/basicServices/BasicServicesService.js index 3d0d56cb..88f415bb 100644 --- a/server/basicServices/basicServices/BasicServicesService.js +++ b/server/basicServices/basicServices/BasicServicesService.js @@ -30,7 +30,7 @@ const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriv const controlConstruct = require('onf-core-model-ap/applicationPattern/onfModel/models/ControlConstruct'); const basicServicesOperationsMapping = require('./BasicServicesOperationsMapping'); -const genericRepresentation = require('onf-core-model-ap-bs/basicServices/GenericRepresentation'); +const genericRepresentation = require('./GenericRepresentation'); /** * Embed yourself into the MBH SDN application layer diff --git a/server/basicServices/basicServices/GenericRepresentation.js b/server/basicServices/basicServices/GenericRepresentation.js index c58c466f..4d1f5fd0 100644 --- a/server/basicServices/basicServices/GenericRepresentation.js +++ b/server/basicServices/basicServices/GenericRepresentation.js @@ -7,7 +7,7 @@ const consequentAction = require('onf-core-model-ap/applicationPattern/rest/server/responseBody/ConsequentAction'); const responseValue = require('onf-core-model-ap/applicationPattern/rest/server/responseBody/ResponseValue'); const ActionProfile = require('onf-core-model-ap/applicationPattern/onfModel/models/profile/ActionProfile'); -const responseProfile = require('onf-core-model-ap/applicationPattern/onfModel/models/profile/responseProfile'); +const responseProfile = require('onf-core-model-ap/applicationPattern/onfModel/models/profile/ResponseProfile'); const fileOperation = require('onf-core-model-ap/applicationPattern/databaseDriver/JSONDriver'); const onfAttributes = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfAttributes'); const onfPaths = require('onf-core-model-ap/applicationPattern/onfModel/constants/OnfPaths'); From 46c4f2bcb2242a1f06a0048b5180d745d9784b21 Mon Sep 17 00:00:00 2001 From: Prathiba Date: Fri, 6 Jan 2023 00:22:41 +0100 Subject: [PATCH 22/79] Include function to support static-value for the response profile Fixes #520 --- .../onfModel/constants/OnfPaths.js | 2 + .../OperationClientInterface.js | 25 +++++ .../ForwardingConstructAutomationServices.js | 83 ++++++++++++++++ ...orwardingConstructConfigurationServices.js | 23 ++++- ...icalTerminationPointWithMappingServices.js | 96 ++++++++++++++++++- .../services/ExecutionAndTraceService.js | 51 ++++++---- server/applicationPattern/package.json | 2 +- .../PrepareALTForwardingAutomation.js | 54 +++++++++++ server/basicServices/package.json | 4 +- 9 files changed, 314 insertions(+), 26 deletions(-) diff --git a/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js b/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js index 02afea7e..195aa183 100644 --- a/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js +++ b/server/applicationPattern/applicationPattern/onfModel/constants/OnfPaths.js @@ -25,6 +25,7 @@ const APPLICATION_PROFILE_APPROVAL_STATUS = APPLICATION_PROFILE_CONFIGURATION + const RESPONSE_PROFILE_PAC = PROFILE + "={profileUuid}/response-profile-1-0:response-profile-pac"; const RESPONSE_PROFILE_CONFIGURATION = RESPONSE_PROFILE_PAC + "/response-profile-configuration"; const RESPONSE_PROFILE_VALUE_REFERENCE = RESPONSE_PROFILE_CONFIGURATION + "/value/value-reference"; +const RESPONSE_PROFILE_STATIC_VALUE = RESPONSE_PROFILE_CONFIGURATION + "/value/static-value"; const ACTION_PROFILE_PAC = PROFILE + "={profileUuid}/action-profile-1-0:action-profile-pac"; const ACTION_PROFILE_CONFIGURATION = ACTION_PROFILE_PAC + "/action-profile-configuration"; @@ -96,6 +97,7 @@ module.exports = { APPLICATION_PROFILE_CONFIGURATION, APPLICATION_PROFILE_APPROVAL_STATUS, RESPONSE_PROFILE_VALUE_REFERENCE, + RESPONSE_PROFILE_STATIC_VALUE, ACTION_PROFILE_PAC, ACTION_PROFILE_CONFIGURATION, ACTION_PROFILE_CONSEQUENT_OPERATION_REFERENCE, diff --git a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js index dc57f503..931bd309 100644 --- a/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js +++ b/server/applicationPattern/applicationPattern/onfModel/models/layerProtocols/OperationClientInterface.js @@ -130,6 +130,31 @@ class OperationClientInterface extends layerProtocol { } }); } + + /** + * @description This function returns the detailedLoggingIsOn attribute of the operation client. + * @param {String} operationClientUuid : uuid of the operation client ,the value should be a valid string + * in the pattern '-\d+-\d+-\d+-op-client-\d+$' + * @returns {promise} string {detailedLoggingIsOn | undefined} + **/ + static getDetailedLoggingIsOnAsync(operationClientUuid) { + return new Promise(async function (resolve, reject) { + let detailedLoggingIsOn; + try { + let logicalTerminationPoint = await controlConstruct.getLogicalTerminationPointAsync( + operationClientUuid); + if (logicalTerminationPoint !== undefined) { + let layerProtocol = logicalTerminationPoint[onfAttributes.LOGICAL_TERMINATION_POINT.LAYER_PROTOCOL][0]; + let operationClientPac = layerProtocol[onfAttributes.LAYER_PROTOCOL.OPERATION_CLIENT_INTERFACE_PAC]; + let operationClientConfiguration = operationClientPac[onfAttributes.OPERATION_CLIENT.CONFIGURATION] + detailedLoggingIsOn = operationClientConfiguration["detailed-logging-is-on"]; + } + resolve(detailedLoggingIsOn); + } catch (error) { + reject(error); + } + }); + } /** * @description This function returns the operation key of the operation client. diff --git a/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructAutomationServices.js b/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructAutomationServices.js index cb5a2186..31bb970d 100644 --- a/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructAutomationServices.js +++ b/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructAutomationServices.js @@ -55,6 +55,42 @@ exports.automateForwardingConstructAsync = function (operationServerName, forwar }); } +/** + * @description This function automates the forwarding construct by calling the appropriate call back operations based on the fcPort input and output directions. + * @param {String} operationServerUuid operation server uuid of the request url + * @param {list} attributeList list of attributes required during forwarding construct automation(to send in the request body) + * @param {String} user user who initiates this request + * @param {string} originator originator of the request + * @param {string} xCorrelator flow id of this request + * @param {string} traceIndicator trace indicator of the request + * @param {string} customerJourney customer journey of the request + **/ +exports.automateForwardingConstructWithoutInputAsync = function (forwardingAutomationInputList, user, + xCorrelator, traceIndicator, customerJourney) { + return new Promise(async function (resolve, reject) { + try { + for (let i = 0; i < forwardingAutomationInputList.length; i++) { + let forwardingAutomationInput = forwardingAutomationInputList[i]; + let forwardingName = forwardingAutomationInput.forwardingName; + let attributeList = forwardingAutomationInput.attributeList; + let context = forwardingAutomationInput.context; + traceIndicator = i; + await automateForwardingsWithoutInputAsync(forwardingName, + attributeList, + context, + user, + xCorrelator, + traceIndicator, + customerJourney + ); + } + resolve(); + } catch (error) { + reject(error); + } + }); +} + /** * @description This function automates the forwarding construct by calling the appropriate call back operations based on the fcPort input and output directions. * @param {String} operationServerUuid operation server uuid of the request url @@ -105,6 +141,53 @@ function automateForwardingsAsync(forwardingName, attributeList, context, operat } +/** + * @description This function automates the forwarding construct by calling the appropriate call back operations based on the fcPort input and output directions. + * @param {String} operationServerUuid operation server uuid of the request url + * @param {list} attributeList list of attributes required during forwarding construct automation(to send in the request body) + * @param {String} user user who initiates this request + * @param {string} originator originator of the request + * @param {string} xCorrelator flow id of this request + * @param {string} traceIndicator trace indicator of the request + * @param {string} customerJourney customer journey of the request + **/ +function automateForwardingsWithoutInputAsync(forwardingName, attributeList, context, user, + xCorrelator, traceIndicator, customerJourney) { + return new Promise(async function (resolve, reject) { + try { + let forwardingConstruct = await ForwardingDomain.getForwardingConstructForTheForwardingNameAsync( + forwardingName); + + if (forwardingConstruct) { + let _isForwardingConstructIsProcessSnippet = isForwardingConstructIsProcessSnippet( + forwardingConstruct); + if (_isForwardingConstructIsProcessSnippet) { + automateProcessSnippetAsync(forwardingConstruct, + attributeList, + context, + user, + xCorrelator, + traceIndicator, + customerJourney + ); + } else { + automateSubscriptionsAsync(forwardingConstruct, + attributeList, + user, + xCorrelator, + traceIndicator, + customerJourney + ); + } + } + resolve(); + } catch (error) { + reject(error); + } + }); + +} + /** * @description This function automates the forwarding construct by calling the appropriate call back operations based on the fcPort input and output directions. * @param {String} operationServerUuid operation server uuid of the request url diff --git a/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructConfigurationServices.js b/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructConfigurationServices.js index d2bf9d8c..119d87cf 100644 --- a/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructConfigurationServices.js +++ b/server/applicationPattern/applicationPattern/onfModel/services/ForwardingConstructConfigurationServices.js @@ -447,6 +447,7 @@ let updated = false; let forwardingConstructUuid = forwardingConstruct["uuid"]; let applicationName = await getApplicationNameAsync(operationClientUuid); + let releaseNumber = await getReleaseNumberAsync(operationClientUuid); let isFcPortExists = await ForwardingConstruct.isFcPortExistsAsync( forwardingConstructUuid, operationClientUuid @@ -457,7 +458,8 @@ for(let i=0 ; i * @returns {Promise} returns true if the operation is successful. Promise is never rejected.
*/ - exports.recordServiceRequestFromClient = function (serverApplicationName, serverApplicationReleaseNumber, xCorrelator, traceIndicator, userName, originator, +exports.recordServiceRequestFromClient = function (serverApplicationName, serverApplicationReleaseNumber, xCorrelator, traceIndicator, userName, originator, operationName, responseCode, requestBody, responseBody) { return new Promise(async function (resolve, reject) { let httpRequestBody = {}; try { let operationClientUuid = await getOperationClientToLogServiceRequest(); let serviceName = await operationClientInterface.getOperationNameAsync(operationClientUuid); + let detailedLoggingIsOn = await operationClientInterface.getDetailedLoggingIsOnAsync(operationClientUuid); let ipAddressAndPort = await operationClientInterface.getTcpIpAddressAndPortAsyncAsync(operationClientUuid); let operationKey = await operationClientInterface.getOperationKeyAsync(operationClientUuid); let timestamp = moment().format(); @@ -42,7 +43,7 @@ const FcPort = require('../onfModel/models/FcPort'); let stringifiedRequestBody = JSON.stringify(requestBody); let stringifiedResponseBody = JSON.stringify(responseBody); let httpRequestBody = formulateRequestBody(xCorrelator, traceIndicator, userName, originator, serverApplicationName, serverApplicationReleaseNumber, - operationName, responseCode, timestamp, stringifiedRequestBody, stringifiedResponseBody); + operationName, responseCode, timestamp, stringifiedRequestBody, stringifiedResponseBody, detailedLoggingIsOn); let response = await requestBuilder.BuildAndTriggerRestRequest(ipAddressAndPort, serviceName, "POST", httpRequestHeader, httpRequestBody); let responseCodeValue = response.status.toString(); if (response !== undefined && responseCodeValue.startsWith("2")) { @@ -76,6 +77,7 @@ exports.recordServiceRequest = function (xCorrelator, traceIndicator, userName, try { let operationClientUuid = await getOperationClientToLogServiceRequest(); let serviceName = await operationClientInterface.getOperationNameAsync(operationClientUuid); + let detailedLoggingIsOn = await operationClientInterface.getDetailedLoggingIsOnAsync(operationClientUuid); let ipAddressAndPort = await operationClientInterface.getTcpIpAddressAndPortAsyncAsync(operationClientUuid); let operationKey = await operationClientInterface.getOperationKeyAsync(operationClientUuid); let timestamp = moment().format(); @@ -85,7 +87,7 @@ exports.recordServiceRequest = function (xCorrelator, traceIndicator, userName, let stringifiedRequestBody = JSON.stringify(requestBody); let stringifiedResponseBody = JSON.stringify(responseBody); let httpRequestBody = formulateRequestBody(xCorrelator, traceIndicator, userName, originator, applicationName, applicationReleaseNumber, - operationName, responseCode, timestamp, stringifiedRequestBody, stringifiedResponseBody); + operationName, responseCode, timestamp, stringifiedRequestBody, stringifiedResponseBody, detailedLoggingIsOn); let response = await requestBuilder.BuildAndTriggerRestRequest(ipAddressAndPort, serviceName, "POST", httpRequestHeader, httpRequestBody); let responseCodeValue = response.status.toString(); if (response !== undefined && responseCodeValue.startsWith("2")) { @@ -116,22 +118,35 @@ exports.recordServiceRequest = function (xCorrelator, traceIndicator, userName, * @returns {object} return the formulated responseBody
*/ function formulateRequestBody(xCorrelator, traceIndicator, userName, originator, applicationName, applicationReleaseNumber, - operationName, responseCode, timestamp, stringifiedBody, stringifiedResponse) { + operationName, responseCode, timestamp, stringifiedBody, stringifiedResponse, detailedLoggingIsOn) { let httpRequestBody = {}; try { - httpRequestBody = { - "x-correlator": xCorrelator, - "trace-indicator": traceIndicator, - "user": userName, - "originator": originator, - "application-name": applicationName, - "application-release-number": applicationReleaseNumber, - "operation-name": operationName, - "response-code": responseCode, - "timestamp": timestamp, - "stringified-body": stringifiedBody, - "stringified-response": stringifiedResponse - }; + if (detailedLoggingIsOn != undefined && detailedLoggingIsOn == true) { + httpRequestBody = { + "x-correlator": xCorrelator, + "trace-indicator": traceIndicator, + "user": userName, + "originator": originator, + "application-name": applicationName, + "application-release-number": applicationReleaseNumber, + "operation-name": operationName, + "response-code": responseCode, + "timestamp": timestamp, + "stringified-body": stringifiedBody, + "stringified-response": stringifiedResponse + }; + } else { + httpRequestBody = { + "x-correlator": xCorrelator, + "trace-indicator": traceIndicator, + "user": userName, + "originator": originator, + "application-name": applicationName, + "application-release-number": applicationReleaseNumber, + "operation-name": operationName, + "response-code": responseCode + }; + } return httpRequestBody; } catch (error) { console.log(error); diff --git a/server/applicationPattern/package.json b/server/applicationPattern/package.json index f2b27d26..b2e5f20b 100644 --- a/server/applicationPattern/package.json +++ b/server/applicationPattern/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap", - "version": "2.0.0-alpha.1", + "version": "2.0.0-alpha.3", "description": "onf core model application pattern", "main": "index.js", "scripts": { diff --git a/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js b/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js index c0e68e0a..d725b31d 100644 --- a/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js +++ b/server/basicServices/basicServices/services/PrepareALTForwardingAutomation.js @@ -3,6 +3,7 @@ const onfFormatter = require('onf-core-model-ap/applicationPattern/onfModel/util const controlConstruct = require('onf-core-model-ap/applicationPattern/onfModel/models/ControlConstruct'); const forwardingDomain = require('onf-core-model-ap/applicationPattern/onfModel/models/ForwardingDomain'); const forwardingConstruct = require('onf-core-model-ap/applicationPattern/onfModel/models/ForwardingConstruct'); +const LayerProtocol = require('onf-core-model-ap/applicationPattern/onfModel/models/LayerProtocol'); exports.getALTForwardingAutomationInputAsync = function (logicalTerminationPointconfigurationStatus, forwardingConstructConfigurationStatus) { return new Promise(async function (resolve, reject) { @@ -79,6 +80,28 @@ exports.getALTUnConfigureForwardingAutomationInputAsync = function (logicalTermi }); } +exports.getALTForwardingAutomationInputForOamRequestAsync = function (uuid) { + return new Promise(async function (resolve, reject) { + let forwardingConstructAutomationList = []; + try { + /*********************************************************************************** + * logical-termination-point related forwarding automation + ************************************************************************************/ + let ltpforwardingConstructAutomationInput = await getLtpForwardingAutomationInputForOAMRequestAsync(uuid); + let ltpforwardingConstructAutomationInputList = [ltpforwardingConstructAutomationInput]; + if (ltpforwardingConstructAutomationInputList) { + for (let i = 0; i < ltpforwardingConstructAutomationInputList.length; i++) { + let ltpforwardingConstructAutomationInput = ltpforwardingConstructAutomationInputList[i]; + forwardingConstructAutomationList.push(ltpforwardingConstructAutomationInput); + } + } + resolve(forwardingConstructAutomationList); + } catch (error) { + reject(error); + } + }); +} + function getLTPForwardingAutomationInputListAsync(logicalTerminationPointconfigurationStatus) { return new Promise(async function (resolve, reject) { let forwardingConstructAutomationList = []; @@ -523,6 +546,37 @@ function getFCPortDeleteForwardingAutomationInputList(fcPortConfigurationStatusL }); } +function getLtpForwardingAutomationInputForOAMRequestAsync(uuid) { + return new Promise(async function (resolve, reject) { + try { + let forwardingAutomation; + let oamRequestCausesLtpUpdateRequestForwardingName = "OamRequestCausesLtpUpdateRequest"; + let oamRequestCausesLtpUpdateRequestContext; + let oamRequestCausesLtpUpdateRequestRequestBody; + + if (uuid) { + oamRequestCausesLtpUpdateRequestRequestBody = await controlConstruct.getLogicalTerminationPointAsync( + uuid); + let layerProtocolName = oamRequestCausesLtpUpdateRequestRequestBody["layer-protocol"][0]["layer-protocol-name"]; + if (layerProtocolName == LayerProtocol.layerProtocolNameEnum.OPERATION_CLIENT || + layerProtocolName == LayerProtocol.layerProtocolNameEnum.OPERATION_SERVER) { + oamRequestCausesLtpUpdateRequestRequestBody = removeAttribute( + oamRequestCausesLtpUpdateRequestRequestBody, + "operation-key"); + } + forwardingAutomation = new forwardingConstructAutomationInput( + oamRequestCausesLtpUpdateRequestForwardingName, + oamRequestCausesLtpUpdateRequestRequestBody, + oamRequestCausesLtpUpdateRequestContext + ); + } + resolve(forwardingAutomation); + } catch (error) { + reject(error); + } + }); +} + function removeAttribute(jsonObject, attributeName) { for (var element in jsonObject) { diff --git a/server/basicServices/package.json b/server/basicServices/package.json index 5a81a616..5c54704a 100644 --- a/server/basicServices/package.json +++ b/server/basicServices/package.json @@ -1,6 +1,6 @@ { "name": "onf-core-model-ap-bs", - "version": "2.0.0-alpha.1", + "version": "2.0.0-alpha.3", "description": "onf core model application pattern", "main": "index.js", "scripts": { @@ -16,7 +16,7 @@ "oas3-tools": "^2.2.3", "randexp": "^0.5.3", "response-time": "^2.3.2", - "onf-core-model-ap": "2.0.0-alpha.1" + "onf-core-model-ap": "2.0.0-alpha.3" }, "author": "Prathiba Jeevan", "license": "Apache-2.0" From 250cdf61f37821dec785906aa7a27f01b081b4ee Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 6 Jan 2023 09:33:45 +0100 Subject: [PATCH 23/79] Add Martin & Vanitha to /server --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index de141fe8..18c11950 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ @openBackhaul -/server/ @PrathibaJee +/server/ @PrathibaJee @MartinSunal @vanithavalluripalli9 /docs/ @openBackhaul @PrathibaJee @IswaryaaS @Rajithapitta From 50fd5ef232b574c795aa545e60ee410cab71d4f9 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 6 Jan 2023 18:57:26 +0100 Subject: [PATCH 24/79] Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 18c11950..dafd535d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ @openBackhaul -/server/ @PrathibaJee @MartinSunal @vanithavalluripalli9 +/server/ @PrathibaJee @MartinSunal @vanithavalluripalli9 @IswaryaaS /docs/ @openBackhaul @PrathibaJee @IswaryaaS @Rajithapitta From 652a260d368edb8b2b8304e4f44ef706118a48b8 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Sat, 7 Jan 2023 09:29:31 +0100 Subject: [PATCH 25/79] Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dafd535d..23eefd9a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ @openBackhaul -/server/ @PrathibaJee @MartinSunal @vanithavalluripalli9 @IswaryaaS +/server/ @PrathibaJee @MartinSunal @DanaSunal @vanithavalluripalli9 @IswaryaaS /docs/ @openBackhaul @PrathibaJee @IswaryaaS @Rajithapitta From 36745f8bdb23b45c3c3ed01ede2e2faae7bfb808 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Sat, 7 Jan 2023 18:27:43 +0100 Subject: [PATCH 26/79] Add link to documentation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c9372b94..52081ecc 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Its implementation is publicly available and can be copied into every individual The ApplicationPattern is base of the application layer running in the live network at Telefonica Germany. ### Resources +- [Documentation](./doc/Main.md) - [Specification](./spec/) - [TestSuite](./testing/) - [Implementation](./server/) From ac8b29227ab12d10a7d1a92ebd376ebb2dd6efeb Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Sat, 7 Jan 2023 18:55:17 +0100 Subject: [PATCH 27/79] Correct findings Correct pattern of UUID at detailed-logging-is-on Lift examples to schema level in case of maxProperties: 1 Keept ONF notation for http in CONFIGfile Fixes #516 Fixes #517 Fixes #518 Fixes #519 --- spec/ApplicationPattern+config.json | 26 +++++++++++++------------- spec/ApplicationPattern.yaml | 13 ++++++++----- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/spec/ApplicationPattern+config.json b/spec/ApplicationPattern+config.json index 01fdbb3e..207c730a 100644 --- a/spec/ApplicationPattern+config.json +++ b/spec/ApplicationPattern+config.json @@ -712,7 +712,7 @@ "tcp-server-interface-1-0:tcp-server-interface-pac": { "tcp-server-interface-configuration": { "description": "Without TLS layer", - "local-protocol": "http", + "local-protocol": "tcp-server-interface-1-0:PROTOCOL_TYPE_HTTP", "local-address": { "ipv-4-address": " >>> ownIpAddress and Port (below) <<< " }, @@ -737,7 +737,7 @@ "tcp-server-interface-1-0:tcp-server-interface-pac": { "tcp-server-interface-configuration": { "description": "With TLS layer", - "local-protocol": "https", + "local-protocol": "tcp-server-interface-1-0:PROTOCOL_TYPE_HTTPS", "local-address": { "ipv-4-address": " >>> ownIpAddress and Port (below) <<< " }, @@ -810,7 +810,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.15" @@ -883,7 +883,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": " >>> IpAddress and Port (below) of the existing release <<< " @@ -930,7 +930,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": " >>> IpAddress and Port (below) of the new release <<< " @@ -1081,7 +1081,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.8" @@ -1128,7 +1128,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.9" @@ -1202,7 +1202,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.10" @@ -1275,7 +1275,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.11" @@ -1348,7 +1348,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.12" @@ -1551,7 +1551,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.13" @@ -1598,7 +1598,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.3.14" @@ -1645,7 +1645,7 @@ "layer-protocol-name": "tcp-client-interface-1-0:LAYER_PROTOCOL_NAME_TYPE_TCP_LAYER", "tcp-client-interface-1-0:tcp-client-interface-pac": { "tcp-client-interface-configuration": { - "remote-protocol": "http", + "remote-protocol": "tcp-client-interface-1-0:PROTOCOL_TYPE_HTTP", "remote-address": { "ip-address": { "ipv-4-address": "1.1.4.1" diff --git a/spec/ApplicationPattern.yaml b/spec/ApplicationPattern.yaml index 104d6275..0082ed74 100644 --- a/spec/ApplicationPattern.yaml +++ b/spec/ApplicationPattern.yaml @@ -7450,11 +7450,12 @@ paths: ipv-4-address: type: string pattern: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' - example: '1.1.4.1' domain-name: type: string pattern: '^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$' - example: 'application-pattern.mw-domain.transport.ger.telefonica.com' + example: + tcp-server-interface-1-0:local-address: + ipv-4-address: '1.1.4.1' responses: '204': description: 'Local IPv4 address documented' @@ -7800,7 +7801,7 @@ paths: required: true schema: type: string - pattern: '^([a-z]{2,6})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,2})-op-c-bm-([a-z]{2,6})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{3})$' + pattern: '^([a-z]{2,6})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,2})-op-c-bs-([a-z]{2,6})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,2})-([0-9]{3})$' example: 'ro-2-0-0-op-c-bs-eatl-2-0-0-000' get: operationId: getOperationClientDetailedLoggingIsOn @@ -9109,11 +9110,13 @@ paths: ipv-4-address: type: string pattern: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' - example: '1.1.4.1' domain-name: type: string pattern: '^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$' - example: 'application-pattern.mw-domain.transport.ger.telefonica.com' + example: + tcp-client-interface-1-0:remote-address: + ip-address: + ipv-4-address: '1.1.4.1' responses: '204': description: 'Remote IPv4 address configured' From e2485fc241724ea84a2e05671eaefbd4a7030cca Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Mon, 9 Jan 2023 10:03:59 +0100 Subject: [PATCH 28/79] Lift examples to schema level in another 2 cases --- spec/ApplicationPattern.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/ApplicationPattern.yaml b/spec/ApplicationPattern.yaml index 0082ed74..13995688 100644 --- a/spec/ApplicationPattern.yaml +++ b/spec/ApplicationPattern.yaml @@ -7409,10 +7409,11 @@ paths: properties: ipv-4-address: type: string - example: '1.1.4.1' domain-name: type: string - example: 'application-pattern.mw-domain.transport.ger.telefonica.com' + example: + tcp-server-interface-1-0:local-address: + ipv-4-address: '1.1.4.1' '400': $ref: '#/components/responses/responseForErroredOamRequests' '401': @@ -9064,10 +9065,12 @@ paths: properties: ipv-4-address: type: string - example: '1.1.4.1' domain-name: type: string - example: 'application-pattern.mw-domain.transport.ger.telefonica.com' + example: + tcp-client-interface-1-0:remote-address: + ip-address: + ipv-4-address: '1.1.4.1' '400': $ref: '#/components/responses/responseForErroredOamRequests' '401': From 6cf8a383f1fa2029856f687ffba1ef0810c70dab Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:32:51 +0100 Subject: [PATCH 29/79] Update Introduction2Git.md --- .../Introduction2Git/Introduction2Git.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/PreparingSpecifying/Introduction2Git/Introduction2Git.md b/doc/PreparingSpecifying/Introduction2Git/Introduction2Git.md index f429b046..3d43d2b9 100644 --- a/doc/PreparingSpecifying/Introduction2Git/Introduction2Git.md +++ b/doc/PreparingSpecifying/Introduction2Git/Introduction2Git.md @@ -7,7 +7,7 @@ In principle, you can use Git for any type of project in which only you or a who Git works particularly well when a project consists of many relatively small text files. Although Git can also handle binary files, changes in such files are difficult to trace. As such, Git is not ideal for tracking changes in Office documents, in audio and video files, or in virtual machine images. -In the terminal or in PowerShell, you control Git with the *git* command. The numerous options of this command allow you to download Git projects from external repositories like GitHub, save changed files in a *commit* and re-upload them, switch between different branches of a software project (e.g. master and develop), undo changes etc. (The repository is the collection of all files in a project, which includes not only the current version, but also all previous versions and all development branches.) +In principle, you could use Terminal or PowerShell for controlling Git by the *git* command. The numerous options of this command allow you to download Git projects from external repositories like GitHub, save changed files in a *commit* and re-upload them, switch between different branches of a software project (e.g. master and develop), undo changes etc. (The repository is the collection of all files in a project, which includes not only the current version, but also all previous versions and all development branches.) However, you can also use at least a subset of the Git functions via convenient interfaces. Almost all common development environments (Visual Studio, Xcode, IntelliJ, Android Studio, etc.) as well as most major editors (Atom, Sublime, VSCode, etc.) provide menu commands with which you can easily perform elementary Git operations. This also applies analogously to Web interfaces such as GitHub or GitLab. This not only allows you to manage Git projects and, for example, track the changes made to a file, but also use various additional functions (issue/bug management, automated tests, etc.). @@ -16,7 +16,7 @@ Despite all the charm that emanates from comfortable user interfaces, you must b ### Git versus GitHub versus GitLab -Basically, Git is a decentralized tool that does not rely on central repositories. In practice, however, external Git repositories such as GitHub or GitLab are ubiquitous. They simplify data exchange between the members of a development team considerably, serve as an additional backup and provide various additional functions (documentation, bug tracker, quality assurance, etc.). In the case of public projects, they also function as information and download sites for anyone interested in the project. +Basically, Git is a decentralized tool that does not rely on central repositories. In practice, however, external Git repositories such as GitHub or GitLab are ubiquitous. They simplify data exchange between the members of a development team considerably, serve as an additional backup and provide various additional functions (documentation, bug tracker, quality assurance, etc.). In the case of public projects, they also serve as information and download sites for anyone interested in the project. Modern web interfaces make it easier to get started and to administrate projects. GitHub, a company bought by Microsoft in 2018, currently has the largest market share among Git hosting providers. Open source projects could always be set up there free of charge. There are a lot of alternatives to GitHub. The best known is the company GitLab, which offers very similar functions - also in this case free of charge or commercially, depending on the requirements. The real specialty of GitLab is that the source code of the program is freely available. This makes it possible to set up GitLab on your own server. @@ -30,4 +30,4 @@ _Git - Projektverwaltung für Entwickler und DevOps-Teams_ Bernd Öggl und Michael Kofler Rheinwerk Verlag -[Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Workflow for contributing ->](../WorkflowForContributing/WorkflowForContributing.md) \ No newline at end of file +[Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Workflow for contributing ->](../WorkflowForContributing/WorkflowForContributing.md) From daa431479d66f780c5296fead7224d61c48eb187 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:51:09 +0100 Subject: [PATCH 30/79] Update WorkflowForContributing.md --- .../WorkflowForContributing.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/PreparingSpecifying/WorkflowForContributing/WorkflowForContributing.md b/doc/PreparingSpecifying/WorkflowForContributing/WorkflowForContributing.md index f4575766..dbb8c3d5 100644 --- a/doc/PreparingSpecifying/WorkflowForContributing/WorkflowForContributing.md +++ b/doc/PreparingSpecifying/WorkflowForContributing/WorkflowForContributing.md @@ -5,8 +5,8 @@ Efficiently doing so requires the definition of a process, which all involved pe ### Requirements to the workflow -* _master branch_ on GitHub: every commit is representing an official version, which is initiating further actions in neighboring domains (e.g. implementation or procurement) -* _develop branch_ (instead of tsi, tsp and so on) on GitHub: common base for all persons, who are involved into the specification process +* _main branch_ on GitHub: every commit is representing an official version, which is initiating further actions in neighboring domains (e.g. implementation or procurement) +* _develop branch_ on GitHub: common base for all persons, who are involved into the specification process * Short living _feature, hotfix and release branches_: separate places for advancing the specification before sharing results in the _develop branch_ * _public_ repository: allowing virtually everybody to contribute either by formulation _issues_ or addressing _pull-requests_, which are proposing concrete changes to the specification * _branch protection_: all changes to the common base (_develop branch_) must be reviewed and approved by either ApplicationOwner or PlatformOwner, which both are able to directly alter the proposed contributions before merging @@ -15,10 +15,14 @@ Efficiently doing so requires the definition of a process, which all involved pe Many different workflows can be implemented based on Git and GitHub. The proposed workflows are a bit more complex to apply in the beginning, but they are both comperably transparent and ease to debug (in case of "Kuddelmuddel"). -* ApplicationOwner (and PlatformOwner): - * will be assigned to be _Collaborator_, which allows to create branches in the _origin_ repository +* ApplicationOwner: + * will be assigned to be _CodeOwner_, which makes his/her approval necessary before merging into the common _develop branch_ * will apply the [_Gitflow Workflow_](../GitFlowWorkflow/GitFlowWorkflow.md) +* Every other team member: + * will be assigned to be _Collaborator_, which allows e.g. to create issues, branches and pull-requests in the public repository + * will also apply the [_Gitflow Workflow_](../GitFlowWorkflow/GitFlowWorkflow.md) * Everybody else: + * repositories are public; 3rd parties might engage, but have to pull the code and work in their own repositories; * will apply the [_Forking Workflow_](../ForkingWorkflow/ForkingWorkflow.md), which can be applied in most open source projects -[<- Back to Introduction to Git and GitHub](../Introduction2Git/Introduction2Git.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to GitFlow ->](../GitFlowWorkflow/GitFlowWorkflow.md) \ No newline at end of file +[<- Back to Introduction to Git and GitHub](../Introduction2Git/Introduction2Git.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to GitFlow ->](../GitFlowWorkflow/GitFlowWorkflow.md) From ac9ad5704810599b1a7c3124b20944e362ce69d1 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:13:16 +0100 Subject: [PATCH 31/79] Update GitFlowWorkflow.md --- .../GitFlowWorkflow/GitFlowWorkflow.md | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/PreparingSpecifying/GitFlowWorkflow/GitFlowWorkflow.md b/doc/PreparingSpecifying/GitFlowWorkflow/GitFlowWorkflow.md index 4cbe4263..2a570a23 100644 --- a/doc/PreparingSpecifying/GitFlowWorkflow/GitFlowWorkflow.md +++ b/doc/PreparingSpecifying/GitFlowWorkflow/GitFlowWorkflow.md @@ -7,18 +7,20 @@ Der Gitflow-Workflow nutzt ein zentrales Repository als Kommunikations-Drehkreuz Wie bei den anderen Workflows arbeiten die Entwickler lokal und pushen Branches in das zentrale Repository. Der Unterschied liegt in der Branch-Struktur des Projekts. -**master and develop branch** -Statt eines einzelnen _master branch_ sieht dieser Workflow zwei Branches vor, welche die History des Projekts abbilden. -Der _master branch_ enthält die offizielle Release-Historie, der _develop branch_ dient als Integrations-Branch für Features. -Es ist zudem üblich, alle Commits in den _master branch_ mit Versionsnummern zu taggen. +**main and develop branch** +Statt eines einzelnen _main branch_ sieht dieser Workflow zwei Branches vor, welche die History des Projekts abbilden. +Der _main branch_ enthält die offizielle Release-Historie, der _develop branch_ dient als Integrations-Branch für Features. +Es ist zudem üblich, alle Commits in den _main branch_ mit Versionsnummern zu taggen. ![Gitflow-Workflow-1](./pictures/Gitflow-Workflow-1.png) **feature branch** -Jedes neue Feature sollte in seinem eigenen Branch entwickelt werden, der für Backups und aus Gründen der Zusammenarbeit in das zentrale Repository gepusht werden kann. -Doch statt Branches auf Basis des _master branch_ zu erzeugen, wird der _develop branch_ als Quelle genutzt. -Wenn ein Feature fertig ist, wird es zurück in diesen _develop branch_ gemergt. -Der Gitflow-Workflow sieht vor, dass Features niemals direkt mit dem _master branch_ interagieren. +Jedes neue Feature wird in einem eigenen Branch entwickelt. +Dieser kann als Backup oder zur Unterstützung von Zusammenarbeit in das zentrale Repository gepusht werden. +Spätestens am Ende der Featureentwicklung muss er jedoch auf das zentrale Repository gepusht werden, damit der Review effizient durchgeführt werden kann. +Feature Branches werden auf Basis des _develop branch_ erstellt. +Wenn ein Feature fertig ist, wird der Feature Branch zurück in den _develop branch_ gemergt. +Der Gitflow-Workflow sieht vor, dass Features niemals direkt mit dem _main branch_ interagieren. ![Gitflow-Workflow-2](./pictures/Gitflow-Workflow-2.png) @@ -31,7 +33,7 @@ Wenn der _develop branch_ genügend Features für ein Release enthält (oder sic ![Gitflow-Workflow-3](./pictures/Gitflow-Workflow-3.png) Neue Features sollten ab diesem Punkt nicht mehr hinzugefügt werden, sondern nur Bugfixes und ähnliche Release-orientierte Änderungen. -Sobald das Release zur Auslieferung bereit ist, wird es in den _master branch_ gemergt und mit einer Versionsnummer getaggt. +Sobald das Release zur Auslieferung bereit ist, wird es in den _main branch_ gemergt und mit einer Versionsnummer getaggt. Zusätzlich sollte es zurück in den _develop branch_ gemergt werden, der sich weiterentwickelt haben könnte, seitdem das Release initiiert wurde. Die Nutzung eines dedizierten _release branch_ zur Vorbereitung von Releases ermöglicht es, dass ein Team das aktuelle Release feinschleift, während das andere Team weiter an Features für das nächste Release arbeitet. @@ -39,16 +41,16 @@ Auf diese Weise lassen sich Entwicklungsphasen sehr gut definieren und in der St **hotfix branch** _hotfix branch_ eignen sich für das Patchen von Produktiv-Releases. -Ein solcher Branch ist der einzige, der direkt vom _master branch_ geforkt wird. -Sobald die Probleme gefixt sind, wird er sowohl in den _master branch_ als auch in den _develop branch_ gemergt und der _master branch_ wird mit einer aktualisierten Versionsnummer getaggt. +Ein solcher Branch ist der einzige, der direkt vom _main branch_ geforkt wird. +Sobald die Probleme gefixt sind, wird er sowohl in den _main branch_ als auch in den _develop branch_ gemergt und der _main branch_ wird mit einer aktualisierten Versionsnummer getaggt. ![Gitflow-Workflow-4](./pictures/Gitflow-Workflow-4.png) Durch eine solche dedizierte Entwicklungslinie für Bugfixes kann ein Team Probleme des Produktiv-Releases beheben, ohne den Rest des Workflows zu unterbrechen oder auf den nächsten Release-Zyklus warten zu müssen. -_hotfix branch_ sind sozusagen Ad-hoc-Release-Branches, die direkt mit dem _master branch_ interagieren. +_hotfix branch_ sind sozusagen Ad-hoc-Release-Branches, die direkt mit dem _main branch_ interagieren. Quelle: //Seibert/Media https://infos.seibert-media.net/display/Productivity/Git-Workflows+-+Der+Gitflow-Workflow -[<- Back to Workflow for contributing](../WorkflowForContributing/WorkflowForContributing.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Forking Workflow ->](../ForkingWorkflow/ForkingWorkflow.md) \ No newline at end of file +[<- Back to Workflow for contributing](../WorkflowForContributing/WorkflowForContributing.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Forking Workflow ->](../ForkingWorkflow/ForkingWorkflow.md) From 243e648cbb7a42504658fc442572b6a43703e8b0 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:19:52 +0100 Subject: [PATCH 32/79] Update OwnGitHubAccount.md --- .../OwnGitHubAccount/OwnGitHubAccount.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/PreparingSpecifying/OwnGitHubAccount/OwnGitHubAccount.md b/doc/PreparingSpecifying/OwnGitHubAccount/OwnGitHubAccount.md index b5cfb34a..66935d4f 100644 --- a/doc/PreparingSpecifying/OwnGitHubAccount/OwnGitHubAccount.md +++ b/doc/PreparingSpecifying/OwnGitHubAccount/OwnGitHubAccount.md @@ -2,15 +2,16 @@ Um einen kostenlosen GitHub-Account einzurichten, füllen Sie das [Sign-up-Formular](https://github.com) aus. -Sie müssen nur drei Daten angeben: den Accountnamen (Username), eine E-Mail-Adresse und ein ausreichend langes/sicheres Passwort. Der Accountname ist später in all Ihren GitHub-Links sichtbar. +Sie müssen nur drei Daten angeben: den Accountnamen (Username), eine E-Mail-Adresse und ein ausreichend langes/sicheres Passwort. Der Accountname ist später in all Ihren GitHub-Links sichtbar. -Versuchen Sie also, einen möglichst sinnvollen Namen zu finden. (Ihr eigener Name bzw. der Ihrer Firma ist vermutlich schon vergeben. Außer Buchstaben und Zahlen ist als einziges Sonderzeichen ein Bindestrich erlaubt.) +Die Zusammearbeit im Team wird wesentlich erleichtert, falls vom Accountnamen auf ihren tatsächlichen Personennamen geschlossen werden kann. +(Ihr eigener Name bzw. der Ihrer Firma ist vermutlich schon vergeben. Außer Buchstaben und Zahlen ist als einziges Sonderzeichen ein Bindestrich erlaubt.) -In der Folge müssen Sie ein einfaches Rätsel lösen (um sicherzugehen, dass Sie kein Programm bzw. Bot sind) und können ein paar freiwillige Angaben zu Ihrem beruflichen Umfeld und Ihrer Programmiererfahrung machen. Zuletzt wird Ihre E-Mail-Adresse verifiziert. Später können Sie Ihren Account noch mit einem Foto oder Avatar, einem Link auf Ihre Website etc. personalisieren – aber all diese Daten sind optional. +In der Folge müssen Sie ein einfaches Rätsel lösen (um sicherzugehen, dass Sie kein Programm bzw. Bot sind) und können ein paar freiwillige Angaben zu Ihrem beruflichen Umfeld und Ihrer Programmiererfahrung machen. Zuletzt wird Ihre E-Mail-Adresse verifiziert. Später können Sie Ihren Account noch mit einem Foto oder Avatar, einem Link auf Ihre Website etc. personalisieren – aber all diese Daten sind optional. Quelle: _Git - Projektverwaltung für Entwickler und DevOps-Teams_ Bernd Öggl und Michael Kofler -Rheinwerk Verlag +Rheinwerk Verlag [<- Back to Avoiding Conflicts](../AvoidingConflicts/AvoidingConflicts.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Installing Git ->](../InstallingGit/InstallingGit.md) From e4a9880d04cd9f26ea7964b9fdd1fdb578b1b614 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:13:21 +0100 Subject: [PATCH 33/79] Update VSCode2GitHub.md --- .../VSCode2GitHub/VSCode2GitHub.md | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md b/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md index 700d0223..6f876b79 100644 --- a/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md +++ b/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md @@ -41,7 +41,7 @@ Therefore go to *File* -> *Preferences* -> *Settings* and type proxy into the ap ### Clone the GitHub repository to VSCode -Navigate to the [repository, which you would like to work with,](https://github.com/openBackhaul/Overview) in the browser to obtain the repository URL. Pressing the green “Code” button expands a clone menu from which the URL can be copied: +Navigate to the [repository, which you would like to work with,](https://github.com/openBackhaul?tab=repositories) in the browser to obtain the repository URL. Pressing the green “Code” button expands a clone menu from which the URL can be copied: |![vsc_02](https://user-images.githubusercontent.com/57349523/152162626-7b471cb2-7957-45f4-a295-630fb64799b8.jpg)| |---| @@ -53,6 +53,42 @@ Press *“Clone from URL”* and select a location to which the repository will |![vsc_03](https://user-images.githubusercontent.com/57349523/152162630-03b0bdbb-c44e-43a8-b954-72b9fba97f84.jpg)| |---| +Change into the local folder to which the repository has been downloaded. +Change into the .git subfolder and open the config file. +Take care that an *"longpaths = true"* statement is added in the core section. +``` +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + longpaths = true +[remote "origin"] + url = https://github.com/openBackhaul/Resolver.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "develop"] + remote = origin + merge = refs/heads/develop +[branch "main"] + remote = origin + merge = refs/heads/main +``` +Save and close the config file. + +Change back into the local folder to which the repository has been downloaded. +Create a .github subfolder aside the already existing .git subfolder. +Change into the .github subfolder. +Create a text file with name CODEOWNERS (no .txt extention!). +Open the CODEOWNERS file in an editor. +Add your own GitHub account name like this: +``` +* @your-github-account-name + +``` +Save and close the CODEOWNERS file. + Change to the **develop** branch by pressing the branch button in the bottom left corner and select the *develop* branch in the then appearing selection menu. The resources of the selected branch will then be downloaded to the local directory and are shown in VSCode. |![vsc_06](https://user-images.githubusercontent.com/57349523/152162636-3587d64c-21d0-4d54-8869-700b293bc995.jpg)| From 6e462305d09604411fb2700c1e8a06915438b463 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:22:29 +0100 Subject: [PATCH 34/79] Update VSCode2GitHub.md --- .../VSCode2GitHub/VSCode2GitHub.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md b/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md index 6f876b79..865d9a03 100644 --- a/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md +++ b/doc/PreparingSpecifying/VSCode2GitHub/VSCode2GitHub.md @@ -77,18 +77,6 @@ Take care that an *"longpaths = true"* statement is added in the core section. ``` Save and close the config file. -Change back into the local folder to which the repository has been downloaded. -Create a .github subfolder aside the already existing .git subfolder. -Change into the .github subfolder. -Create a text file with name CODEOWNERS (no .txt extention!). -Open the CODEOWNERS file in an editor. -Add your own GitHub account name like this: -``` -* @your-github-account-name - -``` -Save and close the CODEOWNERS file. - Change to the **develop** branch by pressing the branch button in the bottom left corner and select the *develop* branch in the then appearing selection menu. The resources of the selected branch will then be downloaded to the local directory and are shown in VSCode. |![vsc_06](https://user-images.githubusercontent.com/57349523/152162636-3587d64c-21d0-4d54-8869-700b293bc995.jpg)| From 1e6f8bc38f2f9d00a6ca9e02901e7ed8c30bd36f Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Mon, 9 Jan 2023 18:33:31 +0100 Subject: [PATCH 35/79] Add doc about CodeOwner configuration --- .../AddCodeOwner/AddCodeOwner.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 doc/PreparingSpecifying/AddCodeOwner/AddCodeOwner.md diff --git a/doc/PreparingSpecifying/AddCodeOwner/AddCodeOwner.md b/doc/PreparingSpecifying/AddCodeOwner/AddCodeOwner.md new file mode 100644 index 00000000..a8db9150 --- /dev/null +++ b/doc/PreparingSpecifying/AddCodeOwner/AddCodeOwner.md @@ -0,0 +1,18 @@ +# Adding the CodeOwner to your repository + +## Introduction + +The CodeOwner has to approve every merge into its repository or subfolder. +The ApplicationOwner shall be defined to be CodeOwner on the entire repository. + +## How to define the CodeOwner + +1. Find or create the `.github` folder in the root directory and change into it. +2. Add a new file named `CODEOWNERS`. +3. Open the CODEOWNERS file. +4. Add your own GitHub account name like this: +``` + @your-github-account-name + +``` +5. Commit the file into the _develop_ branch. From dd05bad68b1a037cb27096e6442cc25c8de3efcc Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Mon, 9 Jan 2023 18:38:07 +0100 Subject: [PATCH 36/79] Create link to CodeOwner doc --- doc/PreparingSpecifying/PreparingSpecifying.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/PreparingSpecifying/PreparingSpecifying.md b/doc/PreparingSpecifying/PreparingSpecifying.md index 2898744f..2566c042 100644 --- a/doc/PreparingSpecifying/PreparingSpecifying.md +++ b/doc/PreparingSpecifying/PreparingSpecifying.md @@ -31,6 +31,7 @@ Git is available for Linux, Windows and Mac. * [Creating an own GitHub account](./OwnGitHubAccount/OwnGitHubAccount.md) * [Installing Git](./InstallingGit/InstallingGit.md) * [Activating YAML validation on your respository](./AddYamlLinter/Adding%20Yaml%20linter%20to%20GitHub.md) +* [Defining CodeOwners on your respository](./AddCodeOwner/AddCodeOwner.md) ### Code Collaboration From 6ac5c4969adb8ff5debc95fe407768ed9f6eddf9 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Wed, 11 Jan 2023 14:49:44 +0100 Subject: [PATCH 37/79] Reformulate chapter "Formulating Issues" --- .../FormulatingIssues/FormulatingIssues.md | 87 +++++++++---------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md b/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md index cfe547ca..bfe2034e 100644 --- a/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md +++ b/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md @@ -1,48 +1,47 @@ # Formulating Issues -Development of documentation, specification and code shall be driven by issues (commits shall reference the respective issue). -These issues shall contain meaningful information and advice for completing the task, even by a third person. -Issues shall -* be used not just for fixing existing problems, but also for defining next steps in the development. -* structure your thoughts, ideally together with others (**here is where the real collaboration happens!**). -* focus on ideas, problems and solutions. - -### How to write issues - -* !!! **one issue per issue** !!!: try to break down complex problems into multiple issues -* **keep titles short and descriptive** -* **start titles with a verb, e.g. with one of the following keywords**: - * Add - * Fix - * Merge - * Polish - * Refactor - * Release - * Remove - * Revert - * Update -* **remain clear and concise**: keep messages short and to the point, use bullet points -* format messages: use markdown syntax for headlines, bold text, lists, images, etc. (only use plain markdown syntax, no embedded html etc.) -* avoid duplication: before creating a new issue assure that it is not already covered by an existing one; if duplicates are found close one (typically the less thorough one) and add missing information from it to the remaining one. The closing comment should contain a link to the remaining issue. -* avoid speculation and opinion: E.g. for a bug describe it thorougly and include some investigation results, but do not speculate where the bug happens. -* issue as user story: if possible consider to include one in the issue, especially beneficial to feature requests. (Example format: “As a [type of user] I want [my goal] so that [my reason].” -* **use labels**: use labels to reflect the issue status or type (e.g. "bug" for bug issues, or "duplicate" to show that it is a duplicate issue.) -* **close solved issues**: close issues once they are solved. - -### What to include into the message - -|![issues_3](https://user-images.githubusercontent.com/57349523/155708237-833c98f0-73ad-4f61-a770-d3dfca0f5017.jpg)| -|---| - -* **context**: explain the condition that led to writing the issue -* **problem or idea**: the context should lead to an idea or problem etc. -* **solution or next step**: engage others here if necessary (e.g. request feedback, assign issue to someone else, etc),must-have, as this is where you move forward -* **include all relevant information when creating the issue**: leave out all the irrelevant information -* **reproduction steps**: in case of bugs or errors provide instructions (reduce steps only the bare minimum) on how to reproduce the problem. -* **include the right people in the discussion**: apart from assigning the issue to the correct person, mention others to get feedback -* **for issues with source code** - * *add project version*: important for context of the issue - * *add branch* to which the issue is related (e.g. on branch-1 the issue is still there, but not on branch-2, as it has been fixed there already) - * *code over text*: include relevant code snippet instead of explaining what it does. +Development of documentation, specification and code shall be driven by Issues. +Issues shall be used not just for fixing existing problems, but also for defining next steps in the development. +Aligning thoughts with team members or users while formulating the Issues is much cheaper and faster than correcting code or formalized specifications. +Descriptions of Pull-requests shall [reference the respective Issue (or Issues)](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls). + +Every Issue shall exclusively deal with a single subject. +If it would turn out that an existing Issue decomposes into multiple subjects (maybe even affecting multiple repositories), several new Issues shall be formulated and the original Issue shall be reduced to referencing all the new Issues (take care that references are made in such a way that they get automatically updated based on the status of the referenced Issue). + +Keep titles short and descriptive. +Avoid words that could be used in every title. +Avoid details about the location of the problem in the title. + +In first place, Issues have to be divided into the following two categories: +1) It's your repository; you formulate the Issue; you assign it to yourself. So, the Issue serves either as a reminder or a documentation of an idea. +2) You are not the CodeOwner and the requested change has to be processed by someone else. + +_In case of 1):_ +No matter how you formulate the Issue, it will help you to structure and plan your activities. +It allows you to separate developing basic ideas from elaborating the concrete formulation (which is often suppressing your creativity by uncertainties about the exact syntax). +If you are expecting the Issue not to be executed at the same day, it is recommended to include a statement that puts it into context. This might be a description of an insufficiency or a wished result. +If you would already have an idea about how the situation could be fixed, this idea should be noted. +Frame conditions, requirements, even doubts about the first idea should be noted as bullet points. +You will be thankful for every note that helps you to shorten the time period for thinking yourself back into the subject again later. + +_In case of 2):_ +Check, whether your point has already been covered in one of the already existing Issues (open and closed). +Please consider that from the CodeOwner's point of view everything is fine. +It's you who wishes a modification. +A clear and concise description obviously increases chances to get the wished change. +Avoid prescribing a concrete syntax for solving a problem in the title or as the exclusive content of the text. +Describe the currently wrong situation and/or how the situation could be better. +After being convinced from need for change, the CodeOwner is certainly open for a concrete **proposal** about where and how to fix the code. +Avoid speculations and opinions, but focus on problems, ideas and propose solutions. + +If you are at least Collaborator, it makes sense to address the Issue. +Assign it to the ApplicationOwner, if changes to the specification are required. +Assign it to the ApplicationImplementer, if changes to the implementation are required. + +If you are the CodeOwner: +- Use labels for categorizing the kind of change required. +- Use milestones for scheduling the required change. +If you would be unsure about proper labels and milestones, visit one of the existing repositories (e.g. [ApplicationPattern](https://github.com/openBackhaul/ApplicationPattern/issues), [RegistryOffice](https://github.com/openBackhaul/RegistryOffice/issues) etc.) as a reference. + [<- Back to Forking Workflow](../ForkingWorkflow/ForkingWorkflow.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Formulating Commit Messages ->](../FormulatingCommitMessages/FormulatingCommitMessages.md) From 68477e3deb2914b0bcc01148d9c931722efe2953 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Wed, 11 Jan 2023 14:54:27 +0100 Subject: [PATCH 38/79] Update FormulatingIssues.md --- doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md b/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md index bfe2034e..98b0f3ba 100644 --- a/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md +++ b/doc/PreparingSpecifying/FormulatingIssues/FormulatingIssues.md @@ -38,9 +38,10 @@ If you are at least Collaborator, it makes sense to address the Issue. Assign it to the ApplicationOwner, if changes to the specification are required. Assign it to the ApplicationImplementer, if changes to the implementation are required. -If you are the CodeOwner: +If you are the CodeOwner: - Use labels for categorizing the kind of change required. - Use milestones for scheduling the required change. + If you would be unsure about proper labels and milestones, visit one of the existing repositories (e.g. [ApplicationPattern](https://github.com/openBackhaul/ApplicationPattern/issues), [RegistryOffice](https://github.com/openBackhaul/RegistryOffice/issues) etc.) as a reference. From 3af1536312d7d8e2b2b6629a2640aa471c3a3e5a Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Wed, 11 Jan 2023 16:15:15 +0100 Subject: [PATCH 39/79] Update "FormulatingCommitMessages" --- .../FormulatingCommitMessages.md | 68 +++++++++++-------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md b/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md index e06258c6..4a37a5e5 100644 --- a/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md +++ b/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md @@ -1,33 +1,47 @@ -# Formulating Commit and Merge Request Messages +# Formulating Commit and Pull-Request Messages Development of documentation, specification and code shall be collaborative. This includes reviewing artifacts before consolidating them into the shared base. -Such review is not just "additional work", but also time critical, because the shared base might change between merge request and merge commit. -Well formulated **merge request messages must support efficiently reviewing** the contributed artifact. - -### Subject line - -* **50 characters** or less: formulate meaningful, concise and comprehensive! -* **start subject line with a verb, e.g. with one of the following keywords**, as e.g. Add, Update, Remove, Refactor, Revert ... -* write in the imperative: e.g. "Add ServiceList" not "ServiceList added" or "Adds ServiceList" -* do not end the subject line with a dot - -### Message body - -* **separate subject from body with a blank line**, if e.g. VSCode is used -* **automate by references**: In case of a pull-request, add "Fixes #issue-number" to the description and the pull-request will be mentioned in the issue and the issue will automatically close after successful merge. -* nice to have: - * explain _what_ and _why_ something has been done, but details about _how_ a change has been made can be left out in most cases - * describe effects of the change - * relate to the content of the issue - * describe limitations of the current code or delivery item - * bullet points can be used - * capitalize each paragraph - * wrap lines at 72 characters - * do not assume that reviewers understand what the original problem was - * do not assume the change/code is self-evident/self-documenting - * if documentation from inside GitHub or external pages should be referenced, these can be linked by \[add link text in square brackets\]\(add link URL in parenthesis\) - +Such review is not just "additional work", but also time critical, because the shared base might change between pull-request and merge. + + +### Subject line and Body of Commits + +- The subject line allows 50 characters or less: formulate meaningful, concise and comprehensive! +- Start the subject line with a verb, e.g. with one of the following keywords, as e.g. Add, Update, Remove, Refactor, Revert, Correct ... +- Formulate the imperative: e.g. "Add ServiceList", but not "ServiceList added" or "Adds ServiceList". +- Do not end the subject line with a dot. +- Be aware that the body of the commit message is usually not visible: + - It's better to make more often Commits and to use just the subject line. + - Otherwise describe all covered aspects with similarly styled statements in the body of the commit message. + + +### Subject line and Body of Pull-Request +- In regards to the subject line, apply the same rules as for Commits +- Separate subject from body with a blank line, if e.g. VSCode is used +- Automate closing the underlying Issue(s) by adding "Fixes #issue-number" (e.g. "Fixes #134") to the body + +Adding the _Fixes_ statement to the body of the Pull-Request is really a must, because ... +- ... the underlying Issue gets referenced in the Pull-Request; usually it's not required to add further details in the body of the Pull-Request. +- ... the underlying Issue gets automatically closed at the moment the Pull-Request gets merged. +- ... a reference to the Pull-Request is added to the Issue. So, you can jump back and forth. +- ... the Issue gets marked as being covered by a Pull-Request in the list of Issues. + + +### Commenting on Pull-Requests +- Ideally, you are associating your comment with the affected line. +- Ideally, you are explicit in what to be replaced by what. +- Often, the same mistake occurs multiple times in the same document. If you would formulate (and test) a phrase to be searched and replaced (CTRL+h) by a correct one, commenting and correcting efforts might get massively reduced. +- If the mistake would not be 100% obvious and clear, explain the need for change in the same way as in an Issue. + + +### Reacting on Comments in Pull-Requests +- Answer to every comment. +- If you accepted the proposed change, then confirm this. +- If you made modifications, but different from the proposed ones, then explain why. +- In case of need for clarification, formulate questions. + + The commit message dialogues at GitHub and VSCode are slightly different. |**GitHub**|**VSCode**| From 7c0cd5b104159387917627ecbd0c2f81fe113b9e Mon Sep 17 00:00:00 2001 From: IswaryaaS Date: Thu, 12 Jan 2023 10:30:45 +0530 Subject: [PATCH 40/79] Fixes #383 Fixes #446 Fixes #399 Fixes #401 Fixes #403 --- testing/ApplicationPattern+testcases.json | 81343 ++++++++++++-------- 1 file changed, 49714 insertions(+), 31629 deletions(-) diff --git a/testing/ApplicationPattern+testcases.json b/testing/ApplicationPattern+testcases.json index 39de221e..90940fce 100644 --- a/testing/ApplicationPattern+testcases.json +++ b/testing/ApplicationPattern+testcases.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "9f4bf6d2-4115-4f11-b6b0-45e23ce65b5e", + "_postman_id": "4436e28f-5988-4868-93f3-ca2676231abd", "name": "ApplicationPattern+testcases", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "16731944" @@ -114,6 +114,89 @@ "name": "functions()", "item": [] }, + { + "name": "=====> JustJumpToTarget =====>", + "item": [ + { + "name": "=====> JustJumpToTarget =====>", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- JustJumpToTarget --------------------------------------------------\");", + "/****************************************************************************************", + "* ", + "* This is a request for daily working with the Validator.", + "* It just makes the program flow jumping to the Request named \"=====> Target =====>\".", + "* ", + "****************************************************************************************/", + " ", + " ", + "/****************************************************************************************", + "* Loading Input Data", + "****************************************************************************************/", + "try {", + " var URI;", + " URI = pm.environment.get(\"dummyUri\");", + "", + "} catch (error) {", + " console.log(\"! Environment variables could not be loaded.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Setting up Local Variables and Preparing the Request", + "****************************************************************************************/", + "try {", + " pm.variables.clear();", + "", + " postman.setNextRequest(\"=====> Target =====>\");", + "", + " pm.variables.set(\"uri\", URI);", + " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", + "", + "} catch (error) {", + " console.log(\"! Local variables could not be set.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Functions", + "****************************************************************************************/", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ] + }, { "name": "ServiceLayer", "item": [ @@ -121,7 +204,7 @@ "name": "BasicPart", "item": [ { - "name": "/v1/inform-about-application", + "name": "/v1/start-application-in-generic-representation", "item": [ { "name": "Continuous Integration", @@ -130,13 +213,13 @@ "name": "Service Idempotent?", "item": [ { - "name": "Expected /v1/inform-about-application - service idempotent?", + "name": "reference /core-model-1-4:control-construct", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-application integration -- is service idempotent? -------------------------------\");\r", + "console.log(\"\\n----- /v1/start-application-in-generic-representation integration -- is service idempotent? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -145,41 +228,8 @@ " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = \"\";\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", + " console.log(\"! Environment variables could not be loaded.\");\r", "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", "\r", "\r", "/****************************************************************************************\r", @@ -187,7 +237,13 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -195,22 +251,18 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", + "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -219,24 +271,6 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", - "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}\r", "" ], "type": "text/javascript" @@ -254,28 +288,47 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", "\r", - " RESPONSE_CODE = parseInt(response.code);\r", + " } else {\r", + " ltpList = [];\r", + " }\r", "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/start-application-in-generic-representation\", ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/inform-about-application responds 200\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(200);\r", - " });\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", "\r", @@ -283,19 +336,46 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", - " }\r", "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", "\r", - " return alternativeLifeCycleState;\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", "}\r", "" ], @@ -4405,17 +4503,30 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", + "var expectedXCorrelator;\r", + "try {\r", + " expectedXCorrelator = pm.collectionVariables.get(\"xCorrelator\");\r", + " \r", + "} catch(error) {\r", + " console.log(\"! Could not load input data. \");\r", + "}\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var actualXCorrelator;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", " \r", + " actualXCorrelator = RESPONSE_HEADERS.get(\"x-correlator\");\r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -4425,14 +4536,18 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"POST /v1/start-application-in-generic-representation responds 200\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(200);\r", + " });\r", + " pm.test(\"Provides expected x-correlator: \" + expectedXCorrelator, function () {\r", + " pm.expect(actualXCorrelator).to.equal(expectedXCorrelator);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -4444,12 +4559,12 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", - "type": "text" + "value": "200", + "type": "default" } ], "body": { @@ -4469,14 +4584,21 @@ } }, "response": [] - }, + } + ], + "description": "## Is the initial x-correlator ín the response?\n\n#### Preparation:\n\n* GETing CC (/core-model-1-4:control-construct)\n* searching CC for op-s of /v1/start-application-in-generic-representation, storing operation-key\n* POST /v1/start-application-in-generic-representation \n \\-operation-key from above\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for response headers containing x-correlator==dummyXCorrelator\n \n\n#### Clearing:\n\n* not applicable" + }, + { + "name": "life-cycle-state responded?", + "item": [ { - "name": "Expected /v1/inform-about-application", + "name": "reference /core-model-1-4:control-construct", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- /v1/start-application-in-generic-representation integration -- life-cycle-state responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -4485,41 +4607,8 @@ " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = \"\";\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", + " console.log(\"! Environment variables could not be loaded.\");\r", "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", "\r", "\r", "/****************************************************************************************\r", @@ -4527,7 +4616,13 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -4535,22 +4630,18 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", + "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -4559,24 +4650,7 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", - "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}" + "" ], "type": "text/javascript" } @@ -4588,50 +4662,52 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedLifeCycleState;\r", - "try {\r", - " let dummyLifeCycleState;\r", - " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", - "\r", - " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", - " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Could not load Input Data. \");\r", - "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", - "var actualLifeCycleState;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", "\r", - " RESPONSE_CODE = parseInt(response.code);\r", + " } else {\r", + " ltpList = [];\r", + " }\r", "\r", - " let RESPONSE_HEADERS;\r", - " RESPONSE_HEADERS = pm.response.headers; \r", + "} catch (error) {\r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", "\r", - " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", + "var currentOperationServer;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/start-application-in-generic-representation\", ltpList);\r", "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", - " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", - " });\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", "\r", @@ -4639,14 +4715,41 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", "" ], "type": "text/javascript" @@ -7914,92 +8461,49 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", - "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var ltpList;\r", + "var RESPONSE_CODE;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", + " RESPONSE_CODE = parseInt(response.code);\r", " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var listRecordsOfFlowOperationKey;\r", - "try {\r", - " listRecordsOfFlowOperationKey = FindOperationKeyForOperationName(\"/v1/list-records-of-flow\", ltpList);\r", - "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Setting Collection Variables\r", + "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.set(\"listRecordsOfFlowOperationKey\", listRecordsOfFlowOperationKey);\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", "\r", "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", + " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function FindOperationKeyForOperationName(operationName, ltpList) {\r", - " let operationKey;\r", - " operationKey = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for ( let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", - " }\r", "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "function GenerateFaultyXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", "\r", - " return alternativeLifeCycleState;\r", + " let separators;\r", + " separators = \".:;/\";\r", + " let separatorsLength;\r", + " separatorsLength = separators.length;\r", + "\r", + " let faultySeparator;\r", + " faultySeparator = separators.charAt(Math.floor(Math.random() * separatorsLength));\r", + "\r", + " xCorrelator += GenerateRandomHexString(8) + faultySeparator;\r", + " xCorrelator += GenerateRandomHexString(4) + faultySeparator;\r", + " xCorrelator += GenerateRandomHexString(4) + faultySeparator;\r", + " xCorrelator += GenerateRandomHexString(4) + faultySeparator;\r", + " xCorrelator += GenerateRandomHexString(12);\r", + "\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", "}\r", "" ], @@ -10496,6 +10315,7 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", @@ -10503,9 +10323,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -10515,14 +10335,15 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"As expected, POST /v1/inform-about-application responds 400, because of incorrect separator in x-correlator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -10534,11 +10355,11 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", + "value": "400", "type": "text" } ], @@ -10559,14 +10380,22 @@ } }, "response": [] - }, + } + ], + "description": "## Gets x-correlator checked for complying the pattern?\n\n#### Preparation:\n\n* POST /v1/inform-about-application\n * reasonable parameters, BUT dummyXCorrelators differing from the pattern in various ways (e.g. empty string).\n\n#### Testing:\n\n* checking for ResponseCode==400\n \n\n#### Clearing:\n\n* not applicable" + }, + { + "name": "trace-indicator pattern", + "item": [ { - "name": "Expected /v1/inform-about-application-in-generic-representation", + "name": "Expected /v1/inform-about-application with letters in trace-indicator", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- /v1/inform-about-application integration -- trace-indicator pattern correctness check -------------------------------\");\r", + "console.log(\"\\n----- trace-indicator parameter correctness check - presence of letters -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -10585,16 +10414,17 @@ "var USER_NAME;\r", "var ORIGINATOR;\r", "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", + "var FAULTY_TRACE_INDICATOR;\r", "var CUSTOMER_JOURNEY;\r", "try {\r", " USER_NAME = APPLICATION.userName;\r", " ORIGINATOR = \"Postman\";\r", " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", + " FAULTY_TRACE_INDICATOR = GenerateFaultyTraceIndicator();\r", " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", " \r", "} catch (error) {\r", + " console.log(error)\r", " console.log(\"! Could not define dummy values for parameters. \");\r", "}\r", "\r", @@ -10617,7 +10447,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-application-in-generic-representation\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -10633,14 +10463,13 @@ " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:FAULTY_TRACE_INDICATOR});\r", " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -10648,6 +10477,30 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function GenerateFaultyTraceIndicator() {\r", + " let traceIndicator;\r", + " traceIndicator = \"\";\r", + "\r", + " let traceIndicatorParts;\r", + " traceIndicatorParts = [];\r", + " for(let i=0; i<3; i++) {\r", + " traceIndicatorParts[i] = Math.floor(Math.random() * 10);\r", + " }\r", + " let characters;\r", + " characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength;\r", + " charactersLength = characters.length;\r", + " let faultyElement;\r", + " faultyElement = characters.charAt(Math.floor(Math.random() * charactersLength));\r", + "\r", + " let faultyTraceIndicatorPart;\r", + " faultyTraceIndicatorPart = Math.floor(Math.random() * 3);\r", + "\r", + " traceIndicatorParts[faultyTraceIndicatorPart] = faultyElement;\r", + " traceIndicator = traceIndicatorParts.join(\".\");\r", + "\r", + " return traceIndicator;\r", + "}\r", "\r", "function CreateXCorrelator() {\r", " let xCorrelator;\r", @@ -10666,7 +10519,8 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}" + "}\r", + "" ], "type": "text/javascript" } @@ -10678,35 +10532,18 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedLifeCycleState;\r", - "try {\r", - " let dummyLifeCycleState;\r", - " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", - "\r", - " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", - " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Could not load Input Data. \");\r", - "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", - " let RESPONSE_HEADERS;\r", - " RESPONSE_HEADERS = pm.response.headers; \r", - "\r", - " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", - "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -10716,8 +10553,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", - " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " pm.test(\"As expected,POST /v1/inform-about-application responds 400, because of presence of letters in trace-indicator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -10740,7 +10577,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "200", + "value": "400", "type": "text" } ], @@ -10763,49 +10600,65 @@ "response": [] }, { - "name": "Initial life-cycle-state", + "name": "Expected /v1/inform-about-application with incorrect separator trace-indicator", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- trace-indicator parameter correctness check - incorrect separator -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", - "var operationServerUuid;\r", - "var initialLifeCycleState;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - "\r", - " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", "\r", - " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "/****************************************************************************************\r", + "* Defining Dummy Parameters\r", + "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var X_CORRELATOR;\r", + "var FAULTY_TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", + "try {\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " X_CORRELATOR = CreateXCorrelator();\r", + " FAULTY_TRACE_INDICATOR = GenerateFaultyTraceIndicator();\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", "} catch (error) {\r", - " console.log(\"! Input Data could not be loaded.\");\r", + " console.log(\"!Could not define request body. \");\r", "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl \r", - " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", - " + operationServerUuid\r", - " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = '{ '\r", - " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", - " + ' }';\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -10817,11 +10670,15 @@ "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " \r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:FAULTY_TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", " console.log(\"! Local variables could not be set.\");\r", @@ -10831,7 +10688,46 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function GenerateFaultyTraceIndicator() {\r", + " let traceIndicator;\r", + " traceIndicator = \"\";\r", + "\r", + " let traceIndicatorParts;\r", + " traceIndicatorParts = [];\r", + " for(let i=0; i<3; i++) {\r", + " traceIndicatorParts[i] = Math.floor(Math.random() * 10);\r", + " }\r", + " let separators;\r", + " separators = \"-:;/\";\r", + " let separatorsLength;\r", + " separatorsLength = separators.length;\r", + "\r", + " let faultySeparator;\r", + " faultySeparator = separators.charAt(Math.floor(Math.random() * separatorsLength));\r", + "\r", + " traceIndicator = traceIndicatorParts.join(faultySeparator);\r", + "\r", + " return traceIndicator;\r", + "}\r", + "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", "" ], "type": "text/javascript" @@ -10853,9 +10749,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -10865,8 +10761,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"As expected, POST /v1/inform-about-application responds 400, because of incorrect separator in trace-indicator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -10885,11 +10781,11 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", + "value": "400", "type": "text" } ], @@ -10912,119 +10808,19 @@ "response": [] } ], - "description": "## Gets lifeCycleState propagated?\n\n#### Preparation:\n\n* GETing CC (/core-model-1-4:control-construct)\n* searching CC for op-s of /v1/inform-about-application-in-generic-representation, storing it\n* PUTting op-s-configuration/life-cycle-state with random alternative value\n* POST /v1/inform-about-application-in-generic-representation\n * all parameters with reasonable values\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n \n\n#### Clearing:\n\n* PUTting op-s-configuration/life-cycle-state back to original value" - } - ] - }, - { - "name": "Exit", - "item": [ - { - "name": "for exiting /v1/inform-about-application-in-generic-representation", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var URI;\r", - "try {\r", - " URI = pm.environment.get(\"dummyUri\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Loading Input Data failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Updating Environmental Variables and Determining the next Step\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " pm.variables.clear();\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = \"\";\r", - "\r", - " let OPERATION_KEY;\r", - " OPERATION_KEY = \"\";\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - " pm.request.headers.upsert({key:\"operationKey\", value:OPERATION_KEY});\r", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:\"application/json\"});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Setting Local Variables and Preparing the Request failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "/v1/inform-about-release-history", - "item": [ - { - "name": "Continuous Integration", - "item": [ + "description": "## Gets trace-indicator checked for complying the pattern?\n\n#### Preparation:\n\n* POST /v1/inform-about-application\n * all parameters with realistic values, BUT dummyTraceIndicator differing from the pattern in various ways (e.g. empty string)\n\n#### Testing:\n\n* checking for ResponseCode==400\n \n\n#### Clearing:\n\n* not applicable" + }, { - "name": "Service Idempotent?", + "name": "response header completeness", "item": [ { - "name": "Expected /v1/inform-about-release-history - service idempotent?", + "name": "Expected /v1/inform-about-application response header parameter completeness", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history integration -- is service idempotent? -------------------------------\");\r", + "console.log(\"\\n----- /v1/inform-about-application integration -- response header completeness -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -11075,7 +10871,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -11143,10 +10939,9 @@ "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var response;\r", "try {\r", - " let response;\r", " response = pm.response;\r", - "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", "} catch (error) {\r", @@ -11158,9 +10953,21 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/inform-about-release-history responds 200\", function () {\r", + " pm.test(\"POST /v1/inform-about-application responds 200\", function () {\r", " pm.expect(RESPONSE_CODE).to.equal(200);\r", " });\r", + " pm.test(\"Response headers contain 'x-correlator'\", function () {\r", + " response.to.have.header(\"x-correlator\");\r", + " });\r", + " pm.test(\"Response headers contain 'exec-time'\", function () {\r", + " response.to.have.header(\"exec-time\");\r", + " });\r", + " pm.test(\"Response headers contain 'backend-time'\", function () {\r", + " response.to.have.header(\"backend-time\");\r", + " });\r", + " pm.test(\"Response headers contain 'life-cycle-state'\", function () {\r", + " response.to.have.header(\"life-cycle-state\");\r", + " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", @@ -11205,26 +11012,26 @@ "response": [] } ], - "description": "## Is service idempotent?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200(not 400 because of idempotence)\"\n \n\n#### Clearing:\n\n* not applicable" + "description": "## Contains response complete set of headers?\n\n#### Preparation:\n\n* POST /v1/inform-about-application\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for ResponseHeaders (x-correlator, exec-time, backend-time and life-cycle-state) being present and checking for correctness of type of each parameter.\n \n\n#### Clearing:\n\n* not applicable" }, { - "name": "request header parameter completeness", + "name": "x-correlator responded?", "item": [ { - "name": "Expected /v1/inform-about-release-history - request header parameter completeness", + "name": "Expected /v1/inform-about-application correct x-correlator responded?", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history integration -- request headers parameters completeness -------------------------------\");\r", + "console.log(\"\\n----- /v1/inform-about-application integration -- x-correlator responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", - "\r", + " \r", "} catch (error) {\r", " console.log(error);\r", " console.log(\"! Input Data could not be loaded.\");\r", @@ -11258,17 +11065,27 @@ "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", + "\r", "/****************************************************************************************\r", "* Setting Collection Variables\r", "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"user\", USER_NAME);\r", + " pm.collectionVariables.set(\"originator\", ORIGINATOR);\r", + " pm.collectionVariables.set(\"xCorrelator\", X_CORRELATOR);\r", + " pm.collectionVariables.set(\"traceIndicator\", TRACE_INDICATOR);\r", + " pm.collectionVariables.set(\"customerJourney\", CUSTOMER_JOURNEY);\r", "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -11276,12 +11093,6 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", - " let parameters;\r", - " parameters = [\"user\", \"originator\", \"x-correlator\", \"trace-indicator\", \"customer-journey\"];\r", - "\r", - " let missingParameter;\r", - " missingParameter = GetMissingParameter(parameters);\r", - "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", @@ -11296,8 +11107,6 @@ " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", - " pm.request.headers.remove(missingParameter);\r", - "\r", "} catch (error) {\r", " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", @@ -11326,12 +11135,7 @@ " }\r", " return randomRandomHexString.substring(0,length);\r", "}\r", - "\r", - "function GetMissingParameter(parameters) {\r", - " let missingParameter;\r", - " missingParameter = parameters[Math.floor(Math.random()*parameters.length)];\r", - " return missingParameter;\r", - "}" + "" ], "type": "text/javascript" } @@ -11343,18 +11147,30 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var expectedXCorrelator;\r", + "try {\r", + " expectedXCorrelator = pm.collectionVariables.get(\"xCorrelator\");\r", + " \r", + "} catch(error) {\r", + " console.log(\"! Could not load input data. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "var actualXCorrelator;\r", "try {\r", " let response;\r", " response = pm.response;\r", - "\r", + " \r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + " \r", + " actualXCorrelator = RESPONSE_HEADERS.get(\"x-correlator\");\r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -11364,8 +11180,11 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of missing parameter\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " pm.test(\"POST /v1/inform-about-application responds 200\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(200);\r", + " });\r", + " pm.test(\"Provides expected x-correlator: \" + expectedXCorrelator, function () {\r", + " pm.expect(actualXCorrelator).to.equal(expectedXCorrelator);\r", " });\r", "\r", "} catch (error) {\r", @@ -11388,7 +11207,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "400", + "value": "200", "type": "default" } ], @@ -11411,19 +11230,19 @@ "response": [] } ], - "description": "## Get parameters checked for completeness?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history\n * all parameters with realistic values, BUT one randomly chosen parameter (user, originator, x-correlator, trace-indicator or customer-journey) missing (not empty string!)\n\n#### Testing:\n\n* checking for ResponseCode == 400\n \n\n#### Clearing:\n\n* not applicable" + "description": "## Is the initial x-correlator ín the response?\n\n#### Preparation:\n\n* POST /v1/inform-about-application\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for response headers containing x-correlator==dummyXCorrelator\n \n\n#### Clearing:\n\n* not applicable" }, { - "name": "originator parameter correctness", + "name": "life-cycle-state responded?", "item": [ { - "name": "Expected /v1/inform-about-release-history too short originator", + "name": "reference /core-model-1-4:control-construct", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- originator parameter correctness check - length too short -------------------------------\");\r", + "console.log(\"\\n----- /v1/inform-about-application integration -- life-cycle-state responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -11432,41 +11251,8 @@ " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var FAULTY_ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " FAULTY_ORIGINATOR = GenerateFaultyOriginator();\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = \"\";\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", + " console.log(\"! Environment variables could not be loaded.\");\r", "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", "\r", "\r", "/****************************************************************************************\r", @@ -11474,7 +11260,13 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -11482,22 +11274,18 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", + "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:FAULTY_ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -11505,51 +11293,7 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function GenerateFaultyOriginator() {\r", - " let faultyOriginator;\r", - " let length;\r", - " let minLength;\r", - " minLength = 0;\r", - " let maxLength;\r", - " maxLength = 2;\r", - " length = Math.floor(Math.random() * maxLength) + minLength;\r", - " faultyOriginator = GenerateRandomString(length);\r", - " return faultyOriginator;\r", - "}\r", - "\r", - "function GenerateRandomString(length) {\r", - " let randomString;\r", - " randomString = \"\";\r", - " try {\r", - " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", - " let charactersLength = characters.length;\r", - " for (let i = 0; i < length; i++) {\r", - " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", - " }\r", - " } catch (error) {\r", - " console.log(\"! Could not generate random string. \");\r", - " }\r", - " return randomString;\r", - "}\r", - "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}\r", "" ], "type": "text/javascript" @@ -11567,28 +11311,47 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", "\r", - " RESPONSE_CODE = parseInt(response.code);\r", + " } else {\r", + " ltpList = [];\r", + " }\r", "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/inform-about-application\", ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of faulty originator parameter(too short string)\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", "\r", @@ -11596,19 +11359,46 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", + " return alternativeLifeCycleState;\r", "}\r", "" ], @@ -12960,16 +13305,16 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", - "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var response;\r", "try {\r", + " let response;\r", " response = pm.response;\r", + " \r", " RESPONSE_CODE = parseInt(response.code);\r", - "\r", + " \r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -12979,27 +13324,14 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/inform-about-release-history responds 200\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(200);\r", - " });\r", - " pm.test(\"Response headers contain 'x-correlator'\", function () {\r", - " response.to.have.header(\"x-correlator\");\r", - " });\r", - " pm.test(\"Response headers contain 'exec-time'\", function () {\r", - " response.to.have.header(\"exec-time\");\r", - " });\r", - " pm.test(\"Response headers contain 'backend-time'\", function () {\r", - " response.to.have.header(\"backend-time\");\r", - " });\r", - " pm.test(\"Response headers contain 'life-cycle-state'\", function () {\r", - " response.to.have.header(\"life-cycle-state\");\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -13011,12 +13343,12 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "x-mock-response-code", - "value": "200", - "type": "default" + "value": "204", + "type": "text" } ], "body": { @@ -13036,28 +13368,21 @@ } }, "response": [] - } - ], - "description": "## Contains response complete set of headers?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for ResponseHeaders (x-correlator, exec-time, backend-time and life-cycle-state) being present and checking for correctness of type of each parameter.\n \n\n#### Clearing:\n\n* not applicable" - }, - { - "name": "x-correlator responded?", - "item": [ + }, { - "name": "Expected /v1/inform-about-release-history correct x-correlator responded?", + "name": "Expected /v1/inform-about-application", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history integration -- x-correlator responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", - " \r", + "\r", "} catch (error) {\r", " console.log(error);\r", " console.log(\"! Input Data could not be loaded.\");\r", @@ -13091,27 +13416,17 @@ "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", - "\r", "/****************************************************************************************\r", "* Setting Collection Variables\r", "****************************************************************************************/\r", - "try {\r", - " pm.collectionVariables.set(\"user\", USER_NAME);\r", - " pm.collectionVariables.set(\"originator\", ORIGINATOR);\r", - " pm.collectionVariables.set(\"xCorrelator\", X_CORRELATOR);\r", - " pm.collectionVariables.set(\"traceIndicator\", TRACE_INDICATOR);\r", - " pm.collectionVariables.set(\"customerJourney\", CUSTOMER_JOURNEY);\r", "\r", - "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", - "}\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -13160,8 +13475,7 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}\r", - "" + "}" ], "type": "text/javascript" } @@ -13173,29 +13487,34 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedXCorrelator;\r", + "var expectedLifeCycleState;\r", "try {\r", - " expectedXCorrelator = pm.collectionVariables.get(\"xCorrelator\");\r", - " \r", - "} catch(error) {\r", - " console.log(\"! Could not load input data. \");\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", + "\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var actualXCorrelator;\r", + "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", " let RESPONSE_HEADERS;\r", " RESPONSE_HEADERS = pm.response.headers; \r", - " \r", - " actualXCorrelator = RESPONSE_HEADERS.get(\"x-correlator\");\r", + "\r", + " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", @@ -13206,11 +13525,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/inform-about-release-history responds 200\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(200);\r", - " });\r", - " pm.test(\"Provides expected x-correlator: \" + expectedXCorrelator, function () {\r", - " pm.expect(actualXCorrelator).to.equal(expectedXCorrelator);\r", + " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", + " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", " });\r", "\r", "} catch (error) {\r", @@ -13234,7 +13550,7 @@ { "key": "x-mock-response-code", "value": "200", - "type": "default" + "type": "text" } ], "body": { @@ -13254,42 +13570,48 @@ } }, "response": [] - } - ], - "description": "## Is the initial x-correlator ín the response?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for response headers containing x-correlator==dummyXCorrelator\n \n\n#### Clearing:\n\n* not applicable" - }, - { - "name": "life-cycle-state responded?", - "item": [ + }, { - "name": "reference /core-model-1-4:control-construct", + "name": "Initial life-cycle-state", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history integration -- life-cycle-state responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", + "var operationServerUuid;\r", + "var initialLifeCycleState;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + "\r", + " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "\r", + " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "\r", "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", + " console.log(\"! Input Data could not be loaded.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + " URI = APPLICATION.serverUrl \r", + " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", + " + operationServerUuid\r", + " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", "\r", " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", + " + ' }';\r", "\r", " let AUTHORIZATION;\r", " AUTHORIZATION = APPLICATION.authorizationCode;\r", @@ -13300,16 +13622,15 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", - "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", + " \r", " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", "\r", "} catch (error) {\r", " console.log(\"! Local variables could not be set.\");\r", @@ -13337,47 +13658,28 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var ltpList;\r", + "var RESPONSE_CODE;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", + " RESPONSE_CODE = parseInt(response.code);\r", " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var currentOperationServer;\r", - "try {\r", - " currentOperationServer = FindOperationServer(\"/v1/inform-about-release-history\", ltpList);\r", - "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Setting Collection Variables\r", + "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.clear();\r", - " \r", - " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", + " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", "\r", "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", + " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", "\r", @@ -13385,45 +13687,18 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function FindOperationServer(operationName, ltpList) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i= 0; expectedReleaseIndex--) {\r", - "\r", - " let expectedReleaseNumber;\r", - " expectedReleaseNumber = expectedReleaseList[expectedReleaseIndex][\"release-number\"];\r", - " let actualReleaseInstance;\r", - " actualReleaseInstance = FindActualReleaseInstanceFor(expectedReleaseNumber, actualReleaseList);\r", - " pm.test(\"Invariant release number '\" + expectedReleaseNumber + \"' could be found\", function () {\r", - " pm.expect(actualReleaseInstance).to.not.be.an('undefined');\r", - " pm.expect(Object.keys(actualReleaseInstance).length).to.not.equal(0);\r", - " });\r", - "\r", - " if ( actualReleaseInstance != undefined ) {\r", - "\r", - " let expectedReleaseDate;\r", - " expectedReleaseDate = expectedReleaseList[expectedReleaseIndex][\"release-date\"];\r", - " let actualReleaseDate;\r", - " try {\r", - " actualReleaseDate = actualReleaseInstance[\"release-date\"];\r", - " } catch (error) {\r", - " actualReleaseDate = \"\";\r", - " }\r", - " pm.test(\"Provides invariant release date '\" + expectedReleaseDate + \"'\", function () {\r", - " pm.expect(actualReleaseDate).to.equal(expectedReleaseDate);\r", - " });\r", - "\r", - " let expectedChanges;\r", - " expectedChanges = expectedReleaseList[expectedReleaseIndex][\"changes\"];\r", - " let actualChanges;\r", - " try {\r", - " actualChanges = actualReleaseInstance[\"changes\"];\r", - " } catch (error) {\r", - " actualChanges = \"\";\r", - " }\r", - " pm.test(\"Provides invariant changes '\" + expectedChanges + \"'\", function () {\r", - " pm.expect(actualChanges).to.equal(expectedChanges);\r", - " });\r", - " }\r", - "\r", - " }\r", - "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", @@ -14880,37 +14985,8 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function FindHttpServerLtp(ltpList) {\r", - " let httpServerLtp;\r", - " httpServerLtp = {};\r", - " try {\r", - " for( let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + "function GenerateFaultyTraceIndicator() {\r", + " let traceIndicator;\r", + " traceIndicator = \"\";\r", + "\r", + " let traceIndicatorParts;\r", + " traceIndicatorParts = [];\r", + " for(let i=0; i<3; i++) {\r", + " traceIndicatorParts[i] = Math.floor(Math.random() * 10);\r", " }\r", + " let characters;\r", + " characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength;\r", + " charactersLength = characters.length;\r", + " let faultyElement;\r", + " faultyElement = characters.charAt(Math.floor(Math.random() * charactersLength));\r", "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + " let faultyTraceIndicatorPart;\r", + " faultyTraceIndicatorPart = Math.floor(Math.random() * 3);\r", "\r", - " return alternativeLifeCycleState;\r", + " traceIndicatorParts[faultyTraceIndicatorPart] = faultyElement;\r", + " traceIndicator = traceIndicatorParts.join(\".\");\r", + "\r", + " return traceIndicator;\r", + "}\r", + "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", "}\r", "" ], @@ -15251,6 +15368,7 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", @@ -15258,9 +15376,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -15270,14 +15388,15 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"As expected, POST /v1/inform-about-application-in-generic-representation responds 400, because of presence of letters in trace-indicator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -15289,11 +15408,11 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", + "value": "400", "type": "text" } ], @@ -15316,12 +15435,13 @@ "response": [] }, { - "name": "expected /v1/inform-about-release-history", + "name": "Expected /v1/inform-about-application-in-generic-representation with incorrect separator trace-indicator", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- trace-indicator parameter correctness check - incorrect separator -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -15340,16 +15460,17 @@ "var USER_NAME;\r", "var ORIGINATOR;\r", "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", + "var FAULTY_TRACE_INDICATOR;\r", "var CUSTOMER_JOURNEY;\r", "try {\r", " USER_NAME = APPLICATION.userName;\r", " ORIGINATOR = \"Postman\";\r", " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", + " FAULTY_TRACE_INDICATOR = GenerateFaultyTraceIndicator();\r", " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", " \r", "} catch (error) {\r", + " console.log(error)\r", " console.log(\"! Could not define dummy values for parameters. \");\r", "}\r", "\r", @@ -15372,7 +15493,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application-in-generic-representation\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -15388,14 +15509,13 @@ " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:FAULTY_TRACE_INDICATOR});\r", " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -15403,6 +15523,27 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function GenerateFaultyTraceIndicator() {\r", + " let traceIndicator;\r", + " traceIndicator = \"\";\r", + "\r", + " let traceIndicatorParts;\r", + " traceIndicatorParts = [];\r", + " for(let i=0; i<3; i++) {\r", + " traceIndicatorParts[i] = Math.floor(Math.random() * 10);\r", + " }\r", + " let separators;\r", + " separators = \"-:;/\";\r", + " let separatorsLength;\r", + " separatorsLength = separators.length;\r", + "\r", + " let faultySeparator;\r", + " faultySeparator = separators.charAt(Math.floor(Math.random() * separatorsLength));\r", + "\r", + " traceIndicator = traceIndicatorParts.join(faultySeparator);\r", + "\r", + " return traceIndicator;\r", + "}\r", "\r", "function CreateXCorrelator() {\r", " let xCorrelator;\r", @@ -15421,7 +15562,8 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}" + "}\r", + "" ], "type": "text/javascript" } @@ -15433,35 +15575,18 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedLifeCycleState;\r", - "try {\r", - " let dummyLifeCycleState;\r", - " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", - "\r", - " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", - " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Could not load Input Data. \");\r", - "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", - " let RESPONSE_HEADERS;\r", - " RESPONSE_HEADERS = pm.response.headers; \r", - "\r", - " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", - "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -15471,8 +15596,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", - " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " pm.test(\"As expected, POST /v1/inform-about-application-in-generic-representation responds 400, because of incorrect separator in trace-indicator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -15495,7 +15620,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "200", + "value": "400", "type": "text" } ], @@ -15516,51 +15641,72 @@ } }, "response": [] - }, + } + ], + "description": "## Gets trace-indicator checked for complying the pattern?\n\n#### Preparation:\n\n* POST /v1/inform-about-application-in-generic-representation\n * all parameters with realistic values, BUT dummyTraceIndicator differing from the pattern in various ways (e.g. empty string)\n\n#### Testing:\n\n* checking for ResponseCode==400\n \n\n#### Clearing:\n\n* not applicable" + }, + { + "name": "response header completeness", + "item": [ { - "name": "Initial life-cycle-state", + "name": "Expected /v1/inform-about-application-in-generic-representation response header parameter completeness", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- /v1/inform-about-application-in-generic-representation integration -- response header completeness -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", - "var operationServerUuid;\r", - "var initialLifeCycleState;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - "\r", - " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", "\r", - " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "/****************************************************************************************\r", + "* Defining Dummy Parameters\r", + "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var X_CORRELATOR;\r", + "var TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", + "try {\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " X_CORRELATOR = CreateXCorrelator();\r", + " TRACE_INDICATOR = \"1\";\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", "} catch (error) {\r", - " console.log(\"! Input Data could not be loaded.\");\r", + " console.log(\"!Could not define request body. \");\r", "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl \r", - " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", - " + operationServerUuid\r", - " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = '{ '\r", - " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", - " + ' }';\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application-in-generic-representation\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -15572,13 +15718,18 @@ "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " \r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", + " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -15587,6 +15738,24 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", "" ], "type": "text/javascript" @@ -15605,12 +15774,11 @@ "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var response;\r", "try {\r", - " let response;\r", " response = pm.response;\r", - " \r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -15620,8 +15788,20 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"POST /v1/inform-about-application-in-generic-representation responds 200\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(200);\r", + " });\r", + " pm.test(\"Response headers contain 'x-correlator'\", function () {\r", + " response.to.have.header(\"x-correlator\");\r", + " });\r", + " pm.test(\"Response headers contain 'exec-time'\", function () {\r", + " response.to.have.header(\"exec-time\");\r", + " });\r", + " pm.test(\"Response headers contain 'backend-time'\", function () {\r", + " response.to.have.header(\"backend-time\");\r", + " });\r", + " pm.test(\"Response headers contain 'life-cycle-state'\", function () {\r", + " response.to.have.header(\"life-cycle-state\");\r", " });\r", "\r", "} catch (error) {\r", @@ -15640,12 +15820,12 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", - "type": "text" + "value": "200", + "type": "default" } ], "body": { @@ -15667,126 +15847,26 @@ "response": [] } ], - "description": "## Gets lifeCycleState propagated?\n\n#### Preparation:\n\n* GETing CC (/core-model-1-4:control-construct)\n* searching CC for op-s of /v1/inform-about-release-history, storing it\n* PUTting op-s-configuration/life-cycle-state with random alternative value\n* POST /v1/inform-about-release-history\n * all parameters with reasonable values\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n \n\n#### Clearing:\n\n* PUTting op-s-configuration/life-cycle-state back to original value" - } - ] - }, - { - "name": "Exit", - "item": [ - { - "name": "for exiting /v1/inform-about-release-history", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var URI;\r", - "try {\r", - " URI = pm.environment.get(\"dummyUri\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Loading Input Data failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Updating Environmental Variables and Determining the next Step\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " pm.variables.clear();\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = \"\";\r", - "\r", - " let OPERATION_KEY;\r", - " OPERATION_KEY = \"\";\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - " pm.request.headers.upsert({key:\"operationKey\", value:OPERATION_KEY});\r", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:\"application/json\"});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Setting Local Variables and Preparing the Request failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "/v1/inform-about-release-history-in-generic-representation", - "item": [ - { - "name": "Continuous Integration", - "item": [ + "description": "## Contains response complete set of headers?\n\n#### Preparation:\n\n* POST /v1/inform-about-application-in-generic-representation\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for ResponseHeaders (x-correlator, exec-time, backend-time and life-cycle-state) being present and checking for correctness of type of each parameter.\n \n\n#### Clearing:\n\n* not applicable" + }, { - "name": "Service Idempotent?", + "name": "x-correlator responded?", "item": [ { - "name": "Expected /v1/inform-about-release-history-in-generic-representation - service idempotent?", + "name": "Expected /v1/inform-about-application-in-generic-representation correct x-correlator responded?", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history-in-generic-representation integration -- is service idempotent? -------------------------------\");\r", + "console.log(\"\\n----- /v1/inform-about-application-in-generic-representation integration -- x-correlator responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", - "\r", + " \r", "} catch (error) {\r", " console.log(error);\r", " console.log(\"! Input Data could not be loaded.\");\r", @@ -15820,17 +15900,27 @@ "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", + "\r", "/****************************************************************************************\r", "* Setting Collection Variables\r", "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"user\", USER_NAME);\r", + " pm.collectionVariables.set(\"originator\", ORIGINATOR);\r", + " pm.collectionVariables.set(\"xCorrelator\", X_CORRELATOR);\r", + " pm.collectionVariables.set(\"traceIndicator\", TRACE_INDICATOR);\r", + " pm.collectionVariables.set(\"customerJourney\", CUSTOMER_JOURNEY);\r", "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history-in-generic-representation\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-application-in-generic-representation\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -15892,18 +15982,30 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "\r", + "var expectedXCorrelator;\r", + "try {\r", + " expectedXCorrelator = pm.collectionVariables.get(\"xCorrelator\");\r", + " \r", + "} catch(error) {\r", + " console.log(\"! Could not load input data. \");\r", + "}\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var actualXCorrelator;\r", "try {\r", " let response;\r", " response = pm.response;\r", - "\r", + " \r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + " \r", + " actualXCorrelator = RESPONSE_HEADERS.get(\"x-correlator\");\r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -15913,9 +16015,12 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/inform-about-release-history-in-generic-representation responds 200\", function () {\r", + " pm.test(\"POST /v1/inform-about-application-in-generic-representation responds 200\", function () {\r", " pm.expect(RESPONSE_CODE).to.equal(200);\r", " });\r", + " pm.test(\"Provides expected x-correlator: \" + expectedXCorrelator, function () {\r", + " pm.expect(actualXCorrelator).to.equal(expectedXCorrelator);\r", + " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", @@ -15960,19 +16065,19 @@ "response": [] } ], - "description": "## Is service idempotent?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history-in-generic-representation\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200(not 400 because of idempotence)\"\n \n\n#### Clearing:\n\n* not applicable" + "description": "## Is the initial x-correlator ín the response?\n\n#### Preparation:\n\n* POST /v1/inform-about-application-in-generic-representation\n * reasonable parameters\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for response headers containing x-correlator==dummyXCorrelator\n \n\n#### Clearing:\n\n* not applicable" }, { - "name": "request header parameter completeness", + "name": "life-cycle-state responded?", "item": [ { - "name": "Expected /v1/inform-about-release-history-in-generic-representation- request header parameter completeness", + "name": "reference /core-model-1-4:control-construct", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/inform-about-release-history-in-generic-representation integration -- request headers parameters completeness -------------------------------\");\r", + "console.log(\"\\n----- /v1/inform-about-application-in-generic-representation integration -- life-cycle-state responded? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -15981,41 +16086,8 @@ " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = \"\";\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", + " console.log(\"! Environment variables could not be loaded.\");\r", "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", "\r", "\r", "/****************************************************************************************\r", @@ -16023,7 +16095,13 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history-in-generic-representation\";\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -16031,30 +16109,18 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", - " let parameters;\r", - " parameters = [\"user\", \"originator\", \"x-correlator\", \"trace-indicator\", \"customer-journey\"];\r", - "\r", - " let missingParameter;\r", - " missingParameter = GetMissingParameter(parameters);\r", "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", - " pm.request.headers.remove(missingParameter);\r", - "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -16063,30 +16129,7 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", - "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}\r", - "\r", - "function GetMissingParameter(parameters) {\r", - " let missingParameter;\r", - " missingParameter = parameters[Math.floor(Math.random()*parameters.length)];\r", - " return missingParameter;\r", - "}" + "" ], "type": "text/javascript" } @@ -16103,28 +16146,47 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", "\r", - " RESPONSE_CODE = parseInt(response.code);\r", + " } else {\r", + " ltpList = [];\r", + " }\r", "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/inform-about-application-in-generic-representation\", ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"As expected, POST /v1/inform-about-release-history-in-generic-representation responds 400, because of missing parameter\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", "\r", @@ -16132,19 +16194,46 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", "\r", + " return alternativeLifeCycleState;\r", + "}\r", "" ], "type": "text/javascript" @@ -18759,92 +19432,49 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", - "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var ltpList;\r", + "var RESPONSE_CODE;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", + " RESPONSE_CODE = parseInt(response.code);\r", " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var listRecordsOfFlowOperationKey;\r", - "try {\r", - " listRecordsOfFlowOperationKey = FindOperationKeyForOperationName(\"/v1/list-records-of-flow\", ltpList);\r", - "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Setting Collection Variables\r", + "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.set(\"listRecordsOfFlowOperationKey\", listRecordsOfFlowOperationKey);\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", "\r", "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", + " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function FindOperationKeyForOperationName(operationName, ltpList) {\r", - " let operationKey;\r", - " operationKey = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for ( let i=0; i= 0; expectedReleaseIndex--) {\r", - " let expectedReleaseNumber;\r", - " expectedReleaseNumber = expectedReleaseList[expectedReleaseIndex][\"release-number\"];\r", - " let actualReleaseInstance;\r", - " actualReleaseInstance = FindActualReleaseInstanceFor(expectedReleaseNumber, actualResponseValueList);\r", - " pm.test(\"Invariant field-name '\" + expectedReleaseNumber + \"' could be found\", function () {\r", - " pm.expect(actualReleaseInstance).to.not.be.an('undefined');\r", - " pm.expect(Object.keys(actualReleaseInstance).length).to.not.equal(0);\r", - " });\r", - " if(actualReleaseInstance != undefined) {\r", - " let expectedValue;\r", - " expectedValue = expectedReleaseList[expectedReleaseIndex][\"release-date\"] + \" - \" + expectedReleaseList[expectedReleaseIndex][\"changes\"];\r", - " let actualValue;\r", - " actualValue = actualReleaseInstance[\"value\"];\r", - " pm.test(\"Provides invariant value '\" + expectedValue + \"'\", function () {\r", - " pm.expect(actualValue).to.equal(expectedValue);\r", - " });\r", - " let actualDataType;\r", - " actualDataType = actualReleaseInstance[\"datatype\"];\r", - " pm.test(\"Provides invariant data type \", function () {\r", - " pm.expect(actualDataType).to.equal(\"String\");\r", - " });\r", - " }\r", - "\r", - " }\r", - " }\r", - "\r", - " // testcases for consequent-action-list\r", - "\r", - " var actualConsequentActionList;\r", - " actualConsequentActionList = {};\r", - " try {\r", - " actualConsequentActionList = RESPONSE[\"consequent-action-list\"];\r", - " } catch (error) {\r", - " actualConsequentActionList = undefined;\r", - " console.log(\"! Exception in retrieving actual consequent action list. \");\r", - " }\r", - "\r", - " pm.test(\"Consequent action list is present in response\" , function () {\r", - " pm.expect(actualConsequentActionList).to.not.equal(undefined);\r", - " });\r", - "\r", - " if (actualConsequentActionList != undefined) {\r", - " pm.test(\"As expected, no consequent actions are provided\", function () {\r", - " pm.expect(actualConsequentActionList.length).to.equal(0);\r", - " });\r", - " }\r", - "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", @@ -19716,37 +20106,8 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function FindHttpServerLtp(ltpList) {\r", - " let httpServerLtp;\r", - " httpServerLtp = {};\r", - " try {\r", - " for( let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + "function GenerateFaultyOriginator() {\r", + " let faultyOriginator;\r", + " let length;\r", + " let minLength;\r", + " minLength = 0;\r", + " let maxLength;\r", + " maxLength = 2;\r", + " length = Math.floor(Math.random() * maxLength) + minLength;\r", + " faultyOriginator = GenerateRandomString(length);\r", + " return faultyOriginator;\r", + "}\r", + "\r", + "function GenerateRandomString(length) {\r", + " let randomString;\r", + " randomString = \"\";\r", + " try {\r", + " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength = characters.length;\r", + " for (let i = 0; i < length; i++) {\r", + " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " }\r", + " } catch (error) {\r", + " console.log(\"! Could not generate random string. \");\r", " }\r", + " return randomString;\r", + "}\r", "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", "\r", - " return alternativeLifeCycleState;\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", "}\r", "" ], @@ -20087,6 +20499,7 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", @@ -20094,9 +20507,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -20106,14 +20519,15 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of faulty originator parameter(too short string)\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -20125,12 +20539,12 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", - "type": "text" + "value": "400", + "type": "default" } ], "body": { @@ -20150,14 +20564,22 @@ } }, "response": [] - }, + } + ], + "description": "## Gets originator checked for compliance with specification?\n\n#### Preparation:\n\n* POST /v1/inform-about-release-history\n * all parameters with realistic values, BUT\n 1. originator set to be a string of 0, 1 or 2 (random) letters length (too short).\n\n#### Testing:\n\n* checking for ResponseCode==400\n \n\n#### Clearing:\n\n* not applicable" + }, + { + "name": "x-correlator pattern", + "item": [ { - "name": "expected /v1/inform-about-release-history-in-generic-representation", + "name": "Expected /v1/inform-about-release-history with Too short x-correlator", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- /v1/inform-about-release-history integration -- x-correlator pattern correctness check -------------------------------\");\r", + "console.log(\"\\n----- x-correlator parameter correctness check - too short -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -20175,17 +20597,18 @@ "****************************************************************************************/\r", "var USER_NAME;\r", "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", + "var FAULTY_X_CORRELATOR;\r", "var TRACE_INDICATOR;\r", "var CUSTOMER_JOURNEY;\r", "try {\r", " USER_NAME = APPLICATION.userName;\r", " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", + " FAULTY_X_CORRELATOR = GenerateFaultyXCorrelator();\r", " TRACE_INDICATOR = \"1\";\r", " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", " \r", "} catch (error) {\r", + " console.log(error)\r", " console.log(\"! Could not define dummy values for parameters. \");\r", "}\r", "\r", @@ -20208,7 +20631,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history-in-generic-representation\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -20223,7 +20646,7 @@ "\r", " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:FAULTY_X_CORRELATOR});\r", " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", @@ -20231,7 +20654,6 @@ " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", - " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -20240,14 +20662,13 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function CreateXCorrelator() {\r", + "function GenerateFaultyXCorrelator() {\r", " let xCorrelator;\r", " xCorrelator = \"\";\r", " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", + " xCorrelator += GenerateRandomHexString(4);\r", " return xCorrelator;\r", "}\r", "\r", @@ -20257,7 +20678,8 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}" + "}\r", + "" ], "type": "text/javascript" } @@ -20269,35 +20691,18 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedLifeCycleState;\r", - "try {\r", - " let dummyLifeCycleState;\r", - " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", - "\r", - " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", - " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Could not load Input Data. \");\r", - "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", - " let RESPONSE_HEADERS;\r", - " RESPONSE_HEADERS = pm.response.headers; \r", - "\r", - " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", - "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -20307,8 +20712,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", - " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of too short x-correlator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -20331,7 +20736,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "200", + "value": "400", "type": "text" } ], @@ -20354,49 +20759,65 @@ "response": [] }, { - "name": "Initial life-cycle-state", + "name": "Expected /v1/inform-about-release-history with Too long x-correlator", "event": [ { "listen": "prerequest", "script": { "exec": [ + "console.log(\"\\n----- x-correlator parameter correctness check - too long -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", - "var operationServerUuid;\r", - "var initialLifeCycleState;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - "\r", - " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", "\r", - " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "/****************************************************************************************\r", + "* Defining Dummy Parameters\r", + "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var FAULTY_X_CORRELATOR;\r", + "var TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", + "try {\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " FAULTY_X_CORRELATOR = GenerateFaultyXCorrelator();\r", + " TRACE_INDICATOR = \"1\";\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", "} catch (error) {\r", - " console.log(\"! Input Data could not be loaded.\");\r", + " console.log(\"!Could not define request body. \");\r", "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl \r", - " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", - " + operationServerUuid\r", - " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = '{ '\r", - " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", - " + ' }';\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -20408,11 +20829,15 @@ "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " \r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:FAULTY_X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", " console.log(\"! Local variables could not be set.\");\r", @@ -20423,6 +20848,25 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function GenerateFaultyXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", "" ], "type": "text/javascript" @@ -20444,9 +20888,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - " \r", + "\r", " RESPONSE_CODE = parseInt(response.code);\r", - " \r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -20456,8 +20900,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of too long x-correlator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -20476,11 +20920,11 @@ } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "x-mock-response-code", - "value": "204", + "value": "400", "type": "text" } ], @@ -20501,121 +20945,15 @@ } }, "response": [] - } - ], - "description": "## Gets lifeCycleState propagated?\n\n#### Preparation:\n\n* GETing CC (/core-model-1-4:control-construct)\n* searching CC for op-s of /v1/inform-about-release-history-in-generic-representation, storing it\n* PUTting op-s-configuration/life-cycle-state with random alternative value\n* POST /v1/inform-about-release-history-in-generic-representation\n * all parameters with reasonable values\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n \n\n#### Clearing:\n\n* PUTting op-s-configuration/life-cycle-state back to original value" - } - ] - }, - { - "name": "Exit", - "item": [ - { - "name": "for exiting /v1/inform-about-release-history-in-generic-representation", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var URI;\r", - "try {\r", - " URI = pm.environment.get(\"dummyUri\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Loading Input Data failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Updating Environmental Variables and Determining the next Step\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " pm.variables.clear();\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = \"\";\r", - "\r", - " let OPERATION_KEY;\r", - " OPERATION_KEY = \"\";\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - " pm.request.headers.upsert({key:\"operationKey\", value:OPERATION_KEY});\r", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:\"application/json\"});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Setting Local Variables and Preparing the Request failed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "/v1/register-yourself", - "item": [ - { - "name": "Continuous Integration", - "item": [ - { - "name": "Service Idempotent?", - "item": [ { - "name": "reference /core-model-1-4:control-construct", + "name": "Expected /v1/inform-about-release-history with incorrect characters count x-correlator", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/register-yourself integration -- is service idempotent? -------------------------------\");\r", + "console.log(\"\\n----- x-correlator parameter correctness check - incorrect characters count -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -20624,22 +20962,50 @@ " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", + "* Defining Dummy Parameters\r", "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var FAULTY_X_CORRELATOR;\r", + "var TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " FAULTY_X_CORRELATOR = GenerateFaultyXCorrelator();\r", + " TRACE_INDICATOR = \"1\";\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", "\r", - " let REQUEST_BODY;\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -20647,13 +21013,16 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", - "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:FAULTY_X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", @@ -20667,6 +21036,37 @@ "* Functions\r", "****************************************************************************************/\r", "\r", + "function GenerateFaultyXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + "\r", + " let faultyElementLength;\r", + " faultyElementLength = Math.floor(Math.random() * 3) + 1;\r", + " let faultyElement;\r", + " faultyElement = GenerateRandomHexString(faultyElementLength);\r", + "\r", + " let xCorrelatorParts;\r", + " xCorrelatorParts = xCorrelator.split(\"-\");\r", + " let faultyXCorrelatorPart;\r", + " faultyXCorrelatorPart = Math.floor(Math.random() * xCorrelatorParts.length);\r", + "\r", + " xCorrelatorParts[faultyXCorrelatorPart] = faultyElement;\r", + " xCorrelator = xCorrelatorParts.join(\"-\");\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", "" ], "type": "text/javascript" @@ -20684,56 +21084,28 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var ltpList;\r", + "var RESPONSE_CODE;\r", "try {\r", " let response;\r", " response = pm.response;\r", - " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", - " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", "\r", - "var currentOperationServer;\r", - "var registryOfficeHttpClientLtp;\r", - "var registryOfficeTcpClientLtp;\r", - "var registerApplicationOperationClientLtp;\r", - "try {\r", - " currentOperationServer = FindOperationServer(\"/v1/register-yourself\", ltpList);\r", - " registryOfficeHttpClientLtp = FindHttpClientForApplicationName(\"RegistryOffice\", ltpList);\r", - " registryOfficeTcpClientLtp = FindServingLtp(registryOfficeHttpClientLtp, ltpList);\r", - " registerApplicationOperationClientLtp = FindOperationClientLtp(registryOfficeHttpClientLtp, ltpList, \"register-application\");\r", + " RESPONSE_CODE = parseInt(response.code);\r", "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Setting Collection Variables\r", + "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.clear();\r", - " \r", - " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"registryOfficeHttpClientLtp\", registryOfficeHttpClientLtp);\r", - " pm.collectionVariables.set(\"registryOfficeTcpClientLtp\", registryOfficeTcpClientLtp);\r", - " pm.collectionVariables.set(\"registerApplicationOperationClientLtp\", registerApplicationOperationClientLtp);\r", + " pm.test(\"As expected, POST /v1/inform-about-release-history responds 400, because of incorrect character count of x-correlator value) \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " });\r", "\r", "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", + " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", "\r", @@ -20741,120 +21113,18 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function FindOperationServer(operationName, ltpList) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i= 0; expectedReleaseIndex--) {\r", + "\r", + " let expectedReleaseNumber;\r", + " expectedReleaseNumber = expectedReleaseList[expectedReleaseIndex][\"release-number\"];\r", + " let actualReleaseInstance;\r", + " actualReleaseInstance = FindActualReleaseInstanceFor(expectedReleaseNumber, actualReleaseList);\r", + " pm.test(\"Invariant release number '\" + expectedReleaseNumber + \"' could be found\", function () {\r", + " pm.expect(actualReleaseInstance).to.not.be.an('undefined');\r", + " pm.expect(Object.keys(actualReleaseInstance).length).to.not.equal(0);\r", + " });\r", + "\r", + " if ( actualReleaseInstance != undefined ) {\r", + "\r", + " let expectedReleaseDate;\r", + " expectedReleaseDate = expectedReleaseList[expectedReleaseIndex][\"release-date\"];\r", + " let actualReleaseDate;\r", + " try {\r", + " actualReleaseDate = actualReleaseInstance[\"release-date\"];\r", + " } catch (error) {\r", + " actualReleaseDate = \"\";\r", + " }\r", + " pm.test(\"Provides invariant release date '\" + expectedReleaseDate + \"'\", function () {\r", + " pm.expect(actualReleaseDate).to.equal(expectedReleaseDate);\r", + " });\r", + "\r", + " let expectedChanges;\r", + " expectedChanges = expectedReleaseList[expectedReleaseIndex][\"changes\"];\r", + " let actualChanges;\r", + " try {\r", + " actualChanges = actualReleaseInstance[\"changes\"];\r", + " } catch (error) {\r", + " actualChanges = \"\";\r", + " }\r", + " pm.test(\"Provides invariant changes '\" + expectedChanges + \"'\", function () {\r", + " pm.expect(actualChanges).to.equal(expectedChanges);\r", + " });\r", + " }\r", + "\r", + " }\r", + "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", @@ -23058,8 +23853,37 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function FindHttpServerLtp(ltpList) {\r", + " let httpServerLtp;\r", + " httpServerLtp = {};\r", + " try {\r", + " for( let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", " }\r", - " let characters;\r", - " characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", - " let charactersLength;\r", - " charactersLength = characters.length;\r", - " let faultyElement;\r", - " faultyElement = characters.charAt(Math.floor(Math.random() * charactersLength));\r", - "\r", - " let faultyTraceIndicatorPart;\r", - " faultyTraceIndicatorPart = Math.floor(Math.random() * 3);\r", - "\r", - " traceIndicatorParts[faultyTraceIndicatorPart] = faultyElement;\r", - " traceIndicator = traceIndicatorParts.join(\".\");\r", - "\r", - " return traceIndicator;\r", - "}\r", "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", + " return alternativeLifeCycleState;\r", "}\r", "" ], @@ -23435,7 +24224,6 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", - "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", @@ -23443,9 +24231,9 @@ "try {\r", " let response;\r", " response = pm.response;\r", - "\r", + " \r", " RESPONSE_CODE = parseInt(response.code);\r", - "\r", + " \r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -23455,15 +24243,14 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"As expected, POST /v1/register-yourself responds 400, because of presence of letters in trace-indicator value) \", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", " });\r", "\r", "} catch (error) {\r", " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", @@ -23475,11 +24262,11 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "x-mock-response-code", - "value": "400", + "value": "204", "type": "text" } ], @@ -23502,26 +24289,19 @@ "response": [] }, { - "name": "Expected /v1/register-yourself with incorrect separator trace-indicator", + "name": "expected /v1/inform-about-release-history", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- trace-indicator parameter correctness check - incorrect separator -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", - "var OPERATION_KEY;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - " \r", - " OPERATION_KEY = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", - "\r", "} catch (error) {\r", " console.log(error);\r", " console.log(\"! Input Data could not be loaded.\");\r", @@ -23533,17 +24313,16 @@ "var USER_NAME;\r", "var ORIGINATOR;\r", "var X_CORRELATOR;\r", - "var FAULTY_TRACE_INDICATOR;\r", + "var TRACE_INDICATOR;\r", "var CUSTOMER_JOURNEY;\r", "try {\r", " USER_NAME = APPLICATION.userName;\r", " ORIGINATOR = \"Postman\";\r", " X_CORRELATOR = CreateXCorrelator();\r", - " FAULTY_TRACE_INDICATOR = GenerateFaultyTraceIndicator();\r", + " TRACE_INDICATOR = \"1\";\r", " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", " \r", "} catch (error) {\r", - " console.log(error)\r", " console.log(\"! Could not define dummy values for parameters. \");\r", "}\r", "\r", @@ -23566,7 +24345,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/register-yourself\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -23579,18 +24358,17 @@ " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", - "\r", " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:FAULTY_TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", "\r", "} catch (error) {\r", + " console.log(error);\r", " console.log(\"! Local variables could not be set.\");\r", "}\r", "\r", @@ -23598,27 +24376,6 @@ "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", - "function GenerateFaultyTraceIndicator() {\r", - " let traceIndicator;\r", - " traceIndicator = \"\";\r", - "\r", - " let traceIndicatorParts;\r", - " traceIndicatorParts = [];\r", - " for(let i=0; i<3; i++) {\r", - " traceIndicatorParts[i] = Math.floor(Math.random() * 10);\r", - " }\r", - " let separators;\r", - " separators = \"-:;/\";\r", - " let separatorsLength;\r", - " separatorsLength = separators.length;\r", - "\r", - " let faultySeparator;\r", - " faultySeparator = separators.charAt(Math.floor(Math.random() * separatorsLength));\r", - "\r", - " traceIndicator = traceIndicatorParts.join(faultySeparator);\r", - "\r", - " return traceIndicator;\r", - "}\r", "\r", "function CreateXCorrelator() {\r", " let xCorrelator;\r", @@ -23637,8 +24394,7 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}\r", - "" + "}" ], "type": "text/javascript" } @@ -23650,18 +24406,35 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", + "var expectedLifeCycleState;\r", + "try {\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", + "\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", + "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + "\r", + " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -23671,8 +24444,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"As expected, POST /v1/register-yourself responds 400, because of incorrect separator in trace-indicator value) \", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", + " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", " });\r", "\r", "} catch (error) {\r", @@ -23695,7 +24468,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "400", + "value": "200", "type": "text" } ], @@ -23716,42 +24489,48 @@ } }, "response": [] - } - ], - "description": "## Gets trace-indicator checked for complying the pattern?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/register-yourself storing operation-key\n- POST several /v1/register-yourself Requests with \n - operation-key from above\n - all parameters with realistic values, BUT dummyTraceIndicator differing from the pattern in various ways (e.g. empty string)\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" - }, - { - "name": "security key missing?", - "item": [ + }, { - "name": "reference /core-model-1-4:control-construct", + "name": "Initial life-cycle-state", "event": [ { "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/register-yourself integration -- securitykey missing? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", "var APPLICATION;\r", + "var operationServerUuid;\r", + "var initialLifeCycleState;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + "\r", + " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "\r", + " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "\r", "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", + " console.log(\"! Input Data could not be loaded.\");\r", "}\r", "\r", - "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + " URI = APPLICATION.serverUrl \r", + " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", + " + operationServerUuid\r", + " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", "\r", " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", + " + ' }';\r", "\r", " let AUTHORIZATION;\r", " AUTHORIZATION = APPLICATION.authorizationCode;\r", @@ -23762,16 +24541,15 @@ " let CONTENT_TYPE;\r", " CONTENT_TYPE = \"application/json\";\r", "\r", - "\r", " pm.variables.clear();\r", "\r", " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", + " \r", " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", "\r", " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", "\r", "} catch (error) {\r", " console.log(\"! Local variables could not be set.\");\r", @@ -23799,47 +24577,28 @@ "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var ltpList;\r", + "var RESPONSE_CODE;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", + " RESPONSE_CODE = parseInt(response.code);\r", " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var currentOperationServer;\r", - "try {\r", - " currentOperationServer = FindOperationServer(\"/v1/register-yourself\", ltpList);\r", - "\r", "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Setting Collection Variables\r", + "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.clear();\r", - " \r", - " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", + " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", "\r", "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", + " console.log(\"! Testing could not be executed.\");\r", "}\r", "\r", "\r", @@ -23847,45 +24606,18 @@ "* Functions\r", "****************************************************************************************/\r", "\r", - "function FindOperationServer(operationName, ltpList) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", - " }\r", - "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", "\r", - " return alternativeLifeCycleState;\r", - "}\r", "" ], "type": "text/javascript" @@ -26977,49 +27769,92 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " RESPONSE_CODE = parseInt(response.code);\r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " }\r", + "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var listRecordsOfFlowOperationKey;\r", + "try {\r", + " listRecordsOfFlowOperationKey = FindOperationKeyForOperationName(\"/v1/list-records-of-flow\", ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", - " });\r", + " pm.collectionVariables.set(\"listRecordsOfFlowOperationKey\", listRecordsOfFlowOperationKey);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function FindOperationKeyForOperationName(operationName, ltpList) {\r", + " let operationKey;\r", + " operationKey = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for ( let i=0; i= 0; expectedReleaseIndex--) {\r", + " let expectedReleaseNumber;\r", + " expectedReleaseNumber = expectedReleaseList[expectedReleaseIndex][\"release-number\"];\r", + " let actualReleaseInstance;\r", + " actualReleaseInstance = FindActualReleaseInstanceFor(expectedReleaseNumber, actualResponseValueList);\r", + " pm.test(\"Invariant field-name '\" + expectedReleaseNumber + \"' could be found\", function () {\r", + " pm.expect(actualReleaseInstance).to.not.be.an('undefined');\r", + " pm.expect(Object.keys(actualReleaseInstance).length).to.not.equal(0);\r", + " });\r", + " if(actualReleaseInstance != undefined) {\r", + " let expectedValue;\r", + " expectedValue = expectedReleaseList[expectedReleaseIndex][\"release-date\"] + \" - \" + expectedReleaseList[expectedReleaseIndex][\"changes\"];\r", + " let actualValue;\r", + " actualValue = actualReleaseInstance[\"value\"];\r", + " pm.test(\"Provides invariant value '\" + expectedValue + \"'\", function () {\r", + " pm.expect(actualValue).to.equal(expectedValue);\r", + " });\r", + " let actualDataType;\r", + " actualDataType = actualReleaseInstance[\"datatype\"];\r", + " pm.test(\"Provides invariant data type \", function () {\r", + " pm.expect(actualDataType).to.equal(\"String\");\r", + " });\r", + " }\r", + "\r", + " }\r", + " }\r", + "\r", + " // testcases for consequent-action-list\r", + "\r", + " var actualConsequentActionList;\r", + " actualConsequentActionList = {};\r", + " try {\r", + " actualConsequentActionList = RESPONSE[\"consequent-action-list\"];\r", + " } catch (error) {\r", + " actualConsequentActionList = undefined;\r", + " console.log(\"! Exception in retrieving actual consequent action list. \");\r", + " }\r", + "\r", + " pm.test(\"Consequent action list is present in response\" , function () {\r", + " pm.expect(actualConsequentActionList).to.not.equal(undefined);\r", + " });\r", + "\r", + " if (actualConsequentActionList != undefined) {\r", + " pm.test(\"As expected, no consequent actions are provided\", function () {\r", + " pm.expect(actualConsequentActionList.length).to.equal(0);\r", + " });\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function FindHttpServerLtp(ltpList) {\r", + " let httpServerLtp;\r", + " httpServerLtp = {};\r", + " try {\r", + " for( let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "expected /v1/inform-about-release-history-in-generic-representation", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -27746,23 +29204,7 @@ "****************************************************************************************/\r", "var REQUEST_BODY;\r", "try {\r", - " REQUEST_BODY = '{'\r", - " + '\"registry-office-application\" : ' + '\"' + registryOfficeApplication + '\",'\r", - " + '\"registry-office-application-release-number\" : ' + '\"' + registryOfficeApplicationReleaseNumber + '\",'\r", - " + '\"registration-operation\" : ' + '\"' + registrationOperation + '\",' \r", - " + '\"registry-office-address\" : ' + '\"' + registryOfficeAddress + '\",'\r", - " + '\"registry-office-port\" : ' + registryOfficePort\r", - " +'}';\r", - "\r", - " let attributes;\r", - " attributes = [\"registry-office-application\", \"registry-office-application-release-number\", \"registration-operation\", \"registry-office-address\", \"registry-office-port\"];\r", - " let missingAttribute;\r", - " missingAttribute = GetMissingAttribute(attributes);\r", - "\r", - " REQUEST_BODY = JSON.parse(REQUEST_BODY);\r", - " delete REQUEST_BODY[missingAttribute];\r", - " REQUEST_BODY = JSON.stringify(REQUEST_BODY);\r", - " \r", + " REQUEST_BODY = \"\";\r", "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", @@ -27776,7 +29218,7 @@ "****************************************************************************************/\r", "try {\r", " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/register-yourself\";\r", + " URI = APPLICATION.serverUrl + \"/v1/inform-about-release-history-in-generic-representation\";\r", "\r", " let ACCEPT;\r", " ACCEPT = \"application/json\";\r", @@ -27789,8 +29231,6 @@ " pm.variables.set(\"uri\", URI);\r", " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", "\r", - " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", - "\r", " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", @@ -27827,12 +29267,6 @@ " randomRandomHexString += Math.random().toString(16).substring(2);\r", " }\r", " return randomRandomHexString.substring(0,length);\r", - "}\r", - "\r", - "function GetMissingAttribute(attributes) {\r", - " let missingAttribute;\r", - " missingAttribute = attributes[Math.floor(Math.random()*attributes.length)];\r", - " return missingAttribute;\r", "}" ], "type": "text/javascript" @@ -27845,18 +29279,35 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", + "var expectedLifeCycleState;\r", + "try {\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", + "\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", + "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", + "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + "\r", + " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", + "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -27866,8 +29317,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/register-yourself responds 400, because of missing attribute\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", + " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", " });\r", "\r", "} catch (error) {\r", @@ -27890,8 +29341,157 @@ "header": [ { "key": "x-mock-response-code", - "value": "400", - "type": "default" + "value": "200", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Initial life-cycle-state", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var operationServerUuid;\r", + "var initialLifeCycleState;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + "\r", + " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "\r", + " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl \r", + " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", + " + operationServerUuid\r", + " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", + " + ' }';\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + " \r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" } ], "body": { @@ -27913,68 +29513,7515 @@ "response": [] } ], - "description": "## Get attributes checked for completeness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/register-yourself, storing operation-key\n- searching CC for http-c of RegistryOffice, its corresponding tcp-c and op-c of register-application, store them.\n- POST /v1/register-yourself with \n - all attributes according to chosen http-c, tcp-c and op-c, BUT one randomly chosen attribute missing\n -operation-key from above\n - all parameters with realistic values\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" - }, + "description": "## Gets lifeCycleState propagated?\n\n#### Preparation:\n\n* GETing CC (/core-model-1-4:control-construct)\n* searching CC for op-s of /v1/inform-about-release-history-in-generic-representation, storing it\n* PUTting op-s-configuration/life-cycle-state with random alternative value\n* POST /v1/inform-about-release-history-in-generic-representation\n * all parameters with reasonable values\n\n#### Testing:\n\n* checking for ResponseCode==200\n* checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n \n\n#### Clearing:\n\n* PUTting op-s-configuration/life-cycle-state back to original value" + } + ] + }, + { + "name": "Exit", + "item": [ { - "name": "Attribute correctness", + "name": "for exiting /v1/inform-about-release-history-in-generic-representation", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var URI;\r", + "try {\r", + " URI = pm.environment.get(\"dummyUri\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Loading Input Data failed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Updating Environmental Variables and Determining the next Step\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " pm.variables.clear();\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = \"\";\r", + "\r", + " let OPERATION_KEY;\r", + " OPERATION_KEY = \"\";\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + " pm.request.headers.upsert({key:\"operationKey\", value:OPERATION_KEY});\r", + " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:\"application/json\"});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Setting Local Variables and Preparing the Request failed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ] + } + ] + }, + { + "name": "/v1/register-yourself", + "item": [ + { + "name": "Continuous Integration", + "item": [ + { + "name": "Service Idempotent?", "item": [ { - "name": "registry-office-application-release-number checked?", - "item": [ + "name": "reference /core-model-1-4:control-construct", + "event": [ { - "name": "reference /core-model-1-4:control-construct", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- /v1/register-yourself acceptance -- registry-office-application-release-number attribute checked? -------------------------------\");\r", - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- /v1/register-yourself integration -- is service idempotent? -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var ltpList;\r", + "var fcList;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + " fcList = responseObject[\"core-model-1-4:control-construct\"][\"forwarding-domain\"][0][\"forwarding-construct\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " fcList = [];\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "var registryOfficeHttpClientLtp;\r", + "var registryOfficeTcpClientLtp;\r", + "var registerApplicationOperationClientLtp;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/register-yourself\", ltpList);\r", + "\r", + " let outputFcPortList;\r", + " outputFcPortList = FindOutputFcPortList(\"PromptForRegisteringCausesRegistrationRequest\", fcList);\r", + "\r", + " let randomOutputFcPort;\r", + " randomOutputFcPort = outputFcPortList[Math.floor(Math.random() * outputFcPortList.length)];\r", + "\r", + " let outputLtpUuid;\r", + " outputLtpUuid = randomOutputFcPort[\"logical-termination-point\"];\r", + "\r", + " registerApplicationOperationClientLtp = FindActualInstanceByUuid(outputLtpUuid, ltpList);\r", + " registryOfficeHttpClientLtp = FindServingLtp(registerApplicationOperationClientLtp, ltpList);\r", + " registryOfficeTcpClientLtp = FindServingLtp(registryOfficeHttpClientLtp, ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", + " pm.collectionVariables.set(\"registryOfficeHttpClientLtp\", registryOfficeHttpClientLtp);\r", + " pm.collectionVariables.set(\"registryOfficeTcpClientLtp\", registryOfficeTcpClientLtp);\r", + " pm.collectionVariables.set(\"registerApplicationOperationClientLtp\", registerApplicationOperationClientLtp);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Expected /v1/register-yourself", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var OPERATION_KEY;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + " \r", + " OPERATION_KEY = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Dummy Parameters\r", + "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var X_CORRELATOR;\r", + "var TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", + "try {\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " X_CORRELATOR = CreateXCorrelator();\r", + " TRACE_INDICATOR = \"1\";\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/v1/register-yourself\";\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var expectedLifeCycleState;\r", + "try {\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", + "\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "var actualLifeCycleState;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + "\r", + " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", + " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Initial life-cycle-state", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var operationServerUuid;\r", + "var initialLifeCycleState;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + "\r", + " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "\r", + " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl \r", + " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", + " + operationServerUuid\r", + " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", + " + ' }';\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + " \r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ], + "description": "## Gets lifeCycleState propagated?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- search for op-s of /v1/register-yourself and store it\n- PUTting op-s-configuration/life-cycle-state with random alternative value\n- POST /v1/register-yourself with \n - operation-key from above\n - all parameters with reasonable values\n\n#### Testing:\n- checking for ResponseCode==204\n- checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n\n#### Clearing:\n- PUTting op-s-configuration/life-cycle-state back to original value" + }, + { + "name": "Attribute completeness", + "item": [ + { + "name": "reference /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- /v1/register-yourself acceptance -- attribute completeness -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var ltpList;\r", + "var fcList;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + " fcList = responseObject[\"core-model-1-4:control-construct\"][\"forwarding-domain\"][0][\"forwarding-construct\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " fcList = [];\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "var registryOfficeHttpClientLtp;\r", + "var registryOfficeTcpClientLtp;\r", + "var registerApplicationOperationClientLtp;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/register-yourself\", ltpList);\r", + "\r", + " let outputFcPortList;\r", + " outputFcPortList = FindOutputFcPortList(\"PromptForRegisteringCausesRegistrationRequest\", fcList);\r", + "\r", + " let randomOutputFcPort;\r", + " randomOutputFcPort = outputFcPortList[Math.floor(Math.random() * outputFcPortList.length)];\r", + "\r", + " let outputLtpUuid;\r", + " outputLtpUuid = randomOutputFcPort[\"logical-termination-point\"];\r", + "\r", + " registerApplicationOperationClientLtp = FindActualInstanceByUuid(outputLtpUuid, ltpList);\r", + " registryOfficeHttpClientLtp = FindServingLtp(registerApplicationOperationClientLtp, ltpList);\r", + " registryOfficeTcpClientLtp = FindServingLtp(registryOfficeHttpClientLtp, ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", + " pm.collectionVariables.set(\"registryOfficeHttpClientLtp\", registryOfficeHttpClientLtp);\r", + " pm.collectionVariables.set(\"registryOfficeTcpClientLtp\", registryOfficeTcpClientLtp);\r", + " pm.collectionVariables.set(\"registerApplicationOperationClientLtp\", registerApplicationOperationClientLtp);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -110885,9 +121621,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -110920,26 +121654,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -111357,9 +122134,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -111392,26 +122167,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -111843,9 +122661,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -111878,28 +122694,68 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -112343,9 +123201,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -112378,26 +123234,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -113598,9 +124455,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -113633,26 +124488,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -114370,9 +125254,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -114405,26 +125287,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -114835,9 +125760,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -114870,26 +125793,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -115314,9 +126280,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -115349,26 +126313,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -115798,9 +126805,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -115833,26 +126838,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -116295,9 +127343,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -116330,26 +127376,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -116802,9 +127905,7 @@ " pm.collectionVariables.set(\"executionAndTraceLogHttpClientLtp\", executionAndTraceLogHttpClientLtp);\r", " pm.collectionVariables.set(\"executionAndTraceLogTcpClientLtp\", executionAndTraceLogTcpClientLtp);\r", " pm.collectionVariables.set(\"httpServerLtp\", httpServerLtp);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -116837,26 +127938,108 @@ " return operationServer;\r", "}\r", "\r", - "function FindHttpClientForApplicationName(applicationName, ltpList) {\r", - " let httpClientLtp;\r", - " httpClientLtp = {};\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -117853,9 +128998,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -117888,26 +129031,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -118673,9 +129859,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -118708,26 +129892,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0) {\r", + " let randomFcWithEndSubscriptionManagement;\r", + " randomFcWithEndSubscriptionManagement = fcListWithEndSubscriptionManagementPort[Math.floor(Math.random() * fcListWithEndSubscriptionManagementPort.length)];\r", + "\r", + " let randomSiblingManagementFcPortForEndSubscription;\r", + " randomSiblingManagementFcPortForEndSubscription = FindRandomSiblingManagementFcPort(operationServerUuid, randomFcWithEndSubscriptionManagement);\r", + "\r", + " randomSubscriptionOperationLtp = FindActualInstanceByUuid(randomSiblingManagementFcPortForEndSubscription[\"logical-termination-point\"], ltpList);\r", + " } else {\r", + " randomSubscriptionOperationLtp = {};\r", + " }\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -119164,9 +130391,7 @@ " pm.collectionVariables.clear();\r", " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"notifyDeregistrationsOperationServerLtp\", notifyDeregistrationsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyApprovalsOperationServerLtp\", notifyApprovalsOperationServerLtp);\r", - " pm.collectionVariables.set(\"notifyWithdrawnApprovalsOperationServerLtp\", notifyWithdrawnApprovalsOperationServerLtp);\r", + " pm.collectionVariables.set(\"randomSubscriptionOperationLtp\", randomSubscriptionOperationLtp);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -119199,26 +130424,67 @@ " return operationServer;\r", "}\r", "\r", - "function FindOperationServerLtp(ltpList, operationName) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", + "function FindFcListWithManagementPortUuid(uuid, fcList) {\r", + " let expectedfcList;\r", + " expectedfcList = [];\r", " try {\r", - " let sampleUuid;\r", - " for(let i=0; i -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", - " }\r", - "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", "\r", - " return alternativeLifeCycleState;\r", - "}\r", "" ], "type": "text/javascript" @@ -190086,49 +201493,92 @@ "* Loading Input Data\r", "****************************************************************************************/\r", "\r", + "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var ltpList;\r", "try {\r", " let response;\r", " response = pm.response;\r", " \r", - " RESPONSE_CODE = parseInt(response.code);\r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " }\r", + "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var listRecordsOfFlowOperationKey;\r", + "try {\r", + " listRecordsOfFlowOperationKey = FindOperationKeyForOperationName(\"/v1/list-records-of-flow\", ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", - " });\r", + " pm.collectionVariables.set(\"listRecordsOfFlowOperationKey\", listRecordsOfFlowOperationKey);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Collection variables could not be set.\");\r", "}\r", "\r", + "\r", "/****************************************************************************************\r", "* Functions\r", "****************************************************************************************/\r", + "function FindOperationKeyForOperationName(operationName, ltpList) {\r", + " let operationKey;\r", + " operationKey = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for ( let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Expected /v1/redirect-topology-change-information", "event": [ { "listen": "prerequest", @@ -190975,16 +202823,6 @@ " + '\"topology-application-address\" : ' + '\"' + topologyApplicationAddress + '\",'\r", " + '\"topology-application-port\" : ' + topologyApplicationPort\r", " +'}';\r", - "\r", - " let attributes;\r", - " attributes = [\"topology-application\", \"topology-application-release-number\", \"topology-operation-application-update\", \"topology-operation-ltp-update\", \"topology-operation-ltp-deletion\", \"topology-operation-fc-update\", \"topology-operation-fc-port-update\", \"topology-operation-fc-port-deletion\", \"topology-application-address\", \"topology-application-port\"];\r", - " let missingAttribute;\r", - " missingAttribute = GetMissingAttribute(attributes);\r", - "\r", - " REQUEST_BODY = JSON.parse(REQUEST_BODY);\r", - " delete REQUEST_BODY[missingAttribute];\r", - " REQUEST_BODY = JSON.stringify(REQUEST_BODY);\r", - "\r", "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", @@ -191050,12 +202888,7 @@ " }\r", " return randomRandomHexString.substring(0,length);\r", "}\r", - "\r", - "function GetMissingAttribute(attributes) {\r", - " let missingAttribute;\r", - " missingAttribute = attributes[Math.floor(Math.random()*attributes.length)];\r", - " return missingAttribute;\r", - "}" + "" ], "type": "text/javascript" } @@ -191067,1727 +202900,863 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", + "var expectedLifeCycleState;\r", "try {\r", - " let response;\r", - " response = pm.response;\r", - "\r", - " RESPONSE_CODE = parseInt(response.code);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", - "\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", "\r", - "/****************************************************************************************\r", - "* Testing\r", - "****************************************************************************************/\r", - "try {\r", - " pm.test(\"POST /v1/redirect-topology-change-information responds 400, because of missing attribute\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "400", - "type": "default" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ], - "description": "## Get attributes checked for completeness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/redirect-topology-change-information, storing operation-key\n- searching CC for http-c of ApplicationLayerTopology, its corresponding tcp-c and op-c of update-all-ltps-and-fcs, update-ltp, delete-ltp-and-dependents, update-fc, update-fc-port, delete-fc-port. store them\n- POST /v1/redirect-topology-change-information\n - all attributes according to chosen http-c, tcp-c and op-c, BUT one randomly chosen attribute missing\n -operation-key from above\n - reasonable parameters\n#### Testing:\n- checking for ResponseCode==400\n#### Clearing:\n- not applicable" - }, - { - "name": "Attribute correctness", - "item": [ - { - "name": "topology-application-release-number checked?", - "item": [ - { - "name": "reference /core-model-1-4:control-construct", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- /v1/redirect-topology-change-information acceptance -- topology-application-release-number attribute checked? -------------------------------\");\r", - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var ltpList;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", - " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var currentOperationServer;\r", - "var applicationLayerTopologyHttpClientLtp;\r", - "var applicationLayerTopologyTcpClientLtp;\r", - "var updateAllLtpsAndFcsOperationClientLtp;\r", - "var updateLtpOperationClientLtp;\r", - "var deleteLtpAndDependentsOperationClientLtp;\r", - "var updateFcOperationClientLtp;\r", - "var updateFcPortOperationClientLtp;\r", - "var deleteFcPortOperationClientLtp;\r", - "try {\r", - " currentOperationServer = FindOperationServer(\"/v1/redirect-topology-change-information\", ltpList);\r", - " applicationLayerTopologyHttpClientLtp = FindHttpClientForApplicationName(\"ApplicationLayerTopology\", ltpList);\r", - " applicationLayerTopologyTcpClientLtp = FindServingLtp(applicationLayerTopologyHttpClientLtp, ltpList);\r", - " updateAllLtpsAndFcsOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"update-all-ltps-and-fcs\");\r", - " updateLtpOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"update-ltp\");\r", - " deleteLtpAndDependentsOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"delete-ltp-and-dependents\");\r", - " updateFcOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"update-fc\");\r", - " updateFcPortOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"update-fc-port\");\r", - " deleteFcPortOperationClientLtp = FindOperationClientLtp(applicationLayerTopologyHttpClientLtp, ltpList, \"delete-fc-port\");\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", - "try {\r", - " pm.collectionVariables.clear();\r", - " \r", - " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"applicationLayerTopologyHttpClientLtp\", applicationLayerTopologyHttpClientLtp);\r", - " pm.collectionVariables.set(\"applicationLayerTopologyTcpClientLtp\", applicationLayerTopologyTcpClientLtp);\r", - " pm.collectionVariables.set(\"updateAllLtpsAndFcsOperationClientLtp\", updateAllLtpsAndFcsOperationClientLtp);\r", - " pm.collectionVariables.set(\"updateLtpOperationClientLtp\", updateLtpOperationClientLtp);\r", - " pm.collectionVariables.set(\"deleteLtpAndDependentsOperationClientLtp\", deleteLtpAndDependentsOperationClientLtp);\r", - " pm.collectionVariables.set(\"updateFcOperationClientLtp\", updateFcOperationClientLtp);\r", - " pm.collectionVariables.set(\"updateFcPortOperationClientLtp\", updateFcPortOperationClientLtp);\r", - " pm.collectionVariables.set(\"deleteFcPortOperationClientLtp\", deleteFcPortOperationClientLtp);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "function FindOperationServer(operationName, ltpList) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i= 5) {\r", - " operationLtpList.push(ltpList[i]);\r", - " }\r", - " }\r", - " }\r", - " if( operationLtpList.length > 0 ) {\r", - " const random = Math.floor(Math.random() * operationLtpList.length);\r", - " randomOperationLtp = operationLtpList[random];\r", - " }\r", - " } catch(error) {\r", - " console.log(error);\r", - " console.log(\"! Exception in function : FindRandomOperationLtp. \")\r", - " }\r", - " return randomOperationLtp;\r", - "}" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [ - { - "key": "x-mock-response-code", - "value": "200", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - }, - { - "name": "Expected /v1/update-operation-key - incorrect new-operation-key", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "var OPERATION_KEY;\r", - "var operationUuid;\r", - "var oldOperationKey;\r", - "var dummyNewOperationKey;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - " \r", - " OPERATION_KEY = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", - "\r", - " let operationLtp;\r", - " operationLtp = pm.collectionVariables.get(\"operationLtp\");\r", - "\r", - " operationUuid = operationLtp[\"uuid\"];\r", - "\r", - " let layerprotocolName;\r", - " layerprotocolName = operationLtp[\"layer-protocol\"][0][\"layer-protocol-name\"];\r", - "\r", - " if ( layerprotocolName.includes(\"operation-server\") ) {\r", - " oldOperationKey = operationLtp[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", - " } else {\r", - " oldOperationKey = operationLtp[\"layer-protocol\"][0][\"operation-client-interface-1-0:operation-client-interface-pac\"][\"operation-client-interface-configuration\"][\"operation-key\"];\r", - " }\r", - "\r", - " dummyNewOperationKey = FaultyOperationKey();\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = '{'\r", - " + '\"operation-uuid\" : ' + '\"' + operationUuid + '\",'\r", - " + '\"old-operation-key\" : ' + '\"' + oldOperationKey + '\",'\r", - " + '\"new-operation-key\" : ' + '\"' + dummyNewOperationKey + '\"' \r", - " +'}';\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", - "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/update-operation-key\";\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", - "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", - "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}\r", - "\r", - "function GenerateRandomString(length) {\r", - " let randomString;\r", - " randomString = \"\";\r", - " try {\r", - " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", - " let charactersLength = characters.length;\r", - " for (let i = 0; i < length; i++) {\r", - " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", - " }\r", - " } catch (error) {\r", - " console.log(\"! Could not generate random string. \");\r", - " }\r", - " return randomString;\r", - "}\r", - "\r", - "function FaultyOperationKey() {\r", - " let faultyOperationKey;\r", - " let length;\r", - " let minLength;\r", - " minLength = 0;\r", - " let maxLength;\r", - " maxLength = 4;\r", - " length = Math.floor(Math.random() * maxLength) + minLength;\r", - " faultyOperationKey = GenerateRandomString(length);\r", - " return faultyOperationKey;\r", - "}" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - "\r", - " RESPONSE_CODE = parseInt(response.code);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Testing\r", - "****************************************************************************************/\r", - "try {\r", - " pm.test(\"POST /v1/update-operation-key responds 400, because of incorrect new-operation-key\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "400", - "type": "default" - } + " delete REQUEST_BODY[missingAttribute];\r", + " REQUEST_BODY = JSON.stringify(REQUEST_BODY);\r", + "\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/v1/update-operation-key\";\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", + "\r", + "function GetMissingAttribute(attributes) {\r", + "\tlet missingAttribute;\r", + "\tmissingAttribute = attributes[Math.floor(Math.random()*attributes.length)];\r", + "\treturn missingAttribute;\r", + "}" ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"POST /v1/update-operation-key responds 400, because of missing attribute\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } } ], - "description": "## Get new-operation-key checked for correctness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/update-operation-key, storing operation-key\n- searching CC for random op-s, storing it\n- POST /v1/update-operation-key\n - all attributes(both old and new) according to chosen op-s,BUT new-operation-key attribute with random dummy value (string of length 0-4)\n -operation-key from above\n - reasonable parameters\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" + "request": { + "method": "POST", + "header": [ + { + "key": "x-mock-response-code", + "value": "400", + "type": "default" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] } - ] + ], + "description": "## Get attributes checked for completeness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/update-operation-key, storing operation-key\n- searching CC for random op-s, storing it\n- POST /v1/update-operation-key\n - all attributes(both old and new) according to chosen op-s , BUT one randomly chosen attribute missing\n -operation-key from above\n - reasonable parameters\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" }, { - "name": "Attribute configured?", + "name": "Attribute correctness", "item": [ { - "name": "new-operation-key updated?", + "name": "new-operation-key checked?", "item": [ { "name": "reference /core-model-1-4:control-construct", @@ -225739,7 +236947,7 @@ "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/update-operation-key acceptance -- new-operation-key attribute updated? -------------------------------\");\r", + "console.log(\"\\n----- /v1/update-operation-key acceptance -- new-operation-key attribute checked? -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -225809,7 +237017,6 @@ "* Extracting Result\r", "****************************************************************************************/\r", "var ltpList;\r", - "var fcList;\r", "try {\r", " let response;\r", " response = pm.response;\r", @@ -225821,11 +237028,9 @@ " let responseObject;\r", " responseObject = JSON.parse(response.stream);\r", " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - " fcList = responseObject[\"core-model-1-4:control-construct\"][\"forwarding-domain\"][0][\"forwarding-construct\"];\r", "\r", " } else {\r", " ltpList = [];\r", - " fcList = [];\r", " }\r", "\r", "} catch (error) {\r", @@ -225851,8 +237056,6 @@ " \r", " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", " pm.collectionVariables.set(\"operationLtp\", operationLtp);\r", - " pm.collectionVariables.set(\"ltpList\", ltpList);\r", - " pm.collectionVariables.set(\"fcList\", fcList);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -225955,7 +237158,7 @@ "response": [] }, { - "name": "Expected /v1/update-operation-key", + "name": "Expected /v1/update-operation-key - incorrect new-operation-key", "event": [ { "listen": "prerequest", @@ -225991,7 +237194,7 @@ " oldOperationKey = operationLtp[\"layer-protocol\"][0][\"operation-client-interface-1-0:operation-client-interface-pac\"][\"operation-client-interface-configuration\"][\"operation-key\"];\r", " }\r", "\r", - " dummyNewOperationKey = GenerateRandomString(12);\r", + " dummyNewOperationKey = FaultyOperationKey();\r", "\r", "} catch (error) {\r", " console.log(error);\r", @@ -226033,12 +237236,7 @@ "/****************************************************************************************\r", "* Setting Collection Variables\r", "****************************************************************************************/\r", - "try {\r", - " pm.collectionVariables.set(\"dummyOperationKey\", dummyNewOperationKey);\r", "\r", - "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", - "}\r", "\r", "/****************************************************************************************\r", "* Setting Local Variables and Preparing the Request\r", @@ -226111,6 +237309,18 @@ " console.log(\"! Could not generate random string. \");\r", " }\r", " return randomString;\r", + "}\r", + "\r", + "function FaultyOperationKey() {\r", + " let faultyOperationKey;\r", + " let length;\r", + " let minLength;\r", + " minLength = 0;\r", + " let maxLength;\r", + " maxLength = 4;\r", + " length = Math.floor(Math.random() * maxLength) + minLength;\r", + " faultyOperationKey = GenerateRandomString(length);\r", + " return faultyOperationKey;\r", "}" ], "type": "text/javascript" @@ -226144,8 +237354,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/update-operation-key responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " pm.test(\"POST /v1/update-operation-key responds 400, because of incorrect new-operation-key\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -226168,7 +237378,7 @@ "header": [ { "key": "x-mock-response-code", - "value": "204", + "value": "400", "type": "default" } ], @@ -226189,515 +237399,17 @@ } }, "response": [] - }, - { - "name": "Expected /core-model-1-4:control-construct", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var expectedOperationKey;\r", - "var initialOperationLtp;\r", - "try {\r", - " expectedOperationKey = pm.collectionVariables.get(\"dummyOperationKey\");\r", - " initialOperationLtp = pm.collectionVariables.get(\"operationLtp\");\r", - " \r", - "} catch(error) {\r", - " console.log(\"! Could not load input data. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var ltpList;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", - " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var actualOperationKey;\r", - "try {\r", - " let operationLtpUuid;\r", - " operationLtpUuid = initialOperationLtp[\"uuid\"];\r", - "\r", - " let actualOperationLtp;\r", - " actualOperationLtp = FindActualInstanceByUuid(operationLtpUuid, ltpList);\r", - "\r", - " let layerprotocolName;\r", - " layerprotocolName = actualOperationLtp[\"layer-protocol\"][0][\"layer-protocol-name\"];\r", - "\r", - " if ( layerprotocolName.includes(\"operation-server\") ) {\r", - " actualOperationKey = actualOperationLtp[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", - " } else {\r", - " actualOperationKey = actualOperationLtp[\"layer-protocol\"][0][\"operation-client-interface-1-0:operation-client-interface-pac\"][\"operation-client-interface-configuration\"][\"operation-key\"];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", - "\r", - "/****************************************************************************************\r", - "* Testing\r", - "****************************************************************************************/\r", - "try {\r", - " pm.test(\"Provides expected new-operation-key \" + expectedOperationKey, function () {\r", - " pm.expect(expectedOperationKey).to.equal(actualOperationKey);\r", - " });\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "function FindActualInstanceByUuid(expectedUuid, actualLtpList) {\r", - " let actualInstance;\r", - " actualInstance = {};\r", - " try {\r", - " for ( let i=0; i= 5) {\r", - " operationLtpList.push(ltpList[i]);\r", - " }\r", - " }\r", - " }\r", - " if( operationLtpList.length > 0 ) {\r", - " const random = Math.floor(Math.random() * operationLtpList.length);\r", - " randomOperationLtp = operationLtpList[random];\r", - " }\r", - " } catch(error) {\r", - " console.log(error);\r", - " console.log(\"! Exception in function : FindRandomOperationLtp. \")\r", - " }\r", - " return randomOperationLtp;\r", - "}\r", - "\r", - "function FindHttpClientForApplicationName(applicationName, ltpList) {\r", - " let httpClientLtp;\r", - " httpClientLtp = {};\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i= 5) {\r", + " operationLtpList.push(ltpList[i]);\r", + " }\r", + " }\r", + " }\r", + " if( operationLtpList.length > 0 ) {\r", + " const random = Math.floor(Math.random() * operationLtpList.length);\r", + " randomOperationLtp = operationLtpList[random];\r", + " }\r", + " } catch(error) {\r", + " console.log(error);\r", + " console.log(\"! Exception in function : FindRandomOperationLtp. \")\r", + " }\r", + " return randomOperationLtp;\r", + "}" ], "type": "text/javascript" } @@ -227175,6 +237604,9 @@ "disableBodyPruning": true }, "request": { + "auth": { + "type": "noauth" + }, "method": "GET", "header": [ { @@ -227202,7 +237634,7 @@ "response": [] }, { - "name": "sampling /v1/update-operation-key", + "name": "Expected /v1/update-operation-key", "event": [ { "listen": "prerequest", @@ -227213,18 +237645,12 @@ "****************************************************************************************/\r", "var APPLICATION;\r", "var OPERATION_KEY;\r", - "var CURRENT_ORIGINATOR;\r", "var operationUuid;\r", "var oldOperationKey;\r", "var dummyNewOperationKey;\r", "try {\r", " APPLICATION = pm.environment.get(\"application\");\r", "\r", - " let ltpList;\r", - " ltpList = APPLICATION[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - "\r", - " CURRENT_ORIGINATOR = FindHttpServerApplicationName(ltpList);\r", - "\r", " let currentOperationServer;\r", " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", " \r", @@ -227287,12 +237713,7 @@ "* Setting Collection Variables\r", "****************************************************************************************/\r", "try {\r", - " pm.collectionVariables.set(\"user\", USER_NAME);\r", - " pm.collectionVariables.set(\"originator\", ORIGINATOR);\r", - " pm.collectionVariables.set(\"xCorrelator\", X_CORRELATOR);\r", - " pm.collectionVariables.set(\"traceIndicator\", TRACE_INDICATOR);\r", - " pm.collectionVariables.set(\"customerJourney\", CUSTOMER_JOURNEY);\r", - " pm.collectionVariables.set(\"currentOriginator\", CURRENT_ORIGINATOR);\r", + " pm.collectionVariables.set(\"dummyOperationKey\", dummyNewOperationKey);\r", "\r", "} catch (error) {\r", " console.log(\"! Collection variables could not be set.\");\r", @@ -227369,20 +237790,6 @@ " console.log(\"! Could not generate random string. \");\r", " }\r", " return randomString;\r", - "}\r", - "\r", - "function FindHttpServerApplicationName(ltpList) {\r", - " let applicationName;\r", - " applicationName = \"\";\r", - " for( let i=0; i 0 ) {\r", + " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", + " randomHttpClientLtp = httpClientLtpList[random];\r", + " }\r", + " } catch( error ){\r", + " console.log(error);\r", + " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", + " }\r", + " return randomHttpClientLtp;\r", + "}\r", + "\r", + "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", + " let randomOperationClientLtp;\r", + " randomOperationClientLtp = {};\r", + " try{\r", + " let clientLtpUuidList;\r", + " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", + " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", + " let randomClientLtpUuid;\r", + " randomClientLtpUuid = clientLtpUuidList[random];\r", + " for( let i=0; i -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Expected /v1/update-operation-client", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var OPERATION_KEY;\r", + "var applicationName;\r", + "var applicationReleaseNumber;\r", + "var operationName;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + " \r", + " OPERATION_KEY = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", + "\r", + " let httpClientLtp;\r", + " httpClientLtp = pm.collectionVariables.get(\"httpClientLtp\");\r", + "\r", + " applicationName = httpClientLtp[\"layer-protocol\"][0][\"http-client-interface-1-0:http-client-interface-pac\"][\"http-client-interface-capability\"][\"application-name\"];\r", + " applicationReleaseNumber = httpClientLtp[\"layer-protocol\"][0][\"http-client-interface-1-0:http-client-interface-pac\"][\"http-client-interface-configuration\"][\"release-number\"];\r", + "\r", + " let operationClientLtp;\r", + " operationClientLtp = pm.collectionVariables.get(\"operationClientLtp\");\r", + "\r", + " operationName = operationClientLtp[\"layer-protocol\"][0][\"operation-client-interface-1-0:operation-client-interface-pac\"][\"operation-client-interface-configuration\"][\"operation-name\"];\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Dummy Parameters\r", + "****************************************************************************************/\r", + "var USER_NAME;\r", + "var ORIGINATOR;\r", + "var X_CORRELATOR;\r", + "var TRACE_INDICATOR;\r", + "var CUSTOMER_JOURNEY;\r", + "try {\r", + " USER_NAME = APPLICATION.userName;\r", + " ORIGINATOR = \"Postman\";\r", + " X_CORRELATOR = CreateXCorrelator();\r", + " TRACE_INDICATOR = \"1\";\r", + " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Could not define dummy values for parameters. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = '{'\r", + " + '\"application-name\" : ' + '\"' + applicationName + '\",'\r", + " + '\"application-release-number\" : ' + '\"' + applicationReleaseNumber + '\",'\r", + " + '\"old-operation-name\" : ' + '\"' + operationName + '\",' \r", + " + '\"new-operation-name\" : ' + '\"' + operationName + '\"'\r", + " +'}';\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/v1/update-operation-client\";\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", + "\r", + " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", + " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", + " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", + " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", + " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function CreateXCorrelator() {\r", + " let xCorrelator;\r", + " xCorrelator = \"\";\r", + " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", + " xCorrelator += GenerateRandomHexString(12);\r", + " return xCorrelator;\r", + "}\r", + "\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var expectedLifeCycleState;\r", + "try {\r", + " let dummyLifeCycleState;\r", + " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", + "\r", + " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", + " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "var actualLifeCycleState;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + " let RESPONSE_HEADERS;\r", + " RESPONSE_HEADERS = pm.response.headers; \r", + "\r", + " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", + " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "Initial life-cycle-state", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var operationServerUuid;\r", + "var initialLifeCycleState;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " let currentOperationServer;\r", + " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", + "\r", + " operationServerUuid = currentOperationServer[\"uuid\"];\r", + "\r", + " initialLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Input Data could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl \r", + " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", + " + operationServerUuid\r", + " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + initialLifeCycleState + '\"'\r", + " + ' }';\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + " \r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE}); \r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " RESPONSE_CODE = parseInt(response.code);\r", + " \r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"PUT Initial life-cycle-state responds 204 \", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(204);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] } - }, - "response": [] - } - ] - }, - { - "name": "Acceptance", - "item": [ + ], + "description": "## Gets lifeCycleState propagated?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/update-operation-client, storing operation-key\n- searching CC for set of already existing random http-c, tcp-c and one of its op-c, store them\n- PUTting op-s-configuration/life-cycle-state with random alternative value\n- POST /v1/update-operation-client\n - all attributes(both old and new) according to chosen http-c, tcp-c and op-c\n - operation-key from above\n - all parameters with reasonable values\n\n#### Testing:\n- checking for ResponseCode==204\n- checking for lifeCycleState being identical with alternative op-s-configuration/life-cycle-state\n\n#### Clearing:\n- PUTting op-s-configuration/life-cycle-state back to original value" + }, { - "name": "life-cycle-state propogated?", + "name": "Attribute completeness", "item": [ { "name": "reference /core-model-1-4:control-construct", @@ -234799,7 +245989,7 @@ "listen": "prerequest", "script": { "exec": [ - "console.log(\"\\n----- /v1/update-operation-client acceptance -- life-cycle-state propogated? -------------------------------\");\r", + "console.log(\"\\n----- /v1/update-operation-client acceptance -- attribute completeness -------------------------------\");\r", "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", @@ -235033,189 +246223,7 @@ "response": [] }, { - "name": "dummy life-cycle-state", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "var operationServerUuid;\r", - "var dummyLifeCycleState;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - " \r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - "\r", - " operationServerUuid = currentOperationServer[\"uuid\"];\r", - "\r", - " currentLifeCycleState = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"life-cycle-state\"];\r", - "\r", - " dummyLifeCycleState = GenerateDummyLifeCycleState(currentLifeCycleState);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Variables could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", - "try {\r", - " pm.collectionVariables.set(\"dummyLifeCycleState\", dummyLifeCycleState);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl \r", - " + \"/core-model-1-4:control-construct/logical-termination-point=\"\r", - " + operationServerUuid\r", - " + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/life-cycle-state\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = '{ '\r", - " + '\"operation-server-interface-1-0:life-cycle-state\": \"' + dummyLifeCycleState + '\"'\r", - " + ' }';\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(error)\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "function GenerateDummyLifeCycleState(currentLifeCycleState) {\r", - " let alternativeLifeCycleStateTypeList;\r", - " alternativeLifeCycleStateTypeList = [ \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_EXPERIMENTAL\",\r", - " \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_OPERATIONAL\",\r", - " \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_DEPRECATED\", \r", - " \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_OBSOLETE\",\r", - " \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_UNKNOWN\",\r", - " \"operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_NOT_YET_DEFINED\"\r", - " ];\r", - " let indexOfCurrentLifeCycleState;\r", - " indexOfCurrentLifeCycleState = alternativeLifeCycleStateTypeList.indexOf(currentLifeCycleState);\r", - " if (indexOfCurrentLifeCycleState > -1) {\r", - " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", - " }\r", - "\r", - " let alternativeLifeCycleState;\r", - " let alternativeLifeCycleStateTypeIndex;\r", - " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", - " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", - "\r", - " return alternativeLifeCycleState;\r", - "}\r", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - " \r", - " RESPONSE_CODE = parseInt(response.code);\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Testing\r", - "****************************************************************************************/\r", - "try {\r", - " pm.test(\"PUT dummy life-cycle-state responds 204\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(204);\r", - " });\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PUT", - "header": [ - { - "key": "x-mock-response-code", - "value": "204", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - }, - { - "name": "Expected /v1/update-operation-client", + "name": "Expected /v1/update-operation-client - attribute completeness", "event": [ { "listen": "prerequest", @@ -235240,7 +246248,7 @@ " let httpClientLtp;\r", " httpClientLtp = pm.collectionVariables.get(\"httpClientLtp\");\r", "\r", - " applicationName = httpClientLtp[\"layer-protocol\"][0][\"http-client-interface-1-0:http-client-interface-pac\"][\"http-client-interface-capability\"][\"application-name\"];\r", + " dummyApplicationName = GenerateRandomString(12);\r", " applicationReleaseNumber = httpClientLtp[\"layer-protocol\"][0][\"http-client-interface-1-0:http-client-interface-pac\"][\"http-client-interface-configuration\"][\"release-number\"];\r", "\r", " let operationClientLtp;\r", @@ -235278,11 +246286,21 @@ "var REQUEST_BODY;\r", "try {\r", " REQUEST_BODY = '{'\r", - " + '\"application-name\" : ' + '\"' + applicationName + '\",'\r", + " + '\"application-name\" : ' + '\"' + dummyApplicationName + '\",'\r", " + '\"application-release-number\" : ' + '\"' + applicationReleaseNumber + '\",'\r", " + '\"old-operation-name\" : ' + '\"' + operationName + '\",' \r", " + '\"new-operation-name\" : ' + '\"' + operationName + '\"'\r", " +'}';\r", + "\r", + " let attributes;\r", + " attributes = [\"application-name\", \"application-release-number\", \"old-operation-name\", \"new-operation-name\"];\r", + " let missingAttribute;\r", + " missingAttribute = GetMissingAttribute(attributes);\r", + "\r", + " REQUEST_BODY = JSON.parse(REQUEST_BODY);\r", + " delete REQUEST_BODY[missingAttribute];\r", + " REQUEST_BODY = JSON.stringify(REQUEST_BODY);\r", + "\r", "} catch (error) {\r", " console.log(\"!Could not define request body. \");\r", "}\r", @@ -235348,7 +246366,27 @@ " }\r", " return randomRandomHexString.substring(0,length);\r", "}\r", - "" + "\r", + "function GenerateRandomString(length) {\r", + " let randomString;\r", + " randomString = \"\";\r", + " try {\r", + " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength = characters.length;\r", + " for (let i = 0; i < length; i++) {\r", + " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " }\r", + " } catch (error) {\r", + " console.log(\"! Could not generate random string. \");\r", + " }\r", + " return randomString;\r", + "}\r", + "\r", + "function GetMissingAttribute(attributes) {\r", + "\tlet missingAttribute;\r", + "\tmissingAttribute = attributes[Math.floor(Math.random()*attributes.length)];\r", + "\treturn missingAttribute;\r", + "}" ], "type": "text/javascript" } @@ -235360,35 +246398,18 @@ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", - "var expectedLifeCycleState;\r", - "try {\r", - " let dummyLifeCycleState;\r", - " dummyLifeCycleState = pm.collectionVariables.get(\"dummyLifeCycleState\");\r", - "\r", - " let prefixLength = ('operation-server-interface-1-0:LIFE_CYCLE_STATE_TYPE_').length; \r", - " expectedLifeCycleState = dummyLifeCycleState.substring(prefixLength);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Could not load Input Data. \");\r", - "}\r", "\r", "\r", "/****************************************************************************************\r", "* Extracting Result\r", "****************************************************************************************/\r", "var RESPONSE_CODE;\r", - "var actualLifeCycleState;\r", "try {\r", " let response;\r", " response = pm.response;\r", "\r", " RESPONSE_CODE = parseInt(response.code);\r", "\r", - " let RESPONSE_HEADERS;\r", - " RESPONSE_HEADERS = pm.response.headers; \r", - "\r", - " actualLifeCycleState = RESPONSE_HEADERS.get(\"life-cycle-state\");\r", - "\r", "} catch (error) {\r", " console.log(\"! Response Code could not be extracted.\");\r", "} \r", @@ -235398,8 +246419,8 @@ "* Testing\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"Provides dummy life-cycle-state in the header of the response: '\" + expectedLifeCycleState + \"' \", function () {\r", - " pm.expect(actualLifeCycleState).to.equal(expectedLifeCycleState);\r", + " pm.test(\"POST /v1/update-operation-client responds 400, because of missing attribute\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(400);\r", " });\r", "\r", "} catch (error) {\r", @@ -235413,683 +246434,2395 @@ "\r", "" ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "204", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-mock-response-code", + "value": "400", + "type": "default" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ], + "description": "## Get attributes checked for completeness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/update-operation-client, storing operation-key\n- searching CC for set of already existing random http-c, tcp-c and one of its op-c, store them\n- POST /v1/update-operation-client\n - all attributes(both old and new) according to chosen http-c, tcp-c and op-c, BUT one randomly chosen attribute missing\n -operation-key from above\n - reasonable parameters\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" + }, + { + "name": "Attribute correctness", + "item": [ + { + "name": "application-release-number checked?", + "item": [ + { + "name": "reference /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- /v1/update-operation-client acceptance -- application-release-number attribute checked? -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var ltpList;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var currentOperationServer;\r", + "var httpClientLtp;\r", + "var operationClientLtp;\r", + "try {\r", + " currentOperationServer = FindOperationServer(\"/v1/update-operation-client\", ltpList);\r", + " httpClientLtp = FindRandomHttpClientLTP(ltpList);\r", + " operationClientLtp = FindRandomOperationClientLtp(httpClientLtp, ltpList);\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", + " pm.collectionVariables.set(\"httpClientLtp\", httpClientLtp);\r", + " pm.collectionVariables.set(\"operationClientLtp\", operationClientLtp);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "function FindOperationServer(operationName, ltpList) {\r", + " let operationServer;\r", + " operationServer = \"\";\r", + " try {\r", + " let sampleUuid;\r", + " for(let i=0; i 0 ) {\r", + " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", + " randomHttpClientLtp = httpClientLtpList[random];\r", + " }\r", + " } catch( error ){\r", + " console.log(error);\r", + " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", + " }\r", + " return randomHttpClientLtp;\r", + "}\r", + "\r", + "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", + " let randomOperationClientLtp;\r", + " randomOperationClientLtp = {};\r", + " try{\r", + " let clientLtpUuidList;\r", + " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", + " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", + " let randomClientLtpUuid;\r", + " randomClientLtpUuid = clientLtpUuidList[random];\r", + " for( let i=0; i 0 ) {\r", + " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", + " randomHttpClientLtp = httpClientLtpList[random];\r", + " }\r", + " } catch( error ){\r", + " console.log(error);\r", + " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", + " }\r", + " return randomHttpClientLtp;\r", + "}\r", + "\r", + "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", + " let randomOperationClientLtp;\r", + " randomOperationClientLtp = {};\r", + " try{\r", + " let clientLtpUuidList;\r", + " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", + " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", + " let randomClientLtpUuid;\r", + " randomClientLtpUuid = clientLtpUuidList[random];\r", + " for( let i=0; i 0 ) {\r", - " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", - " randomHttpClientLtp = httpClientLtpList[random];\r", - " }\r", - " } catch( error ){\r", - " console.log(error);\r", - " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", - " }\r", - " return randomHttpClientLtp;\r", - "}\r", - "\r", - "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", - " let randomOperationClientLtp;\r", - " randomOperationClientLtp = {};\r", - " try{\r", - " let clientLtpUuidList;\r", - " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", - " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", - " let randomClientLtpUuid;\r", - " randomClientLtpUuid = clientLtpUuidList[random];\r", - " for( let i=0; i Target =====>", + "item": [ + { + "name": "=====> Target =====>", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- Target --------------------------------------------------\");", + "/****************************************************************************************", + "* ", + "* Here starts the execution of specific validation tests", + "* ", + "****************************************************************************************/", + "", + "", + "/****************************************************************************************", + "* Loading Input Data", + "****************************************************************************************/", + "try {", + " var URI;", + " URI = pm.environment.get(\"dummyUri\");", + "", + "} catch (error) {", + " console.log(\"! Environment variables could not be loaded.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Setting up Local Variables and Preparing the Request", + "****************************************************************************************/", + "try {", + " pm.variables.clear();", + "", + " pm.variables.set(\"uri\", URI);", + " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", + "", + "} catch (error) {", + " console.log(\"! Local variables could not be set.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Functions", + "****************************************************************************************/", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "=====> JustJumpToTheEnd =====>", + "item": [ + { + "name": "=====> JustJumpToTheEnd =====>", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- JustJumpToEnd --------------------------------------------------\");", + "/****************************************************************************************", + "* ", + "* This is a request for daily working with the Validator.", + "* It just makes the program flow jumping to the Request named \"=====> End\".", + "* ", + "****************************************************************************************/", + " ", + " ", + "/****************************************************************************************", + "* Loading Input Data", + "****************************************************************************************/", + "try {", + " var URI;", + " URI = pm.environment.get(\"dummyUri\");", + "", + "} catch (error) {", + " console.log(\"! Environment variables could not be loaded.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Setting up Local Variables and Preparing the Request", + "****************************************************************************************/", + "try {", + " pm.variables.clear();", + "", + " postman.setNextRequest(\"=====> End\");", + "", + " pm.variables.set(\"uri\", URI);", + " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", + "", + "} catch (error) {", + " console.log(\"! Local variables could not be set.\");", + "}", + "", + "", + "/****************************************************************************************", + "* Functions", + "****************************************************************************************/", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "OamLayer", + "item": [ + { + "name": "IndividualPart", + "item": [ + { + "name": "core", + "item": [ + { + "name": "core-model-1-4:control-construct", + "item": [ + { + "name": "GET", + "item": [ + { + "name": "Continuous Integration", + "item": [ + { + "name": "security key missing?", + "item": [ + { + "name": "Expected /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- GET /core-model-1-4:control-construct -- authorization code missing? -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct\";\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"As expected, GET /core-model-1-4:control-construct responds 401, because of missing Authorization-code\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(401);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "x-mock-response-code", + "value": "401", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ], + "description": "## Gets security key checked for availability?\n#### Preparation:\n- GET core-model-1-4:control-construct in such a way that it does not cause any change due to idempotence, BUT authorizationCode parameter missing (does not mean empty string)\n\n#### Testing:\n- checking for ResponseCode==401\n\n#### Clearing:\n- not applicable" + }, + { + "name": "security key checked?", + "item": [ + { + "name": "Expected /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- GET /core-model-1-4:control-construct -- authorization code checked? -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct\";\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Dummy security key\r", + "****************************************************************************************/\r", + "var FAULTY_AUTHORIZATION_CODE;\r", + "try {\r", + " FAULTY_AUTHORIZATION_CODE = \"Basic \" + GenerateRandomHexString(32);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not define dummy value for operationKey. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:FAULTY_AUTHORIZATION_CODE});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function GenerateRandomHexString(length) {\r", + " var randomRandomHexString = \"\";\r", + " while (randomRandomHexString.length < length) {\r", + " randomRandomHexString += Math.random().toString(16).substring(2);\r", + " }\r", + " return randomRandomHexString.substring(0,length);\r", + "}\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"As expected, GET /core-model-1-4:control-construct responds 401, because of incorrect Authorization-code\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(401);\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "x-mock-response-code", + "value": "401", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ], + "description": "## Gets security key checked for correctness?\n#### Preparation:\n- GET core-model-1-4:control-construct in such a way that it does not cause any change due to idempotence, BUT operationKey/authorizationCode with random generated value.\n\n#### Testing:\n- checking for ResponseCode==401\n\n#### Clearing:\n- not applicable" + }, + { + "name": "Request notified?", + "item": [ + { + "name": "reference /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- GET /core-model-1-4:control-construct integration -- request notified? -------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct\";\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var ltpList;\r", + "var fcList;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + " \r", + " let responseCode;\r", + " responseCode = parseInt(response.code);\r", + " \r", + " if ( Math.floor(responseCode/100) === 2 ) {\r", + " let responseObject;\r", + " responseObject = JSON.parse(response.stream);\r", + " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + " fcList = responseObject[\"core-model-1-4:control-construct\"][\"forwarding-domain\"][0][\"forwarding-construct\"];\r", + "\r", + " } else {\r", + " ltpList = [];\r", + " fcList = [];\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! ltpList could not be extracted.\");\r", + "}\r", + "\r", + "var oamLogHttpClientLtp;\r", + "var oamLogTcpClientLtp;\r", + "var httpServerLtp;\r", + "try {\r", + " let outputFcPortListForOamRequestCausesLoggingRequest;\r", + " outputFcPortListForOamRequestCausesLoggingRequest = FindOutputFcPortList(\"OamRequestCausesLoggingRequest\", fcList);\r", + "\r", + " let randomOutputFcPortForOamRequestCausesLoggingRequest;\r", + " randomOutputFcPortForOamRequestCausesLoggingRequest = outputFcPortListForOamRequestCausesLoggingRequest[Math.floor(Math.random() * outputFcPortListForOamRequestCausesLoggingRequest.length)];\r", + "\r", + " let outputLtpUuidForRecordOamRequest;\r", + " outputLtpUuidForRecordOamRequest = randomOutputFcPortForOamRequestCausesLoggingRequest[\"logical-termination-point\"];\r", + "\r", + " let recordOamRequestOperationClientLtp;\r", + " recordOamRequestOperationClientLtp = FindActualInstanceByUuid(outputLtpUuidForRecordOamRequest, ltpList);\r", + "\r", + " oamLogHttpClientLtp = FindServingLtp(recordOamRequestOperationClientLtp, ltpList);\r", + " oamLogTcpClientLtp = FindServingLtp(oamLogHttpClientLtp, ltpList);\r", + "\r", + " httpServerLtp = FindHttpServerLtp(ltpList);\r", + "\r", + "} catch (error) {\r", + " console.log(error);\r", + " console.log(\"! Reference objects could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.clear();\r", + " \r", + " pm.collectionVariables.set(\"oamLogHttpClientLtp\", oamLogHttpClientLtp);\r", + " pm.collectionVariables.set(\"oamLogTcpClientLtp\", oamLogTcpClientLtp);\r", + " pm.collectionVariables.set(\"httpServerLtp\", httpServerLtp);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function FindOutputFcPortList(forwardingName, fcList) {\r", + " let outputFcPortList;\r", + " outputFcPortList = [];\r", + " try {\r", + " for( let i=0; i= actualTimestamp)) {\r", + "\r", + " foundAnEntryWithTheExpectedValuesInOam = true;\r", + " break;\r", + " }\r", + " }\r", + "\r", + " pm.test(\"The request has been notified and the Parameter values have been processed.\", function () {\r", + " pm.expect(foundAnEntryWithTheExpectedValuesInOam).to.be.true;\r", + " });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Testing could not be executed.\");\r", + " console.log(error)\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-mock-response-code", + "value": "200", + "type": "text" + } ], - "type": "text/javascript" - } - }, + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + } + ], + "description": "## Gets the service request indicated to OL and the Parameters of the request processed?\n\n#### Requires:\n- OamLog server to operate\n\n#### Preparation:\n- Geting CC (/core-model-1-4:control-construct)\n - searching CC for http-c uuid of OamLog\n - finding serving tcp-c uuid of OamLog, storing it for later verification request- GETting OL/CC (while using IP and port from above)\n - searching CC for op-c of /v1/list-records-of-application, storing operation-key\n- GET core-model-1-4:control-construct in such a way that it does not cause any change due to idempotence.\n\n#### Testing:\n- POST OamLog/v1/list-records-of-application with \n - IP and port from above\n - operation-key from above\n - server application-name\n - checking response \n - checking same record for application-name, method, resource, timestamp\n\n#### Clearing:\n- not applicable" + } + ] + }, + { + "name": "Gate", + "item": [ + { + "name": "for gating /core-model-1-4:control-construct to acceptance testing", + "event": [ { - "listen": "test", + "listen": "prerequest", "script": { "exec": [ "/****************************************************************************************\r", "* Loading Input Data\r", "****************************************************************************************/\r", + "var TYPE_OF_TESTING;\r", + "var URI;\r", + "try {\r", + " TYPE_OF_TESTING = pm.environment.get(\"typeOfTesting\");\r", + " URI = pm.environment.get(\"dummyUri\");\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Loading Input Data failed.\");\r", + "}\r", "\r", "\r", "/****************************************************************************************\r", - "* Extracting Result\r", + "* Updating Environmental Variables and Determining the next Step\r", "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", "try {\r", - " let response;\r", - " response = pm.response;\r", - "\r", - " RESPONSE_CODE = parseInt(response.code);\r", + " if ( TYPE_OF_TESTING === \"Acceptance\" ) {\r", + " postman.setNextRequest();\r", + " } else {\r", + " postman.setNextRequest(\"for exiting GET /core-model-1-4:control-construct\");\r", + " }\r", "\r", "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", + " console.log(\"! Updating Environmental Variables and Determining the next Step failed.\");\r", + "}\r", "\r", "\r", "/****************************************************************************************\r", - "* Testing\r", + "* Setting Local Variables and Preparing the Request\r", "****************************************************************************************/\r", "try {\r", - " pm.test(\"POST /v1/update-operation-client responds 400, because of letters in application-release-number\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", + " pm.variables.clear();\r", + "\r", + " let REQUEST_BODY;\r", + " REQUEST_BODY = \"\";\r", + "\r", + " let AUTHORIZATION;\r", + " AUTHORIZATION = \"\";\r", + "\r", + " let OPERATION_KEY;\r", + " OPERATION_KEY = \"\";\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + " pm.request.headers.upsert({key:\"operationKey\", value:OPERATION_KEY});\r", + " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:\"application/json\"});\r", "\r", "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", + " console.log(\"! Setting Local Variables and Preparing the Request failed.\");\r", "}\r", "\r", "\r", @@ -236985,15 +251785,12 @@ } } ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "400", - "type": "default" - } - ], + "method": "GET", + "header": [], "body": { "mode": "raw", "raw": "{{requestBody}}", @@ -237011,2492 +251808,4378 @@ } }, "response": [] + } + ] + }, + { + "name": "Acceptance", + "item": [ + { + "name": "Response body completeness", + "item": [ + { + "name": "Expected /core-model-1-4:control-construct", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"\\n----- GET /core-model-1-4:control-construct acceptance -- response body Response body completeness-------------------------------\");\r", + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct\";\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Environment variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = \"\";\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var expectedControlConstruct;\r", + "var expectedLtpList;\r", + "var expectedFDList;\r", + "try {\r", + " let APPLICATION;\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " expectedControlConstruct = APPLICATION[\"core-model-1-4:control-construct\"];\r", + " expectedLtpList = expectedControlConstruct[\"logical-termination-point\"];\r", + " expectedFDList = expectedControlConstruct[\"forwarding-domain\"];\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Could not load Input Data. \");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Extracting Result\r", + "****************************************************************************************/\r", + "var RESPONSE_CODE;\r", + "var actualControlConstruct;\r", + "try {\r", + " let response;\r", + " response = pm.response;\r", + "\r", + " RESPONSE_CODE = parseInt(response.code);\r", + "\r", + " if ( Math.floor(RESPONSE_CODE/100) === 2 ) {\r", + " actualControlConstruct = JSON.parse(response.stream);\r", + " } else {\r", + " actualControlConstruct = {};\r", + " }\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Response Code could not be extracted.\");\r", + "} \r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Testing\r", + "****************************************************************************************/\r", + "try {\r", + " pm.test(\"POST /core-model-1-4:control-construct responds 200\", function () {\r", + " pm.expect(RESPONSE_CODE).to.equal(200);\r", + " });\r", + "\r", + " pm.test(\"Control construct could be found \" , function () {\r", + " pm.expect(actualControlConstruct).to.not.equal(undefined);\r", + " pm.expect(Object.keys(actualControlConstruct).length).to.not.equal(0);\r", + " });\r", + "\r", + " if( actualControlConstruct != undefined ) { \r", + "\r", + " let controlConstructSchema;\r", + " controlConstructSchema = {\r", + " \"type\": \"object\",\r", + " \"required\": [\r", + " \"uuid\",\r", + " \"profile-collection\",\r", + " \"logical-termination-point\",\r", + " \"forwarding-domain\"\r", + " ],\r", + " \"properties\": {\r", + " \"uuid\": {\r", + " \"type\": \"string\"\r", + " },\r", + " \"profile-collection\": {\r", + " \"type\": \"object\",\r", + " \"required\": [\r", + " \"profile\"\r", + " ],\r", + " \"properties\": {\r", + " \"profile\": {\r", + " \"type\": \"array\",\r", + " \"uniqueItems\": true\r", + " }\r", + " }\r", + " },\r", + " \"logical-termination-point\": {\r", + " \"type\": \"array\",\r", + " \"uniqueItems\": true\r", + " },\r", + " \"forwarding-domain\": {\r", + " \"type\": \"array\",\r", + " \"minItems\": 1,\r", + " \"maxItems\": 1,\r", + " \"items\": {\r", + " \"type\": \"object\",\r", + " \"required\": [\r", + " \"uuid\",\r", + " \"forwarding-construct\"\r", + " ],\r", + " \"properties\": {\r", + " \"uuid\": {\r", + " \"type\": \"string\"\r", + " },\r", + " \"forwarding-construct\": {\r", + " \"type\": \"array\"\r", + " }\r", + " }\r", + " }\r", + " }\r", + " }\r", + " }\r", + " let controlConstructSchemaValidation;\r", + " controlConstructSchemaValidation = tv4.validateMultiple(actualControlConstruct[\"core-model-1-4:control-construct\"], controlConstructSchema, true, true);\r", + " console.log(controlConstructSchemaValidation);\r", + " pm.test(\"Valid schema for Control-construct '\" + expectedControlConstruct[\"uuid\"] + \"'\", function () {\r", + " pm.expect(controlConstructSchemaValidation.valid).to.be.true;\r", + " });\r", + " \r", + " pm.test(\"control-construct uuid '\" + expectedControlConstruct[\"uuid\"] + \"' could be found \" , function () {\r", + " pm.expect(actualControlConstruct[\"core-model-1-4:control-construct\"][\"uuid\"]).to.not.equal(undefined);\r", + " pm.expect(actualControlConstruct[\"core-model-1-4:control-construct\"][\"uuid\"]).to.equal(expectedControlConstruct[\"uuid\"]);\r", + " });\r", + "\r", + " // testcases for logical termination point\r", + "\r", + " var actualLtpList;\r", + " actualLtpList = actualControlConstruct[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", + " pm.test(\"Logical termination point list could be found \" , function () {\r", + " pm.expect(actualLtpList).to.not.equal(undefined);\r", + " pm.expect(Object.keys(actualLtpList).length).to.not.equal(0);\r", + " });\r", + " if(actualLtpList != undefined) {\r", + " for ( let expectedLtpIndex=0; expectedLtpIndex -1) {\r", + " alternativeLifeCycleStateTypeList.splice(indexOfCurrentLifeCycleState, 1);\r", + " }\r", + "\r", + " let alternativeLifeCycleState;\r", + " let alternativeLifeCycleStateTypeIndex;\r", + " alternativeLifeCycleStateTypeIndex = Math.floor(Math.random() * alternativeLifeCycleStateTypeList.length);\r", + " alternativeLifeCycleState = alternativeLifeCycleStateTypeList[alternativeLifeCycleStateTypeIndex]; \r", + "\r", + " return alternativeLifeCycleState;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] + }, + { + "name": "dummy op-s/operation-key", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "var randomOperationServerUuid;\r", + "var dummyOperationKey;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " \r", + " let randomOperationServerInstance;\r", + " randomOperationServerInstance = pm.collectionVariables.get(\"randomOperationServerInstance\");\r", + "\r", + " randomOperationServerUuid = randomOperationServerInstance[\"uuid\"];\r", + " \r", + " oamPath = \"/core-model-1-4:control-construct/logical-termination-point=\" + randomOperationServerUuid + \"/layer-protocol=0/operation-server-interface-1-0:operation-server-interface-pac/operation-server-interface-configuration/operation-key\";\r", + "\r", + " dummyOperationKey = GenerateRandomString(12);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-server-interface-1-0:operation-key\": \"' + dummyOperationKey + '\"'\r", + " + ' }';\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"dummyOperationServerOperationKey\", dummyOperationKey);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath; \r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function GenerateRandomString(length) {\r", + " let randomString;\r", + " randomString = \"\";\r", + " try {\r", + " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength = characters.length;\r", + " for (let i = 0; i < length; i++) {\r", + " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " }\r", + " } catch (error) {\r", + " console.log(\"! Could not generate random string. \");\r", + " }\r", + " return randomString;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "400", - "type": "default" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - }, - { - "name": "Expected /v1/update-operation-client- incorrect separator in application-release-number", - "event": [ { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- incorrect separators in application-release-number -------------------------------\");\r", - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "var OPERATION_KEY;\r", - "var applicationName;\r", - "var dummyApplicationReleaseNumber;\r", - "var operationName;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - " let currentOperationServer;\r", - " currentOperationServer = pm.collectionVariables.get(\"currentOperationServer\");\r", - " \r", - " OPERATION_KEY = currentOperationServer[\"layer-protocol\"][0][\"operation-server-interface-1-0:operation-server-interface-pac\"][\"operation-server-interface-configuration\"][\"operation-key\"];\r", - "\r", - " let httpClientLtp;\r", - " httpClientLtp = pm.collectionVariables.get(\"httpClientLtp\");\r", - "\r", - " applicationName = httpClientLtp[\"layer-protocol\"][0][\"http-client-interface-1-0:http-client-interface-pac\"][\"http-client-interface-capability\"][\"application-name\"];\r", - " dummyApplicationReleaseNumber = FaultyReleaseNumber();\r", - "\r", - " let operationClientLtp;\r", - " operationClientLtp = pm.collectionVariables.get(\"operationClientLtp\");\r", - "\r", - " operationName = operationClientLtp[\"layer-protocol\"][0][\"operation-client-interface-1-0:operation-client-interface-pac\"][\"operation-client-interface-configuration\"][\"operation-name\"];\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Input Data could not be loaded.\");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Dummy Parameters\r", - "****************************************************************************************/\r", - "var USER_NAME;\r", - "var ORIGINATOR;\r", - "var X_CORRELATOR;\r", - "var TRACE_INDICATOR;\r", - "var CUSTOMER_JOURNEY;\r", - "try {\r", - " USER_NAME = APPLICATION.userName;\r", - " ORIGINATOR = \"Postman\";\r", - " X_CORRELATOR = CreateXCorrelator();\r", - " TRACE_INDICATOR = \"1\";\r", - " CUSTOMER_JOURNEY = \"CustomerJourney not yet defined.\";\r", - " \r", - "} catch (error) {\r", - " console.log(\"! Could not define dummy values for parameters. \");\r", - "}\r", - "\r", - "/****************************************************************************************\r", - "* Defining Request Body\r", - "****************************************************************************************/\r", - "var REQUEST_BODY;\r", - "try {\r", - " REQUEST_BODY = '{'\r", - " + '\"application-name\" : ' + '\"' + applicationName + '\",'\r", - " + '\"application-release-number\" : ' + '\"' + dummyApplicationReleaseNumber + '\",'\r", - " + '\"old-operation-name\" : ' + '\"' + operationName + '\",' \r", - " + '\"new-operation-name\" : ' + '\"' + operationName + '\"'\r", - " +'}';\r", - "} catch (error) {\r", - " console.log(\"!Could not define request body. \");\r", - "}\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/v1/update-operation-client\";\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"operation-key\", value:OPERATION_KEY});\r", - "\r", - " pm.request.headers.upsert({key:\"user\", value:USER_NAME});\r", - " pm.request.headers.upsert({key:\"originator\", value:ORIGINATOR});\r", - " pm.request.headers.upsert({key:\"x-correlator\", value:X_CORRELATOR});\r", - " pm.request.headers.upsert({key:\"trace-indicator\", value:TRACE_INDICATOR});\r", - " pm.request.headers.upsert({key:\"customer-journey\", value:CUSTOMER_JOURNEY});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "function CreateXCorrelator() {\r", - " let xCorrelator;\r", - " xCorrelator = \"\";\r", - " xCorrelator += GenerateRandomHexString(8) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(4) + \"-\";\r", - " xCorrelator += GenerateRandomHexString(12);\r", - " return xCorrelator;\r", - "}\r", - "\r", - "function GenerateRandomHexString(length) {\r", - " var randomRandomHexString = \"\";\r", - " while (randomRandomHexString.length < length) {\r", - " randomRandomHexString += Math.random().toString(16).substring(2);\r", - " }\r", - " return randomRandomHexString.substring(0,length);\r", - "}\r", - "\r", - "function FaultyReleaseNumber() {\r", - " let releaseNumber;\r", - " releaseNumber = \"\";\r", - " let releaseNumberParts;\r", - " releaseNumberParts = [];\r", - " for(let i=0; i<3; i++) {\r", - " releaseNumberParts[i] = Math.floor(Math.random() * 10);\r", - " }\r", - " let separators;\r", - " separators = \"-:;/\";\r", - " let separatorsLength;\r", - " separatorsLength = separators.length;\r", - " let faultySeparator;\r", - " faultySeparator = separators.charAt(Math.floor(Math.random() * separatorsLength));\r", - " releaseNumber = releaseNumberParts.join(faultySeparator);\r", - " return releaseNumber;\r", - "}" + "name": "dummy tcp-s/local-address", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "var randomTcpServerUuid;\r", + "var dummyLocalAddress;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " \r", + " let randomTcpServerInstance;\r", + " randomTcpServerInstance = pm.collectionVariables.get(\"randomTcpServerInstance\");\r", + "\r", + " randomTcpServerUuid = randomTcpServerInstance[\"uuid\"];\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct/logical-termination-point=\" + randomTcpServerUuid + \"/layer-protocol=0/tcp-server-interface-1-0:tcp-server-interface-pac/tcp-server-interface-configuration/local-address/ipv-4-address\";\r", + "\r", + " dummyLocalAddress = RandomIpAddress();\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = '{ '\r", + " + '\"tcp-server-interface-1-0:ipv-4-address\": \"' + dummyLocalAddress + '\"'\r", + " + ' }';\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"dummyLocalAddress\", dummyLocalAddress);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function RandomIpAddress() {\r", + " let randomAddress\r", + " let addressParts = [];\r", + " for ( let i=0; i<4; i++ ) {\r", + " addressParts[i] = String(Math.floor(Math.random() * 256));\r", + " }\r", + " randomAddress = addressParts[0] + \".\" + addressParts[1] + \".\" + addressParts[2] + \".\" + addressParts[3];\r", + " return randomAddress;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } ], - "type": "text/javascript" - } + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] }, { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var RESPONSE_CODE;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - "\r", - " RESPONSE_CODE = parseInt(response.code);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Response Code could not be extracted.\");\r", - "} \r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Testing\r", - "****************************************************************************************/\r", - "try {\r", - " pm.test(\"POST /v1/update-operation-client responds 400, because of incorrect separator in application-release-number\", function () {\r", - " pm.expect(RESPONSE_CODE).to.equal(400);\r", - " });\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Testing could not be executed.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" + "name": "dummy tcp-s/local-port", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "var randomTcpServerUuid;\r", + "var dummyLocalPort;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " \r", + " let randomTcpServerInstance;\r", + " randomTcpServerInstance = pm.collectionVariables.get(\"randomTcpServerInstance\");\r", + "\r", + " randomTcpServerUuid = randomTcpServerInstance[\"uuid\"];\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct/logical-termination-point=\" + randomTcpServerUuid + \"/layer-protocol=0/tcp-server-interface-1-0:tcp-server-interface-pac/tcp-server-interface-configuration/local-port\";\r", + "\r", + " dummyLocalPort = RandomTcpPort();\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = '{ '\r", + " + '\"tcp-server-interface-1-0:local-port\": ' + dummyLocalPort\r", + " + ' }';\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"dummyLocalPort\", dummyLocalPort);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function RandomTcpPort() {\r", + " let randomPort;\r", + " randomPort = 2000 + Math.floor( Math.random() * 1000 );\r", + " return randomPort;\r", + "}\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "x-mock-response-code", - "value": "400", - "type": "default" - } - ], - "body": { - "mode": "raw", - "raw": "{{requestBody}}", - "options": { - "raw": { - "language": "json" + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] } - } + }, + "response": [] }, - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ], - "description": "## Get application-release-number checked for correctness?\n#### Preparation:\n- GETing CC (/core-model-1-4:control-construct)\n- searching CC for op-s of /v1/update-operation-client, storing operation-key\n- searching CC for set of already existing random http-c, tcp-c and one of its op-c, store them\n- POST /v1/update-operation-client\n - all attributes(both old and new) according to chosen http-c, tcp-c and op-c,BUT application-release-number attribute with random dummy value (differing from specification in many ways)\n -operation-key from above\n - reasonable parameters\n\n#### Testing:\n- checking for ResponseCode==400\n\n#### Clearing:\n- not applicable" - } - ] - }, - { - "name": "Attribute configured?", - "item": [ - { - "name": "new-operation-name updated?", - "item": [ - { - "name": "reference /core-model-1-4:control-construct", - "event": [ { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- /v1/update-operation-client acceptance -- new-operation-name attribute updated? -------------------------------\");\r", - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "var APPLICATION;\r", - "try {\r", - " APPLICATION = pm.environment.get(\"application\");\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Environment variables could not be loaded.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Local Variables and Preparing the Request\r", - "****************************************************************************************/\r", - "try {\r", - " let URI;\r", - " URI = APPLICATION.serverUrl + \"/core-model-1-4:control-construct\";\r", - "\r", - " let REQUEST_BODY;\r", - " REQUEST_BODY = \"\";\r", - "\r", - " let AUTHORIZATION;\r", - " AUTHORIZATION = APPLICATION.authorizationCode;\r", - "\r", - " let ACCEPT;\r", - " ACCEPT = \"application/json\";\r", - "\r", - " let CONTENT_TYPE;\r", - " CONTENT_TYPE = \"application/json\";\r", - "\r", - "\r", - " pm.variables.clear();\r", - "\r", - " pm.variables.set(\"uri\", URI);\r", - " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", - "\r", - " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", - "\r", - " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", - " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Local variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "" + "name": "dummy op-c/operation-name", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Loading Input Data\r", + "****************************************************************************************/\r", + "var APPLICATION;\r", + "var AUTHORIZATION;\r", + "var randomOperationClientUuid;\r", + "var dummyOperationName;\r", + "var oamPath;\r", + "try {\r", + " APPLICATION = pm.environment.get(\"application\");\r", + " AUTHORIZATION = APPLICATION.authorizationCode;\r", + " \r", + " let randomOperationClientInstance;\r", + " randomOperationClientInstance = pm.collectionVariables.get(\"randomOperationClientInstance\");\r", + "\r", + " randomOperationClientUuid = randomOperationClientInstance[\"uuid\"];\r", + "\r", + " oamPath = \"/core-model-1-4:control-construct/logical-termination-point=\" + randomOperationClientUuid + \"/layer-protocol=0/operation-client-interface-1-0:operation-client-interface-pac/operation-client-interface-configuration/operation-name\";\r", + "\r", + " dummyOperationName = GenerateRandomString(12);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Variables could not be loaded.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Defining Request Body\r", + "****************************************************************************************/\r", + "var REQUEST_BODY;\r", + "try {\r", + " REQUEST_BODY = '{ '\r", + " + '\"operation-client-interface-1-0:operation-name\": \"' + dummyOperationName + '\"'\r", + " + ' }';\r", + "} catch (error) {\r", + " console.log(\"!Could not define request body. \");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Collection Variables\r", + "****************************************************************************************/\r", + "try {\r", + " pm.collectionVariables.set(\"dummyOperationName\", dummyOperationName);\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " let URI;\r", + " URI = APPLICATION.serverUrl + oamPath;\r", + "\r", + " let ACCEPT;\r", + " ACCEPT = \"application/json\";\r", + "\r", + " let CONTENT_TYPE;\r", + " CONTENT_TYPE = \"application/json\";\r", + "\r", + " pm.variables.clear();\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.variables.set(\"requestBody\", REQUEST_BODY);\r", + "\r", + " pm.request.headers.upsert({key:\"Authorization\", value:AUTHORIZATION});\r", + "\r", + " pm.request.headers.upsert({key:\"Accept\", value:ACCEPT});\r", + " pm.request.headers.upsert({key:\"Content-Type\", value:CONTENT_TYPE});\r", + "\r", + "} catch (error) {\r", + " console.log(error)\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "function GenerateRandomString(length) {\r", + " let randomString;\r", + " randomString = \"\";\r", + " try {\r", + " let characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\r", + " let charactersLength = characters.length;\r", + " for (let i = 0; i < length; i++) {\r", + " randomString += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " }\r", + " } catch (error) {\r", + " console.log(\"! Could not generate random string. \");\r", + " }\r", + " return randomString;\r", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "x-mock-response-code", + "value": "204", + "type": "text" + } ], - "type": "text/javascript" - } + "body": { + "mode": "raw", + "raw": "{{requestBody}}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] + } + }, + "response": [] }, { - "listen": "test", - "script": { - "exec": [ - "/****************************************************************************************\r", - "* Loading Input Data\r", - "****************************************************************************************/\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Extracting Result\r", - "****************************************************************************************/\r", - "var ltpList;\r", - "var fcList;\r", - "try {\r", - " let response;\r", - " response = pm.response;\r", - " \r", - " let responseCode;\r", - " responseCode = parseInt(response.code);\r", - " \r", - " if ( Math.floor(responseCode/100) === 2 ) {\r", - " let responseObject;\r", - " responseObject = JSON.parse(response.stream);\r", - " ltpList = responseObject[\"core-model-1-4:control-construct\"][\"logical-termination-point\"];\r", - " fcList = responseObject[\"core-model-1-4:control-construct\"][\"forwarding-domain\"][0][\"forwarding-construct\"];\r", - "\r", - " } else {\r", - " ltpList = [];\r", - " fcList = [];\r", - " }\r", - "\r", - "} catch (error) {\r", - " console.log(\"! ltpList could not be extracted.\");\r", - "}\r", - "\r", - "var currentOperationServer;\r", - "var httpClientLtp;\r", - "var operationClientLtp;\r", - "try {\r", - " currentOperationServer = FindOperationServer(\"/v1/update-operation-client\", ltpList);\r", - " httpClientLtp = FindRandomHttpClientLTP(ltpList);\r", - " operationClientLtp = FindRandomOperationClientLtp(httpClientLtp, ltpList);\r", - "} catch (error) {\r", - " console.log(error);\r", - " console.log(\"! Reference objects could not be extracted.\");\r", - "} \r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Setting Collection Variables\r", - "****************************************************************************************/\r", - "try {\r", - " pm.collectionVariables.clear();\r", - " \r", - " pm.collectionVariables.set(\"currentOperationServer\", currentOperationServer);\r", - " pm.collectionVariables.set(\"httpClientLtp\", httpClientLtp);\r", - " pm.collectionVariables.set(\"operationClientLtp\", operationClientLtp);\r", - " pm.collectionVariables.set(\"ltpList\", ltpList);\r", - " pm.collectionVariables.set(\"fcList\", fcList);\r", - "\r", - "} catch (error) {\r", - " console.log(\"! Collection variables could not be set.\");\r", - "}\r", - "\r", - "\r", - "/****************************************************************************************\r", - "* Functions\r", - "****************************************************************************************/\r", - "\r", - "function FindOperationServer(operationName, ltpList) {\r", - " let operationServer;\r", - " operationServer = \"\";\r", - " try {\r", - " let sampleUuid;\r", - " for(let i=0; i 0 ) {\r", - " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", - " randomHttpClientLtp = httpClientLtpList[random];\r", - " }\r", - " } catch( error ){\r", - " console.log(error);\r", - " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", - " }\r", - " return randomHttpClientLtp;\r", - "}\r", - "\r", - "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", - " let randomOperationClientLtp;\r", - " randomOperationClientLtp = {};\r", - " try{\r", - " let clientLtpUuidList;\r", - " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", - " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", - " let randomClientLtpUuid;\r", - " randomClientLtpUuid = clientLtpUuidList[random];\r", - " for( let i=0; i 0 ) {\r", - " const random = Math.floor(Math.random() * httpClientLtpList.length);\r", - " randomHttpClientLtp = httpClientLtpList[random];\r", - " }\r", - " } catch( error ){\r", - " console.log(error);\r", - " console.log(\"! Exception in function : FindRandomHttpClientLTP. \")\r", - " }\r", - " return randomHttpClientLtp;\r", - "}\r", - "\r", - "function FindRandomOperationClientLtp(serverLtp, ltpList) {\r", - " let randomOperationClientLtp;\r", - " randomOperationClientLtp = {};\r", - " try{\r", - " let clientLtpUuidList;\r", - " clientLtpUuidList = serverLtp[\"client-ltp\"];\r", - " const random = Math.floor(Math.random() * clientLtpUuidList.length);\r", - " let randomClientLtpUuid;\r", - " randomClientLtpUuid = clientLtpUuidList[random];\r", - " for( let i=0; i JustJumpToTarget =====>", - "item": [ + "name": "Clearing collection data", + "event": [ { - "name": "=====> JustJumpToTarget =====>", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- JustJumpToTarget --------------------------------------------------\");", - "/****************************************************************************************", - "* ", - "* This is a request for daily working with the Validator.", - "* It just makes the program flow jumping to the Request named \"=====> Target =====>\".", - "* ", - "****************************************************************************************/", - " ", - " ", - "/****************************************************************************************", - "* Loading Input Data", - "****************************************************************************************/", - "try {", - " var URI;", - " URI = pm.environment.get(\"dummyUri\");", - "", - "} catch (error) {", - " console.log(\"! Environment variables could not be loaded.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Setting up Local Variables and Preparing the Request", - "****************************************************************************************/", - "try {", - " pm.variables.clear();", - "", - " postman.setNextRequest(\"=====> Target =====>\");", - "", - " pm.variables.set(\"uri\", URI);", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", - "", - "} catch (error) {", - " console.log(\"! Local variables could not be set.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Functions", - "****************************************************************************************/", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [], - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "=====> Target =====>", - "item": [ + "listen": "prerequest", + "script": { + "exec": [ + "console.log(\"====================================== Clearing collection data ====================================\");\r", + "console.log(\"==========================================================================================\");\r", + "\r", + "/****************************************************************************************\r", + "* Setting Local Variables and Preparing the Request\r", + "****************************************************************************************/\r", + "try {\r", + " \r", + " let URI;\r", + " URI = pm.environment.get(\"dummyUri\");\r", + "\r", + " pm.variables.set(\"uri\", URI);\r", + " pm.request.headers.upsert({ key: \"Authorization\", value: \"\" });\r", + " pm.request.headers.upsert({ key: \"Accept\", value: \"application/json\" });\r", + " pm.request.headers.upsert({ key: \"Content-Type\", value: \"application/json\" });\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Local variables could not be set.\");\r", + "}\r", + "\r", + "/****************************************************************************************\r", + "* Functions\r", + "****************************************************************************************/\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, { - "name": "=====> Target =====>", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- Target --------------------------------------------------\");", - "/****************************************************************************************", - "* ", - "* Here starts the execution of specific validation tests", - "* ", - "****************************************************************************************/", - "", - "", - "/****************************************************************************************", - "* Loading Input Data", - "****************************************************************************************/", - "try {", - " var URI;", - " URI = pm.environment.get(\"dummyUri\");", - "", - "} catch (error) {", - " console.log(\"! Environment variables could not be loaded.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Setting up Local Variables and Preparing the Request", - "****************************************************************************************/", - "try {", - " pm.variables.clear();", - "", - " pm.variables.set(\"uri\", URI);", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", - "", - "} catch (error) {", - " console.log(\"! Local variables could not be set.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Functions", - "****************************************************************************************/", - "", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [], - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] + "listen": "test", + "script": { + "exec": [ + "/****************************************************************************************\r", + "* Clearing Variables \r", + "****************************************************************************************/\r", + "try {\r", + " pm.environment.clear();\r", + " pm.collectionVariables.clear();\r", + " pm.variables.clear();\r", + "\r", + "} catch (error) {\r", + " console.log(\"! Collection variables could not be set.\");\r", + "}\r", + "console.log(pm.collectionVariables)\r", + "console.log(pm.environment)\r", + "console.log(pm.variables)" + ], + "type": "text/javascript" + } } - ] - }, - { - "name": "=====> JustJumpToTheEnd =====>", - "item": [ - { - "name": "=====> JustJumpToTheEnd =====>", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "console.log(\"\\n----- JustJumpToEnd --------------------------------------------------\");", - "/****************************************************************************************", - "* ", - "* This is a request for daily working with the Validator.", - "* It just makes the program flow jumping to the Request named \"=====> End\".", - "* ", - "****************************************************************************************/", - " ", - " ", - "/****************************************************************************************", - "* Loading Input Data", - "****************************************************************************************/", - "try {", - " var URI;", - " URI = pm.environment.get(\"dummyUri\");", - "", - "} catch (error) {", - " console.log(\"! Environment variables could not be loaded.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Setting up Local Variables and Preparing the Request", - "****************************************************************************************/", - "try {", - " pm.variables.clear();", - "", - " postman.setNextRequest(\"=====> End\");", - "", - " pm.variables.set(\"uri\", URI);", - " pm.request.headers.upsert({key:\"Accept\", value:\"application/json\"});", - "", - "} catch (error) {", - " console.log(\"! Local variables could not be set.\");", - "}", - "", - "", - "/****************************************************************************************", - "* Functions", - "****************************************************************************************/", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [], - "url": { - "raw": "{{uri}}", - "host": [ - "{{uri}}" - ] - } - }, - "response": [] + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{uri}}", + "host": [ + "{{uri}}" + ] } - ] - }, + }, + "response": [] + } + ] + }, + { + "name": "Termination", + "item": [ { "name": "=====> End", "item": [ From 1c13583f82fcbf1097dc54734e1715b8977e0211 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 08:50:32 +0100 Subject: [PATCH 41/79] Update FormulatingCommitMessages.md --- .../FormulatingCommitMessages.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md b/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md index 4a37a5e5..bd47b1a0 100644 --- a/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md +++ b/doc/PreparingSpecifying/FormulatingCommitMessages/FormulatingCommitMessages.md @@ -15,6 +15,13 @@ Such review is not just "additional work", but also time critical, because the s - It's better to make more often Commits and to use just the subject line. - Otherwise describe all covered aspects with similarly styled statements in the body of the commit message. +The commit message dialogues at GitHub and VSCode are slightly different. + +|**GitHub**|**VSCode**| +|---|---| +|The subject line and body have own text fields.|There is only a single textfield (add linebreaks
like in any regular editor to separate subject line and body).| +|![commit_2](https://user-images.githubusercontent.com/57349523/155980718-cbbb2d14-89c7-4938-9e15-70253f7252e3.jpg)|![commit_1](https://user-images.githubusercontent.com/57349523/155980716-30b63626-4f73-4268-9851-cbefc6d24619.jpg)| + ### Subject line and Body of Pull-Request - In regards to the subject line, apply the same rules as for Commits @@ -42,11 +49,4 @@ Adding the _Fixes_ statement to the body of the Pull-Request is really a must, b - In case of need for clarification, formulate questions. -The commit message dialogues at GitHub and VSCode are slightly different. - -|**GitHub**|**VSCode**| -|---|---| -|The subject line and body have own text fields.|There is only a single textfield (add linebreaks
like in any regular editor to separate subject line and body).| -|![commit_2](https://user-images.githubusercontent.com/57349523/155980718-cbbb2d14-89c7-4938-9e15-70253f7252e3.jpg)|![commit_1](https://user-images.githubusercontent.com/57349523/155980716-30b63626-4f73-4268-9851-cbefc6d24619.jpg)| - [<- Back to Formulating Issues](../FormulatingIssues/FormulatingIssues.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Managing Conflicts ->](../ConflictManagement/ConflictManagement.md) From b5ae11448e207d4e527346603114d7ebc8669763 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 09:58:05 +0100 Subject: [PATCH 42/79] Update AvoidingConflicts.md --- .../AvoidingConflicts/AvoidingConflicts.md | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/doc/PreparingSpecifying/AvoidingConflicts/AvoidingConflicts.md b/doc/PreparingSpecifying/AvoidingConflicts/AvoidingConflicts.md index 409561b2..f3a8df46 100644 --- a/doc/PreparingSpecifying/AvoidingConflicts/AvoidingConflicts.md +++ b/doc/PreparingSpecifying/AvoidingConflicts/AvoidingConflicts.md @@ -2,30 +2,36 @@ As described in [Managing Conflicts](../ConflictManagement/ConflictManagement.md), creating conflicts is inherent to several persons working on copies of the same code or document, but probability of conflicts can significantly be reduced. -Examples: -* Person A and person B are working in parallel. They are organizing their work in **small** packages. Person A creates a _feature branch_, makes 5 changes on the code and _merges_ again into the common _develop_ branch. Same for person B. In this example, person B has 5 chances to get into conflict with 5 changes made by person A in meantime. -* Person A and person B are working in parallel. They are organizing their work in **big** packages. Person A creates a _feature branch_, makes 50 changes on the code and _merges_ again into the common _develop_ branch. Same for person B. In this example, person B has 50 chances to get into conflict with 50 changes made by person A in meantime. - -Without doing exact calculations, it is obvious that working in parallel for long periods can rapidly increase the chances for conflicts. - -It is also obvious that there are two root causes of conflicts that have to coincident: -* Own changes -* Changes, which have been made by other members of the team - -In principle, it can be assumed that the number of changes, which are made by other members of the team during some time period, is a matter of coincidence. -So the only way of keeping the number of potential source of conflicts low is keeping the time between creating a branch and _merging_ it short. +Without doing exact calculations, it is obvious that working in parallel for long periods is increasing chances for conflicts. +So one method for keeping the number of conflicts low is minimizing the time period between creating a _feature branch_ and _merging_ it back into _develop_. Several persons working in parallel does not necessarily mean creating conflicts, if these persons would work on different parts of the code. +Unfortunately, Git doesn't indicate the code segments, which are currently under change in separate branches. The following proceeding is recommended and also described in the step-by-step guidelines for [Documenting an Issue](../DocumentingAnIssue/DocumentingAnIssue.md), [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md) and [Completing an Issue](../CreatingMergeRequest/CreatingMergeRequest.md): * Create _Issues_ for describing fixes, but also features! -* Assign these _Issues_ to concrete persons, and take care that different persons are working on different parts of the code or document -* Keep the scope of the individual _Issue_ small (effort for 30 minutes up to 1 day in maximum) -* Only work on _Issues_ that are assigned to yourself -* Before starting to work, read the _Issue_ in deep detail and add notes about all necessary changes -* When starting to work, update your local copy of the _develop branch_ first, and create a fresh _feature branch_ [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md) second -* Focus on a single _Issue_ at a time and keep going until all necessary changes are completed -* Double check completeness and correctness of the changes, _merge_ them into the common _develop branch_ right after [Completing an Issue](../CreatingMergeRequest/CreatingMergeRequest.md), close the _Issue_ and delete your local _feature branch_. +* Assign every _Issue_ to exactly one person and take care that persons are working on separate parts of the code. +* Keep the scope of the individual _Issue_ small (effort for 30 minutes up to 1 day in maximum). +* Exclusively work on _Issues_ that are assigned to yourself (if necessary change the assignment, but coordinate this step with the former assignee). +* Before starting to work, read the _Issue_ in deep detail and add notes about all necessary changes. +* When starting to work, update your local _develop branch_ first, and create a fresh _feature branch_ for [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md) from your updated local _develop branch_ second. +* Focus on a single _Issue_ at a time and keep going until all necessary changes have been completed. +* Double check completeness and correctness of the changes. +* Replicate your local _feature branch_ to Github. +* Create a _Pull-Request_ from the remote _feature branch_ into the remote _develop branch_ right after [Completing an Issue](../CreatingMergeRequest/CreatingMergeRequest.md). +* Define a team member to be _Reviewer_. If you wouldn't be _CodeOwner_, the _CodeOwner_ should be automatically listed as _Reviewer_. +* Assign the _Pull-Request_ to the person, who shall consolidate potential feedback and execute the _Merge_. +* Deal with the feedback as soon as some has been provided. +* If a second review would be required, don't forget to push the circular arrows. +* As soon as all comments have been resolved, merge the remote _feature branch_ into the remote _develop branch_. +* Delete the remote _feature branch_. +* Make sure the underlaying _Issue_ has been closed. +* Delete the local _feature branch_. + +Additional hints: +* Github produces a lot of emails. Your _Reviewer_ might overlook the request for review. Potentially, it make sense sending a separate email with a little bit of useful information and a direct link into the _Pull-Request_. +* Be frugal with appointing _Reviewers_. Reviewing is work. If you would appoint several _Reviewers_, you wouldn't know, who is actually active. In worst case, you would do the _Merge_ while some _Reviewers_ are still in the process. +* If you would have been appointed to be _Reviewer_, conclude the review as soon as possible. Chances of conflicts are constantly increasing until the _Merge_. Often, the CodeOwner would like to start working on the next _Issue_, but can't until the current one has been _merged_. Over the intention of creating small packages, it shall not been forgotten that the _develop branch_ shall always contain an executable code. It is not planned to _merge_ partly solved problems or half of an _Issue_. From 4b6666b3dc95df8ad971bcac5fd9b8c3017d7cb8 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 10:29:37 +0100 Subject: [PATCH 43/79] Update DocumentingAnIssue.md --- .../DocumentingAnIssue/DocumentingAnIssue.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/PreparingSpecifying/DocumentingAnIssue/DocumentingAnIssue.md b/doc/PreparingSpecifying/DocumentingAnIssue/DocumentingAnIssue.md index eb6a0923..e9ed7287 100644 --- a/doc/PreparingSpecifying/DocumentingAnIssue/DocumentingAnIssue.md +++ b/doc/PreparingSpecifying/DocumentingAnIssue/DocumentingAnIssue.md @@ -1,5 +1,11 @@ # Documenting an Issue +Using the GitHub webGUI is recommended for documenting _Issues_. +Formulate title and body according to the guidelines for [Formulating Issues](../FormulatingIssues/FormulatingIssues.md). +Put _Assignee_, _Label_ and _Milestone_. + +Alternatively, you can create _Issues_ in VSCode. + Click on the GitHub symbol to the left of the VSCode window. ![createIssuePicture1](./pictures/createIssue_01.png) @@ -27,4 +33,4 @@ Complete creating the _Issue_ by clicking the tick in the upper right corner and If the creation of the _Issue_ has been confirmed, it has also been automatically published on the original repository on GitHub. -[<- Back to Connecting VSCode with GitHub ->](../VSCode2GitHub/VSCode2GitHub.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Processing an Issue ->](../ProcessingAnIssue/ProcessingAnIssue.md) \ No newline at end of file +[<- Back to Connecting VSCode with GitHub ->](../VSCode2GitHub/VSCode2GitHub.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Processing an Issue ->](../ProcessingAnIssue/ProcessingAnIssue.md) From 9d9ebe4cca2d57ac06777034f6b55b74ac21e8b7 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Thu, 12 Jan 2023 10:45:11 +0100 Subject: [PATCH 44/79] Change Agenda of Introduction --- doc/Introduction/Agenda.md | 43 ++++++++------------------------------ 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/doc/Introduction/Agenda.md b/doc/Introduction/Agenda.md index 831dfff6..4cc5b59b 100644 --- a/doc/Introduction/Agenda.md +++ b/doc/Introduction/Agenda.md @@ -1,37 +1,12 @@ -# Agenda of an Introduction Session -_Please, add the subjects and questions you would like to be addressed during the introduction session below._ -## Platform -_What would you like to know about the MW SDN platform?_ - - - - -## Applications -_What would you like to know about the types of applications that will be implemented on the MW SDN platform, respectively which applications come into question for being specified as an own project during the workshop series?_ -1. What type of function shall be implemented as microservice and what kind of function shall be handeled by other applications? How does an application qualify to be implemented as a microservice? -2. Is it possible to specify microservices for not completeley defined parts of the SDN model, example MacAddressTablerecorder? -3. How will the microservices be tested? - -## Tools for Specifying Applications -_What would you like to know about the tools and languages, which we will use for specifying applications?_ - - - - -## Processes for Specifying Applications -_What would you like to know about the processes, which we will use for specifying applications?_ - - - - -## Workshop Series -_What yould you like to know about how we will organize the workshop series?_ - - - - -## Any other business -_What else should we discuss during the introduction session?_ +# Agenda of an Introduction Session +Action items in the training for ApplicationOwners have changed. +Please, don't create an _Issue_ for contributing to the agenda of an introduction session, but for improving the documentation. +Is there a mistake in the training material? +It there still something unclear or missing? +Please, create an _Issue_ in the ApplicationPattern repository that documents a need for improving the documentation. +Assign it to openBackhaul. +Label should be _documentation_. +Milestone should be the next release of the specification according to semantic versioning (2.x.y_spec). From 58900e07ee59f3027a7496655775bb5e0bb645da Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 10:46:23 +0100 Subject: [PATCH 45/79] Update Agenda.md --- doc/Introduction/Agenda.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Introduction/Agenda.md b/doc/Introduction/Agenda.md index 4cc5b59b..b49c7924 100644 --- a/doc/Introduction/Agenda.md +++ b/doc/Introduction/Agenda.md @@ -1,6 +1,6 @@ # Agenda of an Introduction Session -Action items in the training for ApplicationOwners have changed. +Action items of the training for ApplicationOwners have changed. Please, don't create an _Issue_ for contributing to the agenda of an introduction session, but for improving the documentation. Is there a mistake in the training material? From 6336e066a17ee0aef83fd833e5ef91206fb9203e Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:03:19 +0100 Subject: [PATCH 46/79] Update CreatingCommit.md --- doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md b/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md index 3ca2e908..24eebca5 100644 --- a/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md +++ b/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md @@ -43,12 +43,13 @@ After authentication, VSCode will try to push the changes to the remote reposito It would not succeed, if you would neither be owner nor _Contributor_ to the addressed repository. In such case you would have to address your _Push_ to a _Fork_ (copy) of the original repository in your own GitHub account (see also [Forking Workflow](../ForkingWorkflow/ForkingWorkflow.md)). -Even if you are _Contributor_ to the addressed repository, you need permission to _Push_ into the addressed branch. -This might not be given, in case you forgot to create a feature branch from the _Issue_ (see [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md)) before starting to work. -In such case, you would now fail to push your commit into _develop_ or _main_ branch. +Even if you are _Contributor_ to the addressed repository, you need permission to _Push_ into the addressed branch. +This might not be given, in case you forgot to create a feature branch from the _Issue_ (see [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md)) before starting to work. ![vsc_12](https://user-images.githubusercontent.com/57349523/152162653-59a0e1d1-dd16-4f9c-bd88-3ccfae0c45cd.jpg) +As you are failing to push your commit into _develop_ or _main_ branch, you can try saving your contribution by following the steps that are described beginning with _"Starting to actually work on the Issue"_ in [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md)). In most cases, changes don't get lost. + If you are _Contributor_ (as the ApplicationOwner you certainly are) and properly created a feature branch before starting to make changes, the latest state of the feature branch will now be published in the original repository on GitHub. [<- Back to Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Completing an Issue ->](../CreatingMergeRequest/CreatingMergeRequest.md) From 343c15d22e81df61a030cc47fe7e43da77e113c1 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:05:18 +0100 Subject: [PATCH 47/79] Update CreatingCommit.md --- doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md b/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md index 24eebca5..db66f37b 100644 --- a/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md +++ b/doc/PreparingSpecifying/CreatingCommit/CreatingCommit.md @@ -48,8 +48,8 @@ This might not be given, in case you forgot to create a feature branch from the ![vsc_12](https://user-images.githubusercontent.com/57349523/152162653-59a0e1d1-dd16-4f9c-bd88-3ccfae0c45cd.jpg) -As you are failing to push your commit into _develop_ or _main_ branch, you can try saving your contribution by following the steps that are described beginning with _"Starting to actually work on the Issue"_ in [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md)). In most cases, changes don't get lost. +As you are failing to push your commit into _develop_ or _main_ branch, you can try saving your contribution by following the steps that are described beginning with _"Starting to actually work on the Issue"_ in [Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md). In most cases, changes don't get lost. -If you are _Contributor_ (as the ApplicationOwner you certainly are) and properly created a feature branch before starting to make changes, the latest state of the feature branch will now be published in the original repository on GitHub. +If you are _Contributor_ (as the ApplicationOwner you certainly are) and properly created a feature branch before starting to make changes, the latest state of the feature branch is now publicly available on GitHub. [<- Back to Processing an Issue](../ProcessingAnIssue/ProcessingAnIssue.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) - - - [Ahead to Completing an Issue ->](../CreatingMergeRequest/CreatingMergeRequest.md) From 1ef99397c25ee45646ed556826184ef5885bd76e Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:33:43 +0100 Subject: [PATCH 48/79] Update CreatingMergeRequest.md --- .../CreatingMergeRequest.md | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/doc/PreparingSpecifying/CreatingMergeRequest/CreatingMergeRequest.md b/doc/PreparingSpecifying/CreatingMergeRequest/CreatingMergeRequest.md index 5619b97e..312a3db0 100644 --- a/doc/PreparingSpecifying/CreatingMergeRequest/CreatingMergeRequest.md +++ b/doc/PreparingSpecifying/CreatingMergeRequest/CreatingMergeRequest.md @@ -1,4 +1,4 @@ -# Completing an Issue and creating a Merge Request +# Completing an Issue and creating a Pull-Request After _committing_ all changes, which are necessary to complete the _Issue_, into the local _feature branch_ it is time for consolidating your contribution into the public _develop_ branch (_origin/develop branch_). @@ -15,58 +15,53 @@ For this purpose, you have to _merge_ the _origin/develop branch_ into your loca * ... and chose the _origin/develop branch_ from the list. ![RequestingMerge8](./pictures/RequestingMerge_08.png) -* If there would be any _merge conflicts_, they would show up now. +* If there would be any _conflicts_, they would show up now. * After analyzing two conflicting versions of the code, you could decide for the versions (current, incoming or both) to become part of your local _feature branch_. ![RequestingMerge9](./pictures/RequestingMerge_09.png) -* Save the files, which got changed during resolving all conflicts by Ctrl+s and _stage_ them for being _committed_ during the _merge_ of the _origin/develop branch_ into your local _feature branch_. +* Save the files, which got changed during resolving all _conflicts_ by Ctrl+s and _stage_ them for being _committed_ during the _merge_ of the _origin/develop branch_ into your local _feature branch_. ![RequestingMerge10](./pictures/RequestingMerge_10.png) * Confirm the _merge_ of the _origin/develop branch_ into your local _feature branch_ ... ![RequestingMerge11](./pictures/RequestingMerge_11.png) -* ... and _push_ your local _feature branch_ with the resolved conflicts to the remote repository (creates or updates remote _feature branch_). +* ... and _push_ your local _feature branch_ with the resolved _conflicts_ to the remote repository (creates or updates remote _feature branch_). ![RequestingMerge12](./pictures/RequestingMerge_12.png) -In the second phase of the process, you have to create the _Merge Request_ for consolidating the remote copy of your _feature branch_, which is now cleared from conflicts, into the _origin/develop branch_. +In the second phase of the process, you have to create the _Pull-Request_ for consolidating the remote copy of your _feature branch_ into the _origin/develop branch_. -* Click on the pull request icon at the repository you would like to change. +* Click on the _Pull-Request_ icon at the repository you would like to change. ![RequestingMerge13](./pictures/RequestingMerge_13.png) -* VSCode is now automatically filling the source and target branch into a form and you just have to double check. -Please, add a _Merge Request_ message, which is complying the chapter about [Formulating Merge Request Messages](../FormulatingCommitMessages/FormulatingCommitMessages.md) and click Create. +* VSCode is now automatically filling the source and target branch names into a form and you just have to double check. +Please, add a _Pull-Request_ message, which is complying the chapter about [Formulating _Pull-Request_ Messages](../FormulatingCommitMessages/FormulatingCommitMessages.md) and click Create. ![RequestingMerge14](./pictures/RequestingMerge_14.png) -* Alike in the following picture, the _Merge Request_ does not create any conflicts and can directly be _merged_ after reviewing the changes. As you can see, the _Merge Request_ is not involving your local repository. The _Merge_ is happening exclusively in the remote repository on GitHub. +* Alike in the following picture, the _Pull-Request_ does not create any conflicts and can directly be _merged_ after reviewing the changes. As you can see, the _Pull-Request_ is not involving your local repository. The _Merge_ is happening exclusively in the remote repository on GitHub. ![RequestingMerge15](./pictures/RequestingMerge_15.png) -* At least the originator of the _Issue_, which is underlying the branch that is now requested to be merged, should be marked as a Reviewer. +* At least the originator of the _Issue_, which is underlying the branch that is now requested to be merged, should be marked as a _Reviewer_. ![RequestingMerge16](./pictures/RequestingMerge_16.png) -* The _Merge Request_ should be assigned to the assignee of the underlying _Issue_, because the assignee of the _Issue_ should be the person, who merges the results into the _origin/develop branch_ and deletes the _feature branch_. +* The _Pull-Request_ shall be assigned to the person, who is consolidating potential feedback, merging the _Pull-Request_ into the _origin/develop branch_ and deleting the _feature branch_. ![RequestingMerge16](./pictures/RequestingMerge_15a.png) In the third phase of the process, it is recommended to immediately clean up your local repository. -Your local _feature branch_ has been copied to the remote repository. So your data is save. -After successfully _merging_ into the _origin/develop branch_, the remote _feature branch_ will be automatically(!) deleted, but your local copy is disconnected from further proceeding. -For avoiding accumulating useless branches in your local repository, it is recommended to delete the local _feature branch_ right after formulating the _Merge Request_. +After successfully _merging_ into the _origin/develop branch_, the remote _feature branch_ should have been deleted, but the local copy is still existing. +For avoiding accumulation of useless branches in your local repository, it is recommended to delete the local _feature branch_ right after successfully _merging_ into the _origin/develop branch_. * For deleting the obsolete _feature branch_, you have to leave it first. So open the list of branches ... ![RequestingMerge17](./pictures/RequestingMerge_17.png) -* ... and chose the _develop branch_ from the list. +* ... and chose the _develop branch_ from the list. ![RequestingMerge18](./pictures/RequestingMerge_18.png) * Open the menu at the repository, which you would like to clean up, click on "Branch löschen"... ![RequestingMerge19](./pictures/RequestingMerge_19.png) -* ... and chose the obsolete _feature branch_ from the list. +* ... and chose the obsolete _feature branch_ from the list. ![RequestingMerge20](./pictures/RequestingMerge_20.png) -After conducting the _merge_ -* the _Issue_, which initiated creation of the _feature branch_, will be closed -* and the remote copy of the _feature branch_ will be automatically(!) deleted. - [<- Back to Creating a Commit](../CreatingCommit/CreatingCommit.md) - - - [Up to Preparing for Specifying Applications](../PreparingSpecifying.md) From 90a3bb0483d83b9069fd2ca83eca7cf59f332189 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Thu, 12 Jan 2023 11:47:23 +0100 Subject: [PATCH 49/79] Correct new proceeding in Agenda --- doc/Introduction/Agenda.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/Introduction/Agenda.md b/doc/Introduction/Agenda.md index b49c7924..fe6d7bf1 100644 --- a/doc/Introduction/Agenda.md +++ b/doc/Introduction/Agenda.md @@ -7,6 +7,8 @@ Is there a mistake in the training material? It there still something unclear or missing? Please, create an _Issue_ in the ApplicationPattern repository that documents a need for improving the documentation. -Assign it to openBackhaul. +Assign it to yourself. Label should be _documentation_. Milestone should be the next release of the specification according to semantic versioning (2.x.y_spec). + +Execute the _Issue_ and address a _Pull-Request_ for consolidating your contribution into the official documentation. From b7e5ecfd79378fac443729a2ad37f53fdb6eb156 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 14:34:43 +0100 Subject: [PATCH 50/79] Update StructureOfServices.md --- .../StructureOfServices.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md index 5fe42e77..ac468c8f 100644 --- a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md +++ b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md @@ -1,16 +1,16 @@ -# Structure of Services +# Structure of Operations -There is no clear right or wrong for structuring services, but some general guidance that should be kept across all applications. +There is no clear right or wrong for structuring _Operations_, but some general guidance that should be kept across all applications. **Explicit** -During later operation of the modular application layer, people will conclude from the service names on the offered functions. -A service should focus on doing a single thing and this thing should be precisely described in its naming. +During later operation of the modular application layer, people will conclude from the _OperationName_ on the offered functions. +An _Operation_ should focus on doing a single thing and this thing should be precisely described in its naming. Examples: _/v1/notify-approvals_ and _/v1/notify-withdrawn-approvals_ -If services would implement diverse functions depending on the values of the parameters, which are sent in the request body, it would not support transparency. +If _Operations_ would implement diverse functions depending on the values of the parameters, which are sent in the RequestBody, it would not support transparency. **Atomic** It might happen that we need an output, which results from a process comprising several steps. -During structuring the services, it should be considered that there might be future applications that require the output of just one or several of these steps. +During structuring the _Operations_, it should be considered that there might be future applications that require the output of just a subset of these steps. So, wise substructuring might cause some additional effort in the beginning, but it supports avoiding redundancy of implementations. Every piece of code needs to be maintained as long as it will be in use. Need for updating will in tendency be reduced to a single, relatively small place, if wisely substructured. @@ -23,11 +23,11 @@ There are two different ways of leading. Example: "Clean up the yard!" vs. "Make sure the yard is clean!" Telling the desired target state leaves it to the implementation to decide about how to reach that state. This usually leads to more efficient implementations and it also supports encapsulating the impact of changes. -As a side effect, the same service can be called over and over again, successful execution always leads to the same result (which is the target state). +As a side effect, the same _Operation_ can be called over and over again, because successful execution always leads to the same condition (which is the target state). This supports debugging the overall system of applications. Unfortunately, this concept cannot be applied in all cases and often it is not that explicit. -Nevertheless, it is recommended to use it as often as possible. -Example: _/v1/notify-approvals_ creates or updates a subscription for a specific combination of application name and release number. -(It does not create another subscription, if there is already one for the same combination of application name and release number. -There is no _update subscription_ service required. -Using the _subscription_ service again with the same combination of application name and release number, but different value of IP address and port, will define a different target state.) +Nevertheless, it is recommended to apply it as often as possible. +Example: _/v1/notify-approvals_ creates or updates a subscription for a specific combination of _ApplicationName_ and _ReleaseNumber_. +(It does not create another subscription, if there is already one for the same combination of _ApplicationName_ and _ReleaseNumber_. +There is no _/v1/update subscription_ _Operation_ required. +Using the subscription _Operation_ again with the same combination of _ApplicationName_ and _ReleaseNumber_, but different values of IP address and port, will define a different target state.) From 8e1d68003226ad23aaed7f2186dea0e5c43ea241 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 14:42:27 +0100 Subject: [PATCH 51/79] Update StructureOfServiceNames.md --- .../StructureOfServiceNames.md | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md b/doc/ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md index 7423030f..afca96a2 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md @@ -1,31 +1,27 @@ -# Structure of Service Names +# Structure of OperationNames -The name of a service shall be formulated like an order (e.g. _calculate-mw-capacity_); meaning it shall start with a verb, followed by an object and potentially further details. +The name of an _Operation_ shall be formulated like an order (e.g. _calculate-mw-capacity_); meaning it shall start with a verb, followed by an object and potentially further details. It shall be composed from two to five meaningful words (another three words would be put on top for "InGenericRepresentation", wherever applicable). -The service shall already be explained by its naming. -The purpose of the application shall be clear from reading the service names. +The _Operation_ shall already be explained by its naming. +The purpose of the application shall be clear from reading the _OperationNames_. -Service names must be unique, at least within scope of the individual application. -It is recommended to read service names at several existing applications, preferably with similar purpose, for becoming sensitive for choosing names, which allow to distinguish from existing services at other applications. +_OperationNames_ must be unique, at least within scope of the individual application. +It is recommended to read the list of _OperationNames_ at several existing applications, preferably with similar purpose, for becoming sensitive for choosing names, which allow to distinguish from existing _Operations_ at other applications. -Services, which are for ... +_Operations_, which are for ... * ... retrieving data, might start with "provide...". -* ... creating multiple **separate instances** every time they get called, might start with "create...". +* ... creating multiple **separate instances** every time they get called, might start with "create..." (remark: not idempotent!). * ... overwriting the values of the **selfsame** object every time they get called, might start with "update...". -If an alternative verb would describe the effect of the operation more precisely, the alternative verb shall be preferred. +If an alternative verb would describe the effect of the _Operation_ more precisely, the alternative verb shall be preferred. -Service names shall start with a slash followed by a version identifier (e.g. /v1). -A second slash shall separate the version identifier from the descriptive part of the service name. -Hyphens have to be used for separating words in the descriptive part of the service name. -Service names shall exclusively contain lower case letters. +_OperationNames_ shall start with a slash followed by a version identifier (e.g. /v1). +A second slash shall separate the version identifier from the descriptive part of the _OperationName_. +Hyphens have to be used for separating words in the descriptive part of the _OperationName_. +_OperationNames_ shall exclusively contain lower case letters. They must not contain any special characters (like &, * , ?) apart from hyphens. -Example: _/v1/provide-proper-service-names_ - -Please, take already existing definitions in the ServiceList template or other applications as a reference. - - - +Example: _/v1/provide-proper-operation-names_ +Please, take already existing definitions in the ServiceList template or other applications as a reference. From f8459dc3586476ec49ded7d0e50aea262fdc546d Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:19:00 +0100 Subject: [PATCH 52/79] Update StructureOfReleaseNumbers.md --- .../StructureOfReleaseNumbers.md | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md b/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md index fa1b872b..987e39bc 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md @@ -1,39 +1,39 @@ -# Structure of Release Numbers +# Structure of _ReleaseNumbers_ ### Summary -Release Numbers shall follow the concept of Semantic Versioning (with some deviations that are described below). -Given a version number MAJOR.MINOR.PATCH, increment the: +_ReleaseNumbers_ shall follow the concept of Semantic Versioning (with some deviations that are described below). +Given a version number MAJOR.MINOR.PATCH, increment the ...: -- MAJOR version when you make incompatible API changes, -- MINOR version when you add functionality in a backwards compatible manner, and -- PATCH version when you make backwards compatible bug fixes. +- ... MAJOR version when you make incompatible API changes, +- ... MINOR version when you add functionality in a backwards compatible manner, and +- ... PATCH version when you make backward compatible bug fixes. ### Example - Situation 1: A new application gets specified. -The specification will be identified by the release number 1.0.0 +The specification will be identified by the _ReleaseNumber_ 1.0.0 - Situation 2: After publishing, the implementer requests for clarification. -Comments get added and corrected in the existing 1.0.0 release (backwards compatible bug fixes). -The resulting specification will be identified by the release number 1.0.1 +Comments get added and corrected in the existing 1.0.0 release (backward compatible bug fixes). +The resulting specification will be identified by the _ReleaseNumber_ 1.0.1 - Situation 3: After putting release 1.0.1 into operation, users are requesting for resulting temperature values to be provided in Celsius instead of Kelvin. -The existing operations gets specified and implemented for a second time, but now providing the result in Celsius instead of Kelvin. -The operations for Celsius are added (backward compatible) and run in parallel to the ones for Kelvin, which just get marked as deprecated (also backward compatible). -The resulting specification will be identified by the release number 1.1.0 +The existing _Operation_ gets specified and implemented for a second time, but now providing its result in Celsius instead of Kelvin. +The new _Operation_ for Celsius is added (backward compatible) and runs in parallel to the one for Kelvin, which just gets marked as deprecated (also backward compatible). +The resulting specification will be identified by the _ReleaseNumber_ 1.1.0 - Situation 4: After a while, several wishes for additional functionality have been addressed. -Further on, the existing operation providing its result in Kelvin shall be deleted, because it permanently confuses users (incompatible API change). -The resulting specification will be identified by the release number 2.0.0 +Further on, the existing _Operation_ providing its result in Kelvin shall be discontinued, because it permanently confuses users (incompatible API change). +The resulting specification will be identified by the _ReleaseNumber_ 2.0.0 -- Situation 5: The specification 2.0.0 has been finished and develop Branch got merged into main Branch for publishing it to potential implementers. -The new content of the main Branch gets tagged with "2.0.0_spec" by the PlatformOwner (no other than main branch gets tagged). +- Situation 5: The specification 2.0.0 has been finished and _develop branch_ got merged into _main branch_ for publishing it to potential implementers. +The new content of the _main branch_ gets tagged with "2.0.0_spec" by the PlatformOwner (exclusively the _main branch_ gets tagged). -- Situation 6: The specification 2.0.0 has been implemented and the implementer merged his code into the main Branch. -The new content of the main Branch gets tagged with "2.0.0_imp" by the PlatformOwner (no other than main branch gets tagged). +- Situation 6: The specification 2.0.0 has been implemented and the implementer merged his code into the _main branch_. +The new content of the _main branch_ gets tagged with "2.0.0_imp" by the PlatformOwner (exclusively the _main branch_ gets tagged). ### Specification @@ -59,16 +59,16 @@ Major version 1.0.0 is for initial development. 5. Version 1.0.0 defines the public API. The way in which the version number is incremented after this release is dependent on this public API and how it changes. -6. Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced. +6. Patch version Z (x.y.Z | x > 0) MUST be incremented if only backward compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior. -7. Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API. +7. Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backward compatible functionality is introduced to the public API. It MUST be incremented if any public API functionality is marked as deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within the private code. It MAY include patch level changes. Patch version MUST be reset to 0 when minor version is incremented. -8. Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API. +8. Major version X (X.y.z | X > 0) MUST be incremented if any backward incompatible changes are introduced to the public API. It MAY also include minor and patch level changes. Patch and minor versions MUST be reset to 0 when major version is incremented. @@ -79,9 +79,9 @@ Patch and minor versions MUST be reset to 0 when major version is incremented. 11. _[official text has been removed]_ 12. _[complement to the official rules]_ -Since specification and implementation get merged into the same main Branch on GitHub at different points in time, -\- the tag that is identifying the specification of a release shall be composed from the release number and "_spec" and -\- the tag that is identifying the implementation of a release shall be composed from the release number and "_imp". +Since specification and implementation get merged into the same _main branch_ on GitHub at different points in time, +\- the tag that is identifying the specification of a release shall be composed from the _ReleaseNumber_ and "_spec" and +\- the tag that is identifying the implementation of a release shall be composed from the _ReleaseNumber_ and "_imp". . _Source:_ From 2d442ce2e6ac9c0f0add4291eb0b990a9fcef8f7 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:19:33 +0100 Subject: [PATCH 53/79] Update StructureOfReleaseNumbers.md --- .../StructureOfReleaseNumbers/StructureOfReleaseNumbers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md b/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md index 987e39bc..805142e7 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md @@ -81,7 +81,7 @@ Patch and minor versions MUST be reset to 0 when major version is incremented. 12. _[complement to the official rules]_ Since specification and implementation get merged into the same _main branch_ on GitHub at different points in time, \- the tag that is identifying the specification of a release shall be composed from the _ReleaseNumber_ and "_spec" and -\- the tag that is identifying the implementation of a release shall be composed from the _ReleaseNumber_ and "_imp". +\- the tag that is identifying the implementation of a release shall be composed from the _ReleaseNumber_ and "_impl". . _Source:_ From e6a988b3da074fb077cbf30b79dbaed5b7a612cb Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:56:57 +0100 Subject: [PATCH 54/79] Update StructureOfUuids.md --- .../StructureOfUuids/StructureOfUuids.md | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md index 3f77ea9c..d6766e69 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md @@ -1,10 +1,12 @@ # Structure of UUIDs -UUIDs are used for identifying the individual objects within the structure of the configuration data inside the applications. +UUIDs are used for identifying the logical objects within the structure of the configuration data inside the applications. Example: If interfaces A and B are identified by UUIDs, it suffices to list the two UUIDs to express a connection between the two interfaces. -Obviously, UUIDs have to be unique within the network domain for expressing connections between interfaces at different applications. -Harmonizing UUIDs across all applications helps reading and navigating through the configuration data of the individual applications. +Obviously, UUIDs have to be unique within the network domain for unambiguously describing a connection between interfaces at different applications. +Uniqueness could have been assured by an algorithm for creating qualified random strings, but it has been decided to create UUIDs from information about the objects, which are to be identified. +These harmonized UUIDs are supporting reading and navigating through the configuration data of the individual applications. +Unfortunately, it takes some training to properly put them together. **UUIDs are composed from the following information:** @@ -12,12 +14,11 @@ Harmonizing UUIDs across all applications helps reading and navigating through t **OwnApplicationID** This application identifier relates to the application that contains the data object that is identified by the UUID (name space). -It is composed from the official abbreviation of the application name composed from the uppercase letters of the application name (e.g. RO, TAR), but transferred into lowercase letters (e.g. ro, tar) and the official release number of the specification of the application that contains the data object, dots to be replaced by hyphens (e.g. 1-0-0, 1-0-1). -A hyphen is also used between abbreviation of the application name and release number. +It is composed from the official abbreviation of the _ApplicationName_ composed from the uppercase letters of the _ApplicationName_ (e.g. RegistryOffice=>RO, TypeApprovalRegister=>TAR), but transferred into lowercase letters (e.g. RO=>ro, TAR=>tar) and the official _ReleaseNumber_ of the specification of the application that contains the data object, dots to be replaced by hyphens (e.g. 1.0.0=>1-0-0, 1.0.1=>1-0-1). +A hyphen is also used between abbreviation of the _ApplicationName_ and _ReleaseNumber_. Examples: ro-1-0-0, tar-1-0-1 (Now, it should be clear why [Structure of ApplicationNames](../StructureOfApplicationNames/StructureOfApplicationNames.md) prescribes abbreviations to be unique within the modular application layer.) -If someone would find it more convinient, - UUIDs could be abstracted from OwnApplicationID inside ServiceList and ForwardingList, but OAS, CONFIGfile and test cases must contain the complete UUIDs. **LayerID** Currently the following layers are defined: @@ -28,10 +29,10 @@ Currently the following layers are defined: - prot = Protocol - tcp = TCP/IP -If the ObjectType identifies an instance of Profile (p), the LayerID is used for identifying the type of Profile. -In principle, the ApplicationOwner is free in defining Profiles and choosing the LayerID, because instances of Profile just exist within the application itself. -If an already existing Profile definition would be re-used, would be recommended to re-use the same LayerID, too. -The following LayerIDs are already in use for Profiles: +If the _ObjectType_ identifies an instance of _Profile_ (p), the _LayerID_ is used for identifying the type of _Profile_. +In principle, the _ApplicationOwner_ is free in defining _Profiles_ and choosing the _LayerID_, because instances of _Profile_ just exist within the application itself. +If an already existing _Profile_ definition would be re-used, it would be recommended to re-use the same _LayerID_, too. +The following _LayerIDs_ are already in use for _Profiles_: - action = For describing the consequent action in a generic representation - file = For storing information required for connecting to a file that is holding application data - integer = For storing a single Integer @@ -40,15 +41,15 @@ The following LayerIDs are already in use for Profiles: **ObjectType** Within the respective layers the following types of objects are defined: -- c = Client -- s = Server -- fd = ForwardingDomain (potential forwarding inside applications) -- fc = ForwardingConstruct (actual forwarding inside applications) -- link = Link (actual forwarding outside applications) -- p = Profile +- c = _Client_ +- s = _Server_ +- fd = _ForwardingDomain_ (potential forwarding inside applications) +- fc = _ForwardingConstruct_ (actual forwarding inside applications) +- link = _Link_ (actual forwarding outside applications) +- p = _Profile_ **ApiSegment** -The ApiSegment is contained in the UUIDs of OperationServers, OperationClients and FCs. +The _ApiSegment_ is contained in the UUIDs of _OperationServers_, _OperationClients_ and _FCs_. Basically, identical letters are used, but there is a slight divergence in the deep details of the semantical meanings. The **OperationServers** are categorized according to the following two aspects: From 11c8b4613d843a8f2056f9c7ec085a931d25b2fa Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 09:13:53 +0100 Subject: [PATCH 55/79] Update ElementsApplicationPattern.md --- doc/ElementsApplicationPattern/ElementsApplicationPattern.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md index 0a7a79d3..200ef28e 100644 --- a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md +++ b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md @@ -8,7 +8,6 @@ * [RESTful](./Principles/Restful/Restful.md) * [Microservice](./Principles/Microservice/Microservice.md) * [CONFIGfile](./Principles/ConfigFile/ConfigFile.md) -* **Idempotence**: In general, executing the same request (applies on Services and OaM) with the same set of attributes again, shall just lead to the same state. There shall be no error messages, which would indicate that no change has been made. This shall apply in general. Few exceptions might occur (hypothetical example: /v1/create-additional-instance), but not contradict the general principle. **Functions** * [Structure of Services](./Functions/StructureOfServices/StructureOfServices.md) From 883a44128e07ebbf56b7090b0ea2ff9ed85f34c5 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 09:17:19 +0100 Subject: [PATCH 56/79] Update StructureOfServices.md --- .../Functions/StructureOfServices/StructureOfServices.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md index ac468c8f..5f29de90 100644 --- a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md +++ b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md @@ -16,6 +16,8 @@ Every piece of code needs to be maintained as long as it will be in use. Need for updating will in tendency be reduced to a single, relatively small place, if wisely substructured. **Idempotent** +In general, executing the same request (applies on _Operations_ and _OaM_) with the same set of attributes again, shall just lead to the same state. There shall be no error messages, which would indicate that no change has been made. This shall apply in general. Few exceptions might occur (hypothetical example: /v1/create-additional-instance), but not contradict the general principle. + There are two different ways of leading. 1) You tell what to do 2) You tell the desired target state From 7010864bd19e7020be256049a10de9de4f3589ac Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:27:34 +0100 Subject: [PATCH 57/79] Update StructureOfServices.md --- .../StructureOfServices.md | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md index 5f29de90..6956d148 100644 --- a/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md +++ b/doc/ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md @@ -1,6 +1,35 @@ # Structure of Operations -There is no clear right or wrong for structuring _Operations_, but some general guidance that should be kept across all applications. +In a REST server based microservice architecture, function is triggered in a way that is very similar to calling a website in the Internet. +The 'address' of some function is composed from protocol (e.g. HTTPS), IP address, TCP port, and an individual part. +This individual part of the 'address' is called _path_ in the language we are using for specifying applications. + +Further on, targets of such 'addresses' can be categorized into _Resources_ and _Services_. +- A _Resource_ is like a parameter and calling its 'address' is for reading or changing the value of this parameter. +Configuring a device usually works like this. +- A _Service_ is like a little program, which gets executed after calling its 'address'. +Using microservices usually works like this. + +In case of the MW SDN application layer, the REST APIs of the applications are supporting both. +The _Services_ are representing the 'payload' interfaces in some sense. They are defining the purpose of the application. +_Resources_ are used for configuring the application. +So the REST APIs of the applications of MW SDN application layer are distinguishing a _ServiceLayer_ and an _OamLayer_. + +The _OamLayer_ layer, which is defined in the _ApplicationPattern_, is assumed to suffice in most cases. +So, the individual part of some specification will usually be limited to the _ServiceLayer_. + +Since the term 'Service' is used for very different things, I decided to use _Operation_ instead. +The individual part of the 'address', which is mentioned in the first paragraph, is called _OperationName_. +So, some 'address' of an _Operation_ could look like this example: 'http://192.168.0.1:80/v1/operation-name' + +Input values for such an _Operation_ would be passed in the _RequestBody_. +Results would be provided in the _ResponseBody_. + +Now, first step of the specification process is thinking about which _Operations_ are to be provided by the application. +This includes structuring the function, which is expected to be supported by the application. +Detailed definition of the input values and results will follow during describing the _OAS_. + +There is no clear right or wrong for structuring into _Operations_, but some general guidance that should be kept across all applications. **Explicit** During later operation of the modular application layer, people will conclude from the _OperationName_ on the offered functions. @@ -11,9 +40,9 @@ If _Operations_ would implement diverse functions depending on the values of the **Atomic** It might happen that we need an output, which results from a process comprising several steps. During structuring the _Operations_, it should be considered that there might be future applications that require the output of just a subset of these steps. -So, wise substructuring might cause some additional effort in the beginning, but it supports avoiding redundancy of implementations. +So, wise sub-structuring might cause some additional effort in the beginning, but it supports avoiding redundancy of implementations. Every piece of code needs to be maintained as long as it will be in use. -Need for updating will in tendency be reduced to a single, relatively small place, if wisely substructured. +Need for updating will in tendency be reduced to a single, relatively small place, if wisely sub-structured. **Idempotent** In general, executing the same request (applies on _Operations_ and _OaM_) with the same set of attributes again, shall just lead to the same state. There shall be no error messages, which would indicate that no change has been made. This shall apply in general. Few exceptions might occur (hypothetical example: /v1/create-additional-instance), but not contradict the general principle. From e0bd7c97f4d0d70c708506610fa15c0c16b99d8d Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:07:45 +0100 Subject: [PATCH 58/79] Update StructureOfUuids.md --- .../Names/StructureOfUuids/StructureOfUuids.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md index d6766e69..5a485028 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md @@ -8,7 +8,8 @@ Uniqueness could have been assured by an algorithm for creating qualified random These harmonized UUIDs are supporting reading and navigating through the configuration data of the individual applications. Unfortunately, it takes some training to properly put them together. -**UUIDs are composed from the following information:** + +## UUIDs are composed from the following information: ![UUID Structure](./pictures/uuid-structure.png) @@ -93,7 +94,9 @@ The SequenceNumber is just distinguishing objects of the same kind. It has three digits. Counting is decimal. -**Examples** + +## Examples: + | UUID | Object description | | ---- | ------------------ | | ro-1-0-0-op-s-bm-004 | OperationServer (for /v1/end-subscription) inside the RegistryOffice release 1.0.0 | From 478a8ef3eea09470e7c100f76c0e4e409f60b1f6 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:23:32 +0100 Subject: [PATCH 59/79] Update StructureOfUuids.md --- .../StructureOfUuids/StructureOfUuids.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md index 5a485028..186d8257 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md @@ -15,7 +15,8 @@ Unfortunately, it takes some training to properly put them together. **OwnApplicationID** This application identifier relates to the application that contains the data object that is identified by the UUID (name space). -It is composed from the official abbreviation of the _ApplicationName_ composed from the uppercase letters of the _ApplicationName_ (e.g. RegistryOffice=>RO, TypeApprovalRegister=>TAR), but transferred into lowercase letters (e.g. RO=>ro, TAR=>tar) and the official _ReleaseNumber_ of the specification of the application that contains the data object, dots to be replaced by hyphens (e.g. 1.0.0=>1-0-0, 1.0.1=>1-0-1). +It is composed from the official abbreviation of the _ApplicationName_ composed from the uppercase letters of the _ApplicationName_ (e.g. RegistryOffice=>RO, TypeApprovalRegister=>TAR), but transferred into lowercase letters (e.g. RO=>ro, TAR=>tar) and the official _ReleaseNumber_ of the specification of the application that contains the data object. +Dots are to be replaced by hyphens (e.g. 1.0.0=>1-0-0, 1.0.1=>1-0-1). A hyphen is also used between abbreviation of the _ApplicationName_ and _ReleaseNumber_. Examples: ro-1-0-0, tar-1-0-1 @@ -31,7 +32,7 @@ Currently the following layers are defined: - tcp = TCP/IP If the _ObjectType_ identifies an instance of _Profile_ (p), the _LayerID_ is used for identifying the type of _Profile_. -In principle, the _ApplicationOwner_ is free in defining _Profiles_ and choosing the _LayerID_, because instances of _Profile_ just exist within the application itself. +In principle, the _ApplicationOwner_ is free in defining _Profiles_ and choosing the _LayerID_, because instances of _Profile_ just exist within the scope of the application itself. If an already existing _Profile_ definition would be re-used, it would be recommended to re-use the same _LayerID_, too. The following _LayerIDs_ are already in use for _Profiles_: - action = For describing the consequent action in a generic representation @@ -58,8 +59,8 @@ The **OperationServers** are categorized according to the following two aspects: - Basic to all applications vs. Individual to this application This results in four categories: -- bm = Basic Management: Operation, which is available at this application, but all other applications, too -- im = Individual Management: Operation, which is individual for managing this application +- bm = Basic Management: _Operation_ for managing this application, but same _Operation_ is available at all other applications, too +- im = Individual Management: _Operation_, which is individual for managing this application - bs = Basic Service: Offering a service, which must be provided by all applications - is = Individual Service: Offering a services, which is individual to this application @@ -70,14 +71,14 @@ The **OperationClients** are categorized according to the following two aspects: - Basic to all applications vs. Individual to this application This results in four categories: -- bm = Basic Management: All applications have this client for executing management -- im = Individual Management: Only this application has this client for executing some management at the addressed application -- bs = Basic Services: All applications are consuming this service from the same application -- is = Individual Services: Consuming this service is individual to this application +- bm = Basic Management: All applications have this client for executing management on another application +- im = Individual Management: Only this application has this client for executing management on another application +- bs = Basic Services: All applications are consuming the same service from the same application +- is = Individual Services: It's individual to this application to consume this service UUIDs of **HttpClient** and **TcpClient** don't contain an ApiSegment. -**FCs** are inheriting the ApiSegment from the connected OperationClients. +**FCs** are inheriting the ApiSegment from the connected OperationClients. UUIDs of **Profile**, **FD** and **Link** don't contain an ApiSegment. @@ -86,7 +87,7 @@ This application identifier relates to the application that is connected by the It is **exclusively used with ObjectType c (Client)**. It is composed from the official abbreviation of the application name composed from the uppercase letters of the application name (e.g. RO, TAR), but transferred into lowercase letters (e.g. ro, tar) and the official release number of the specification of the application that is connected by the described client interface object. Dots to be replaced by hyphens (e.g. 1-0-0, 1-0-1) inside the release number. -ElasticSearch would be identified by es-1-0-0. +ElasticSearch would be identified by es-1-0-0. A hyphen also to be used between abbreviation of the application name and release number. **SequenceNumber** From 605b5a9bfbdca7d08bdff9ffaec352cd53b56960 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:34:17 +0100 Subject: [PATCH 60/79] Update ConceptOfServiceList.md --- .../ConceptOfServiceList/ConceptOfServiceList.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md b/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md index 9a31fb2c..89342351 100644 --- a/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md +++ b/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md @@ -1,17 +1,17 @@ # Concept of the ServiceList -The ServiceList is a compact notation for designing the service names and allocating the UUIDs. -It provides full focus on composing a complete and well-structured set of services before adding parameter and body details in the OpenApiSpecification. +The _ServiceList_ is a compact notation for designing the _OperationNames_ and allocating the UUIDs. +It provides full focus on composing a complete and well-structured set of _Operations_ before adding parameter and body details in the OpenApiSpecification. **Be aware that the template must not be altered outside the zones indicated by comments starting with '##'.** ### HTTP and TCP Server -* The application name must be identical with the one stated in the repository. +* The _ApplicationName_ must be identical with the one stated in the repository. * The release number ... - * has to follow the definitions in [Structure of Release Numbers](../../ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md), - * has to identify the version resulting from the specification (if originally planned to fix some bugs and later decided to add functionality the release number has to be changed accordingly). + * ... has to follow the definitions in [Structure of Release Numbers](../../ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md), + * ... has to identify the version resulting from the specification (if originally planned to fix some bugs and later decided to add functionality the release number has to be changed accordingly). * The CONFIGfile contains all data that is necessary to establish the connections, which are required for properly operating the application. TCP/IP addresses, operation names and application release number might depend on the environment (e.g. SDN test laboratory or live network) in which the application gets instantiated in. As a consequence the CONFIGfile has to be adapted to the environment before instantiation. This adaption shall be automated. For supporting the automation, fake IP addresses have to be put into the ServiceList during specification. Fake IP addresses will be replaced by environmental specific addresses during the creation of docker image. New IP addresses and TCP ports will be assigned by the platform owner. Please, request for an address and look it up at [Fake TCP/IP addresses](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). From eb266d77635f43df8f9b0af7d94e22829d44db5c Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Fri, 13 Jan 2023 17:30:11 +0100 Subject: [PATCH 61/79] Update ConceptOfServiceList.md --- .../ConceptOfServiceList.md | 94 +++++++++---------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md b/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md index 89342351..0f72fc7f 100644 --- a/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md +++ b/doc/SpecifyingApplications/ConceptOfServiceList/ConceptOfServiceList.md @@ -6,92 +6,88 @@ It provides full focus on composing a complete and well-structured set of _Opera **Be aware that the template must not be altered outside the zones indicated by comments starting with '##'.** -### HTTP and TCP Server +### HttpServer and TcpServer * The _ApplicationName_ must be identical with the one stated in the repository. -* The release number ... - * ... has to follow the definitions in [Structure of Release Numbers](../../ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md), - * ... has to identify the version resulting from the specification (if originally planned to fix some bugs and later decided to add functionality the release number has to be changed accordingly). -* The CONFIGfile contains all data that is necessary to establish the connections, which are required for properly operating the application. TCP/IP addresses, operation names and application release number might depend on the environment (e.g. SDN test laboratory or live network) in which the application gets instantiated in. As a consequence the CONFIGfile has to be adapted to the environment before instantiation. This adaption shall be automated. For supporting the automation, fake IP addresses have to be put into the ServiceList during specification. Fake IP addresses will be replaced by environmental specific addresses during the creation of docker image. New IP addresses and TCP ports will be assigned by the platform owner. Please, request for an address and look it up at [Fake TCP/IP addresses](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). +* The _ReleaseNumber_ ... + * ... has to follow the definitions in [Structure of _ReleaseNumbers_](../../ElementsApplicationPattern/Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md), + * ... has to identify the version resulting from the specification (if originally planned to fix some bugs and later decided to add functionality the _ReleaseNumber_ has to be changed accordingly). +* The CONFIGfile contains all data that is necessary to establish the connections, which are required for properly operating the application. TCP/IP addresses, _OperationNames_ and _ReleaseNumber_ might depend on the environment (e.g. SDN test laboratory or live network) in which the application gets instantiated in. As a consequence the CONFIGfile has to be adapted to the environment before instantiation. This adaption shall be automated. For supporting the automation, fake IP addresses have to be put into the _ServiceList_ during specification. Fake IP addresses will be replaced by environmental specific addresses during the creation of docker image. New IP addresses and TCP ports will be assigned by the _PlatformOwner_. Please, request for an address and look it up at [Fake TCP/IP addresses](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). -### Operation Servers +### OperationServers -* Services, which shall be provided by the new application, have to be added into the section _operation-servers/service/individual_. -* While brainstorming new OperationServers, think about ... - * the services, which shall be provided to other applications, +* _Operations_, which shall be provided by the new application, have to be added into the section _operation-servers/service/individual_. +* While brainstorming new _OperationServers_, think about ... + * the _Operations_, which shall be provided to other applications, * different styles of responses (e.g. filtered, formatted, compressed, generic representation), * potentially required inversions (e.g. ending subscriptions, de-activation of some automation) or restoring the original state, * parameters or functionality, which need to be pre-configured at this application, * data that shall be available as a data base dump. -* While defining the individual services, think carefully about sub-structuring and other aspects discussed in [Structuring of Services](../../ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md). -* While naming the individual services, be as descriptive as possible and follow the recommendations made in [Structuring of Service Names](../../ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md). -* The order of the services shall support understanding the purpose of the individual service while reading through the API description. - * Reflecting the expected sequence of appliance of the services might be helpful. - * Grouping services, which are either doing similar stuff or are for inverting some condition, might also ease understanding. +* While defining the individual _Operations_, think carefully about sub-structuring and other aspects discussed in [Structuring of _Operations_](../../ElementsApplicationPattern/Functions/StructureOfServices/StructureOfServices.md). +* While naming the individual _Operations_, be as descriptive as possible and follow the recommendations made in [Structuring of _OperationNames_](../../ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md). +* The order of the _Operations_ shall support understanding the purpose of the individual _Operation_ while reading through the API description. + * Reflecting the expected sequence of appliance of the _Operations_ might be helpful. + * Grouping _Operations_, which are either doing similar stuff or are for inverting some condition, might also ease understanding. * Sleep over, double check the definitions and probably discuss them with a colleague. -* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md) and contain "op-s-" to indicate that they are identifying an OperationServer. The consequent number shall start counting at 3001. It must be unique within the scope of the individual application, but it does not necessarily need to be sequential. +* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). ### Planning Clients -* The subset of OperationClients, which are required for embedding into the microservice management, need not to be planned. They will just be copied. -* While brainstorming the individual OperationClients, think about ... +* The subset of _OperationClients_, which are required for embedding into the microservice management, need not to be planned. They will just be copied. +* While brainstorming the individual _OperationClients_, think about ... * problems or calculations that have already been solved in existing implementations, * input data, which is needed, * event notifications, which need to be subscribed for triggering activities, - * additional services, which are needed for inverting originally desired conditions (e.g. stop subscription) or for restoring an original or default state, -* Knowing the existing services is crucial for efficient microservice specification. It is very much recommended to use e.g. the GenericRepresentation application to browse the API descriptions of existing implementations + * additional _Operations_, which are needed for inverting originally desired conditions (e.g. stop subscription) or for restoring an original or default state, +* Knowing the existing _Operations_ is required for efficient microservice specification. It is very much recommended to use e.g. the GenericRepresentation application to browse the API descriptions of existing implementations. * While considering consumption of data provided by other applications, take special care for * exact meaning of the provided attributes * update period of the provided information - * life cycle state of the consumed service (e.g. obsolete services will be discontinued soon) + * life cycle state of the consumed _Operation_ (e.g. obsolete _Operations_ will be discontinued soon) -### HTTP and TCP Clients +### HttpClients and TcpClients -* It is recommended to update the HTTP and TCP Clients in the ServiceList before adding the OperationClients. -* **Do not delete the HTTP and TCP Clients with UUIDs containing ApiSegments _bm_ or _bs_**. These Clients are required for embedding the application into the microservice management environment. -* The HTTP and TCP Clients holding the OperationClients listed during the brainstorming shall be added. Take care for correct application names and latest release numbers. +* It is recommended to update the _HttpClients_ and _TcpClients_ in the _ServiceList_ before adding the _OperationClients_. +* **Do not delete the _HttpClients_ and _TcpClients_ supporting _OperationClients_ with UUIDs containing ApiSegments _bm_ or _bs_**. These clients are required for embedding the application into the microservice layer. +* The _HttpClients_ and _TcpClients_ holding the _OperationClients_ listed during the brainstorming shall be added. Take care for correct application names and latest _ReleaseNumbers_. * Please, find the latest [Fake TCP/IP addresses](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md), which have to be applied here, for later replacement. -* It would be helpful, if the sequence of HTTP and TCP Clients would be the same across all applications. So please, take a look into existing specifications (e.g. RegistryOffice, TypeApprovalRegister) and put the HTTP and TCP Clients into the same order. -* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md) and contain "http-c-"/"tcp-c-" to indicate that they are identifying an HTTP, respectively TCP Client. In most cases it makes sense to just copy the UUIDs from existing ServiceLists or CONFIGfiles. +* It would be helpful, if the sequence of _HttpClients_ and _TcpClients_ would be the same across all applications. So please, take a look into existing specifications (e.g. RegistryOffice, TypeApprovalRegister) and put the _HttpClients_ and _TcpClients_ into the same order. +* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). In most cases it makes sense to just copy the UUIDs from existing _ServiceLists_ or _CONFIGfiles_. -### Operation Clients +### OperationClients -* OperationClients get categorized. -* It is not expected that ApplicationOwners will have to add OperationClients into the OwnOam section. These should be covered by the ApplicationPattern definitions. -* The Service section distinguishes OperationClients, which are addressing all existing applications in the same way (basic), and OperationClients, which are addressing individual applications (individual). -* Example for basic OperationClients: The request for sending notification about OaM activities is send by the OamLog application to all other applications. -* It is rather unlikely that ApplicationOwners will have to define an OperationClient into the basic section. -* So, most likely all the OperationClients from the brainstorming have to be added into the _operation-clients/service/individual_ section. Take care for correct service names. -* The order of the services shall support understanding the purpose of the individual service. - * Reflecting the expected sequence of appliance of the services might be helpful. - * Grouping services, which are either doing similar stuff or are for inverting some condition, might also ease understanding. -* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md) and contain "op-c-" to indicate that they are identifying an OperationClient. The consequent number of an individual service shall start with 3. The next two digits have to be identical with the second and third digit of the UUID of the HTTP Client. The last digit is for counting, but it does not necessarily need to be sequential. +* _OperationClients_ get categorized. +* It is not expected that _ApplicationOwners_ will have to add _OperationClients_ into the OwnOam section or the basic category. These should be covered by the _ApplicationPattern_ definitions. +* So, most likely all the _OperationClients_ from the brainstorming have to be added into the _operation-clients/service/individual_ section. Take care for correct _OperationNames_. +* The order of the _Operations_ shall support understanding the purpose of the individual _Operation_. + * Reflecting the expected sequence of appliance of the _Operations_ might be helpful. + * Grouping _Operations_, which are either doing similar stuff or are for inverting some condition, might also ease understanding. +* As a last step, assign the UUIDs. They shall follow the specifications made in [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -### ElasticSearch Clients +### ElasticSearchClients * In case the application is expected to create a lot of internal data, it is better to write it into a database instead of a datafile. -* An ElasticSearch Client shall be used for describing the REST connection to the database. -* The latest template of the ServiceList is containing such an ElasticSearch Client. -* It just has to be completed by a [Fake Index Alias from the List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IndexAliases.md). Potentially, the PlatformOwner has to be asked to add another Fake Index Alias to the list. -* If connecting a database would not be required, the ElasticSearch Client has to be deleted from the ServiceList. +* An _ElasticSearchClient_ shall be used for documenting the REST connection to the database. +* The latest template of the _ServiceList_ is containing such an _ElasticSearchClient_. +* It just has to be completed by a [Fake Index Alias from the List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IndexAliases.md). Potentially, the _PlatformOwner_ has to be asked to add another Fake Index Alias to the list. +* If connecting a database would not be required, the _ElasticSearchClient_ has to be deleted from the _ServiceList_. ### Commenting -The template of the ServiceList is prepared in such a way that comments (## TODO:) have to be replaced by changes that are individual to the application under specification. -If this initial concept would be followed, the ServiceList would be finalized as soon as all "## TODO:" would either be replaced or deleted. -If someone would find it helpful to add his thoughts into the ServiceList, he would be free to add own comments, but these comments should not start with "TODO:" after finalizing the ServiceList. -If someone would decide to add comments into the ServiceList, it would be strongly recommended to properly indent the additional lines. +The template of the _ServiceList_ is prepared in such a way that comments (## TODO:) have to be replaced by changes that are individual to the application under specification. +If this initial concept would be followed, the _ServiceList_ would be finalized as soon as all "## TODO:" would either be replaced or deleted. +If someone would find it helpful to add his thoughts into the _ServiceList_, he would be free to add own comments, but these comments should not start with "TODO:" after finalizing the _ServiceList_. +If someone would decide to add comments into the _ServiceList_, it would be recommended to properly indent the additional lines. ### Validation -Supporting to automatically transfer the ServiceList content into the OpenApiSpecification is planned for the future. +Automatically transferring the content of the _ServiceList_ into the OpenApiSpecification is planned for the future. Proper YAML files are required for facilitating such tool support. -It is recommended to validate the ServiceList.yaml for proper YAML syntax before publishing. -This could be done by copying the content of the file into the YAML validator at [www.yamllint.com](http://www.yamllint.com/). +Please, regard the test results of the YAML linting in the _Pull-Request_ and correct the syntax, if errors are indicated (warnings need not to be regarded). From de37887adc32f6b89cfbcb8a3973ace38c907602 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Fri, 13 Jan 2023 18:31:59 +0100 Subject: [PATCH 62/79] Updating CreatingServiceList.md --- .../CreatingServiceList.md | 93 ++++++++----------- spec/ApplicationPattern+services.yaml | 64 ++++++------- 2 files changed, 69 insertions(+), 88 deletions(-) diff --git a/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md b/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md index a0218b94..fabfbebe 100644 --- a/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md +++ b/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md @@ -1,88 +1,79 @@ # Creating the ServiceList -This is a step by step cookbook for creating the ServiceList. +This is a step by step cookbook for creating the _ServiceList_. -**Please, read the background information about the [Concept of the ServiceList](../ConceptOfServiceList/ConceptOfServiceList.md) before working in the ServiceList.** -**Be aware that the template must not be altered outside the zones indicated by comments starting with '##'.** +**Please, read the background information about the [Concept of the _ServiceList_](../ConceptOfServiceList/ConceptOfServiceList.md) before working in the _ServiceList_.** +**Be aware that the template must not be altered outside the zones indicated by comments starting with '##'.** ### File Handling -* Assure that there is a copy of the latest [template for the ServiceList](https://github.com/openBackhaul/ApplicationPattern/blob/develop/ApplicationPattern+services.yaml) in the develop branch of your application's repository. The latest ApplicationPattern+services.yaml can be downloaded from the [ApplicationPattern repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop). -* Rename the file, by replacing "ApplicationPattern" by your application's name. +* Assure that there is a copy of the latest [template for the _ServiceList_](https://github.com/openBackhaul/ApplicationPattern/blob/develop/spec/ApplicationPattern+services.yaml) in the _develop_ branch of your application's repository. The latest ApplicationPattern+services.yaml can be downloaded from the [ApplicationPattern repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop/spec). +* Rename the file, by replacing "ApplicationPattern" by your application's name. ### General -* Re-using already existing services for avoiding redundant code is very much recommended. -* Information about existing applications can be found e.g. in the GenericRepresentationApplication. -* In case clarification about existing services would be needed, the responsible ApplicationOwner has to be addressed for complementing the documentation of his application. +* Re-using already implemented function at other applications is very much recommended. +* Information about existing applications can be found e.g. in the _GenericRepresentationApplication_. +* In case clarification about existing _Operations_ would be needed, the responsible _ApplicationOwner_ has to be addressed for complementing the documentation of his application. -### HTTP and TCP Server +### HttpServer and TcpServer -* Add the official name and the official release number of the application. -* Add fake IP address and TCP port from [official List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). +* Add the official _ApplicationName_ and _ReleaseNumber_ of the application. +* Add fake IP address and TCP port from [official List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). ### OperationServers -* Add OperationServers that are specific to this application. - * Add the following two lines for every service the application shall provide: +* Add _OperationServers_ that are specific to this application. + * Add the following two lines for every _OperationServer_ the application shall provide: ``` - - service-name: + - operation-name: uuid: ``` - * Fill in a name of the service according to [structure of service names](../../ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md). - * Put them into a reasonable order. - * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). + * Fill in an _OperationName_ according to [structure of _OperationNames_](../../ElementsApplicationPattern/Names/StructureOfServiceNames/StructureOfServiceNames.md). + * Put them into a reasonable order. + * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). ### ElasticSearch * If connecting a database would be required, add official [Fake Index Alias from the List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IndexAliases.md). -* Otherwise, just delete the ElasticSearch Client from the ServiceList. +* Otherwise, just delete the _ElasticSearchClient_ from the _ServiceList_. ### OldRelease -* Add official release number of the operational version of the application. In case of new application, put the same value as in HttpServer above. -* Add fake IP address and TcpPort of the operational version of the application. In case of new application, put the same value as in TcpServer above. +* Add official _ReleaseNumber_ of the operational version of the application. In case of new application, put the same value as in _HttpServer_ above. +* Add fake IP address and TCP port of the operational version of the application. In case of new application, put the same value as in TcpServer above. ### NewRelease -* Add same value as in HttpServer above as the substituting release number. -* Add fake IP address and TcpPort from TcpServer above as IpAddress and TcpPort of the substituting release. -* Add OperationsClients that need to be configured at the OldRelease for addressing OperationServers at the NewRelease to handover configuration and data. - * Add the following two lines for every service client that shall be defined: +* Add same value as in _HttpServer_ above as the substituting _ReleaseNumber_. +* Add fake IP address and TCP port from _TcpServer_ above as IP address and TCP port of the substituting release. +* Add _OperationsClients_ that will be required for handing-over the configuration information to the _NewRelease_. + * Add the following two lines for every _OperationsClient_ that shall be defined: ``` - - service-name: + - operation-name: uuid: ``` - * Fill in a name of the service according to OperationServer definitions from above. + * Fill in the _OperationName_ according to _OperationServer_ definitions from above. * Put them into execution sequence. * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). ### From RegistryOffice to OperationKeyManagement -* If your application would address all other applications including the ones forming the TinyApplicationController at the same OperationServer (which is very unlikely), - * add the following two lines for defining a service client in the basic service sections of all applications of the TinyApplicationController: -``` - - service-name: - uuid: -``` - * Fill in the name of the service, which is identically available at all applications. - * Fill in a UUID starting with "op-c-2", followed by two digits that are identifying the application and a sequence number. -* If your application would _not_ address all other applications at the same OperationServer (which is very likely), just delete the todo "Add Clients specific to this application, but addressing all other applications" throughout the entire ServiceList. -* If your application would address one or several applications of the TinyApplicationController, - * the following two lines for defining a service client have to be added into the individual service section of the affected applications of the TinyApplicationController: +* If your application would address one or several applications of the _TinyApplicationController_, + * the following two lines for defining an _OperationClient_ have to be added into the individual service section of the affected applications of the _TinyApplicationController_: ``` - - service-name: + - operation-name: uuid: ``` - * Fill in the name of the service, which shall be addressed. + * Fill in the _OperationName_, which shall be addressed. * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). @@ -90,30 +81,20 @@ This is a step by step cookbook for creating the ServiceList. * If further applications would have to be addressed, create additional entries into the clients list. * Take the last entry as a template (and delete it, if no longer needed). -* Start with specifying the HTTP and TCP clients. - * Add the official name and release number of the application, which shall be addressed, into the HttpClient. +* Start with specifying the HttpClients and TcpClients. + * Add the official _ApplicationName_ and _ReleaseNumber_ of the application, which shall be addressed, into the _HttpClient_. * Add a UUID according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). - * Add the fake IP address and TCP port of the application to be addressed to the TcpClient. + * Add the fake IP address and TCP port of the application to be addressed to the _TcpClient_. * Add a UUID according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* If some service would be consumed from one or several, but not all other applications, it shall be listed in the _operation-clients/service/individual_ section; Add the usual two lines for defining a service client: -``` - - service-name: - uuid: -``` - * Fill in the name of the service, which shall be addressed. - * Fill in a UUID according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* In the extremely unlikely case that the application is addressing the same service at all other applications, the following two lines have to be added to the _operation-clients/service/basic_ section: +* Add the usual two lines for defining an _OperationClient_ to the _operation-clients/service/individual_ section: ``` - - service-name: + - operation-name: uuid: ``` - * Fill in the name of the service, which shall be addressed. + * Fill in the name of the _Operation_, which shall be addressed. * Fill in a UUID according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). ### Validation -* Open the YAML validator at [www.yamllint.com](http://www.yamllint.com/) -* Click into the ServiceList, Control+A, Control+C -* Click into YAML validator editor, Control+V, Push "Go" button -* Syntax of ServiceList is fine, if YAML validator indicates "Valid YAML!" +* Please, regard the test results of the YAML linting in the _Pull-Request_ and correct the syntax, if errors are indicated (warnings need not to be regarded). diff --git a/spec/ApplicationPattern+services.yaml b/spec/ApplicationPattern+services.yaml index 5c10240d..2ba1395d 100644 --- a/spec/ApplicationPattern+services.yaml +++ b/spec/ApplicationPattern+services.yaml @@ -4,44 +4,44 @@ servers: operation-servers: own-oam: basic: - - service-name: /v1/register-yourself + - operation-name: /v1/register-yourself uuid: xx-1-0-0-op-s-bm-000 - - service-name: /v1/embed-yourself + - operation-name: /v1/embed-yourself uuid: xx-1-0-0-op-s-bm-001 - - service-name: /v1/redirect-service-request-information + - operation-name: /v1/redirect-service-request-information uuid: xx-1-0-0-op-s-bm-002 - - service-name: /v1/redirect-oam-request-information + - operation-name: /v1/redirect-oam-request-information uuid: xx-1-0-0-op-s-bm-003 - - service-name: /v1/end-subscription + - operation-name: /v1/end-subscription uuid: xx-1-0-0-op-s-bm-004 - - service-name: /v1/inquire-oam-request-approvals + - operation-name: /v1/inquire-oam-request-approvals uuid: xx-1-0-0-op-s-bm-005 - - service-name: /v1/update-client + - operation-name: /v1/update-client uuid: xx-1-0-0-op-s-bm-007 - - service-name: /v1/list-ltps-and-fcs + - operation-name: /v1/list-ltps-and-fcs uuid: xx-1-0-0-op-s-bm-008 - - service-name: /v1/redirect-topology-change-information + - operation-name: /v1/redirect-topology-change-information uuid: xx-1-0-0-op-s-bm-009 - - service-name: /v1/update-operation-key + - operation-name: /v1/update-operation-key uuid: xx-1-0-0-op-s-bm-010 - - service-name: /v1/update-operation-client + - operation-name: /v1/update-operation-client uuid: xx-1-0-0-op-s-bm-011 individual: - - service-name: /v1/bequeath-your-data-and-die + - operation-name: /v1/bequeath-your-data-and-die uuid: xx-1-0-0-op-s-im-000 service: basic: - - service-name: /v1/start-application-in-generic-representation + - operation-name: /v1/start-application-in-generic-representation uuid: xx-1-0-0-op-s-bs-000 - - service-name: /v1/inform-about-application + - operation-name: /v1/inform-about-application uuid: xx-1-0-0-op-s-bs-001 - - service-name: /v1/inform-about-application-in-generic-representation + - operation-name: /v1/inform-about-application-in-generic-representation uuid: xx-1-0-0-op-s-bs-002 - - service-name: /v1/inform-about-release-history + - operation-name: /v1/inform-about-release-history uuid: xx-1-0-0-op-s-bs-003 - - service-name: /v1/inform-about-release-history-in-generic-representation + - operation-name: /v1/inform-about-release-history-in-generic-representation uuid: xx-1-0-0-op-s-bs-004 - - service-name: /docs + - operation-name: /docs uuid: xx-1-0-0-op-s-bs-005 individual: ## TODO: Add Services specific to this application @@ -89,7 +89,7 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/bequeath-your-data-and-die + - operation-name: /v1/bequeath-your-data-and-die uuid: xx-1-0-0-op-c-bm-or-1-0-0-000 individual: service: @@ -126,13 +126,13 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/register-application + - operation-name: /v1/register-application uuid: xx-1-0-0-op-c-bm-ro-2-0-0-000 - - service-name: /v1/relay-server-replacement + - operation-name: /v1/relay-server-replacement uuid: xx-1-0-0-op-c-bm-ro-2-0-0-001 - - service-name: /v1/deregister-application + - operation-name: /v1/deregister-application uuid: xx-1-0-0-op-c-bm-ro-2-0-0-002 - - service-name: /v1/relay-operation-update + - operation-name: /v1/relay-operation-update uuid: xx-1-0-0-op-c-bm-ro-2-0-0-003 individual: service: @@ -172,7 +172,7 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/record-service-request + - operation-name: /v1/record-service-request uuid: xx-1-0-0-op-c-bs-eatl-2-0-0-000 individual: service: @@ -193,7 +193,7 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/record-oam-request + - operation-name: /v1/record-oam-request uuid: xx-1-0-0-op-c-bs-ol-2-0-0-000 individual: service: @@ -214,7 +214,7 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/approve-oam-request + - operation-name: /v1/approve-oam-request uuid: xx-1-0-0-op-c-bs-aa-2-0-0-000 individual: service: @@ -235,17 +235,17 @@ clients: operation-clients: own-oam: basic: - - service-name: /v1/update-all-ltps-and-fcs + - operation-name: /v1/update-all-ltps-and-fcs uuid: xx-1-0-0-op-c-bm-alt-2-0-0-000 - - service-name: /v1/update-ltp + - operation-name: /v1/update-ltp uuid: xx-1-0-0-op-c-bm-alt-2-0-0-001 - - service-name: /v1/delete-ltp-and-dependents + - operation-name: /v1/delete-ltp-and-dependents uuid: xx-1-0-0-op-c-bm-alt-2-0-0-002 - - service-name: /v1/update-fc + - operation-name: /v1/update-fc uuid: xx-1-0-0-op-c-bm-alt-2-0-0-003 - - service-name: /v1/update-fc-port + - operation-name: /v1/update-fc-port uuid: xx-1-0-0-op-c-bm-alt-2-0-0-004 - - service-name: /v1/delete-fc-port + - operation-name: /v1/delete-fc-port uuid: xx-1-0-0-op-c-bm-alt-2-0-0-005 individual: service: From daa3bf18bdd2dfa5b3e4e5be0408dc543a160de5 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Mon, 16 Jan 2023 09:36:50 +0100 Subject: [PATCH 63/79] Change anyOf to oneOf in Profile --- spec/ApplicationPattern.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/ApplicationPattern.yaml b/spec/ApplicationPattern.yaml index 13995688..1cb8981c 100644 --- a/spec/ApplicationPattern.yaml +++ b/spec/ApplicationPattern.yaml @@ -3933,7 +3933,7 @@ paths: type: array uniqueItems: true items: - anyOf: + oneOf: - description: 'action profile' type: object required: From 22c057a6ff71c3c2caf529505b82fa6fc5c3f961 Mon Sep 17 00:00:00 2001 From: Dana Sunalova Date: Mon, 16 Jan 2023 09:58:25 +0100 Subject: [PATCH 64/79] Fixed some bugs in Elasticsearch Service - corrected export - fixed correct variable usage Signed-off-by: Dana Sunalova --- .../applicationPattern/services/ElasticsearchService.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js index 25479ddd..634af512 100644 --- a/server/applicationPattern/applicationPattern/services/ElasticsearchService.js +++ b/server/applicationPattern/applicationPattern/services/ElasticsearchService.js @@ -52,7 +52,7 @@ class ElasticsearchService { async getClient(uuid) { let esUuid = await getElasticsearchClientUuidAsync(uuid); let newApiKey = await getApiKeyAsync(esUuid); - let client = this._clients.get(uuid); + let client = this._clients.get(esUuid); if (client) { let storedApiKey = client.apiKey; if (newApiKey !== storedApiKey) { @@ -63,13 +63,13 @@ class ElasticsearchService { } } let storedApiKey = newApiKey; - client = new Client(await configureClientAsync(uuid, storedApiKey)); + client = new Client(await configureClientAsync(esUuid, storedApiKey)); client.on('response', (err, result) => { if (err) { console.error(`Elasticsearch error occurred: ${err}`); } }); - this._clients.set(uuid, { client: client, apiKey: storedApiKey }); + this._clients.set(esUuid, { client: client, apiKey: storedApiKey }); return client; } @@ -87,6 +87,7 @@ class ElasticsearchService { return (ping.statusCode === 200) ? operationalStateEnum.AVAILABLE : operationalStateEnum.UNAVAILABLE; } catch (error) { + console.log(error); return operationalStateEnum.UNAVAILABLE; } } @@ -286,4 +287,4 @@ module.exports.createResultArray = function createResultArray(result) { } module.exports.getIndexAliasAsync = getIndexAliasAsync -module.exports = new ElasticsearchService() +module.exports.elasticsearchService = new ElasticsearchService() From 577fad22232e075e24a577f871113828d356e933 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Mon, 16 Jan 2023 15:47:33 +0100 Subject: [PATCH 65/79] Update Profile chapter --- .../ConceptOfProfiles/ConceptOfProfiles.md | 69 ++++---- .../ConceptOfProfileList.md | 30 ++-- .../CreatingProfileInstanceList.md | 152 ++++++++++-------- .../CreatingProfileList.md | 39 +++-- .../CreatingServiceList.md | 34 ++-- 5 files changed, 181 insertions(+), 143 deletions(-) diff --git a/doc/ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md b/doc/ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md index ac7507db..efa656de 100644 --- a/doc/ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md +++ b/doc/ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md @@ -2,9 +2,10 @@ ### Purpose of Profiles -Profiles are for holding configuration information. -Most the configuration information is for documenting traffic relationships (e.g. HttpServer, OperationClient). -Profiles are for configuration information that is not directly related to an individual interface. + +_Profiles_ are for holding configuration information. +Most the configuration information is for documenting traffic relationships (e.g. _HttpServer_, _OperationClient_). +_Profiles_ are for configuration information that is not directly related to an individual interface. Contained information could relate e.g. * to all or a group of interfaces * or to a process or calculation that is executed inside the application. @@ -14,67 +15,67 @@ Examples: - If there would be an application for calculating some value from input from the network, there could be one or several static parameters in that formular. Potentially, it would make sense to make these parameters available for configuration during runtime of the application. Configuration information is not to be mixed with application data. -While data is entering the application through body or response body of services, configuration information is read and set through GET and PUT requests in the OaM section of the REST API. -Moreover structuring and storing of application data is implementation specific (could be e.g. a database), while structuring of configuration information is subject to specification and storing is happening in the CONFIGfile. +While data is entering the application through _RequestBody_ or _ResponseBody_ of services, configuration information is read and set through GET and PUT requests in the OaM section of the REST API. +Moreover structuring and storing of application data is implementation specific (could be e.g. a database), while structuring of configuration information is subject to specification and storing happens in the CONFIGfile. ### Structure of Profiles -Every definition of a Profile has to contain: -* ProfileName for identifying the kind of Profile -* UUID for identifying the instance of Profile -* Set of additional attributes that are specific to the individual kind of Profile -Its independence from individual interfaces is also obvious from the core information model and the Profile class being separated from the LogicalTerminationPoint, respectively the LayerProtocol. +Every definition of a _Profile_ has to contain: +* _ProfileName_ for identifying the kind of _Profile_ +* UUID for identifying the instance of _Profile_ +* Set of additional attributes that are specific to the individual kind of _Profile_ + +Its independence from individual interfaces is also obvious from the core information model and the _Profile_ class being separated from the LogicalTerminationPoint, respectively the LayerProtocol. ![Location of Profiles](./pictures/220628_core_classes_profile_s.png) **ProfileName** -The name of the Profile must describe the data object in one or two meaningful nouns followed by "Profile". +The name of the _Profile_ must describe the data object in one or two meaningful nouns followed by "Profile". The name must be written in UpperCamelCase and it must be unique within the scope of the individual application. **UUIDs** -UUIDs of Profiles have to comply with the rules defined in [Structure of UUIDs](../StructureOfUuids/StructureOfUuids.md). +UUIDs of _Profiles_ have to comply with the rules defined in [Structure of UUIDs](../StructureOfUuids/StructureOfUuids.md). **Additional Attributes** -The ApplicationOwner is free to define a set of additional attributes in the ProfileList. +The _ApplicationOwner_ is free to define a set of additional attributes in the _ProfileList_. Attributes have to be substructured into: - * Invariant attributes that are for identifying the instance of Profile (Capability) - * Attributes that are available for storing values during run-time of the application (Configuration) -(Capability attributes will only be represented by GET method in the OaM section of the OAS, while Configuration attributes will have PUT method, too.) + * Invariant attributes that are for identifying the instance of _Profile_ (_Capability_) + * Attributes that are available for storing values during run-time of the application (_Configuration_) +(_Capability_ attributes will only be represented by GET method in the OaM section of the OAS, while _Configuration_ attributes will have PUT method, too.) ### Re-use of Profiles -Re-using already existing Profile definitions is very much recommended. -Re-using is not just easier and faster during elaborating OpenApiSpecification and CONFIGfile, also program code is already available. -The templates of the ProfileList and the ProfileInstanceList already contain the following definitions. +Re-using already existing _Profile_ definitions is very much recommended. +Re-using is not just easier and faster during elaborating OpenApiSpecification and _CONFIGfile_, also program code is already available. +The templates of the _ProfileList_ and the _ProfileInstanceList_ already contain the following definitions. **ActionProfile** -The ActionProfile is for defining a potential next step in the workflow that shall be represented in the GenericRepresentation. -It is describing the label of a button that shall be shown and the request, which is to be sent, in case the button has been pushed. +The _ActionProfile_ is for defining a potential next step in the workflow that shall be represented in the _GenericRepresentation_. +It is describing the label of a button and a request, which is to be sent, in case the button has been pushed. Even input fields for values, which need to be sent in the body of this request, can be defined. -The ActionProfile is the most complex, but also the by far most often used Profile. +The _ActionProfile_ is the most complex, but also the by far most often used _Profile_. It occurs several times in all existing applications. **FileProfile** -The FileProfile contains the information, which is required for connecting with a file that holds application data. +The _FileProfile_ contains the information, which is required for connecting with a file that holds application data. Aside identifying and describing the referenced file, it makes file path, access credentials and allowed operations available for configuration. -The FileProfile is used whenever the application uses one or several files for storing internal data. +The _FileProfile_ is used whenever the application uses one or several files for storing internal data. **GenericResponseProfile** -The GenericResponseProfile contains one out of potentially several response values of an *-in-generic-representation request. -The operation-name attribute works like a filter on the responses, which have to be put into an *-in-generic-representation request. +The _GenericResponseProfile_ contains one out of potentially several response values of an _GenericRepresentation_ request. +The _OperationName_ attribute works like a filter on the responses, which have to be put into an _GenericRepresentation_ request. The name of the field and its datatype a are invariant, but the value is configurable. -The GenericResponseProfile occurs several times in all existing applications. +The _GenericResponseProfile_ occurs several times in all existing applications. **IntegerProfile** -The IntegerProfile is for storing a single Integer value. -In addition to the bare value, the Profile also allows to define unit, minimum and maximum values. +The _IntegerProfile_ is for storing a single Integer value. +In addition to the bare value, the _Profile_ also allows to define unit, minimum and maximum values. It has been used for several times in multiple applications. -E.g. it is holding the configuration of the number of records to be stored in the ExecutionAndTraceLog application. +E.g. it is holding the configuration of the number of records to be stored in the _ExecutionAndTraceLog_ application. **StringProfile** -The StringProfile is for storing a single String value. -In addition to the bare string, the Profile also allows to define an array of legal values (enumeration) or a structure of the string (Regex pattern). +The _StringProfile_ is for storing a single String value. +In addition to the bare string, the _Profile_ also allows to define an array of legal values (enumeration) or a structure of the string (Regex pattern). It has been used in some applications. -E.g. it is holding the operational mode of the OperationKeyManagement application. - +E.g. it is holding the operational mode of the _OperationKeyManagement_ application. diff --git a/doc/SpecifyingApplications/ConceptOfProfileList/ConceptOfProfileList.md b/doc/SpecifyingApplications/ConceptOfProfileList/ConceptOfProfileList.md index b19a1a07..b4ae1f50 100644 --- a/doc/SpecifyingApplications/ConceptOfProfileList/ConceptOfProfileList.md +++ b/doc/SpecifyingApplications/ConceptOfProfileList/ConceptOfProfileList.md @@ -3,39 +3,39 @@ ### Concept of ProfileList -The ProfileList is a compact notation for designing the Profiles as classes. +The _ProfileList_ is a compact notation for designing the _Profiles_ as classes. It provides full focus on composing the set of necessary attributes and their datatypes. In case of String datatype, it also allows defining generic expression about the allowed values of the String. This must be applied on the UUIDs and can be applied on any other String attribute. -The ProfileList distinguishes invariant and configurable attributes. -The ProfileList is preparing for defining the individual section of the OaM part of the OpenApiSpecification. +The _ProfileList_ distinguishes invariant and configurable attributes. +The _ProfileList_ is preparing for defining the individual section of the OaM part of the OpenApiSpecification. -Definition of the Profiles gives much more freedom to the ApplicationOwner than defining the interfaces. -The template of the ProfileList contains the definitions of the existing Profiles. +Definition of the _Profiles_ gives much more freedom to the _ApplicationOwner_ than defining the interfaces. +The template of the _ProfileList_ contains a set of definitions of already existing _Profiles_. Unused definitions need to be deleted from the application specific copy of the template. -Additional definitions can be added, if needed. +Additional _Profile_ definitions can be added, if needed. ### Concept of ProfileInstanceList -The ProfileInstanceList is a compact notation of the instances of Profiles that are required to define the configuration of the application. +The _ProfileInstanceList_ is a compact notation of the instances of _Profiles_ that are required for documenting the configuration of the application. It provides full focus on the values that shall be used right after instantiation. -The ProfileInstanceList is preparing for writing the profile section of the CONFIGfile of the applications. +The _ProfileInstanceList_ is preparing for writing the profile section of the _CONFIGfile_ of the applications. -The template of the ProfileInstanceList contains the instances of ActionProfile and GenericResponseProfile, which are necessary for the basic functions in generic representation. -Further on, it contains forms for creating additional instances of ActionProfile, FileProfile, GenericResponseProfile, IntegerProfile and StringProfile. +The template of the _ProfileInstanceList_ contains the instances of _ActionProfile_ and _GenericResponseProfile_, which are necessary for the basic functions in _GenericRepresentation_. +Further on, it contains forms for creating additional instances of _ActionProfile_, _FileProfile_, _GenericResponseProfile_, _IntegerProfile_ and _StringProfile_. These forms shall provide guidance while filling in concrete values. Unused forms need to be deleted from the application specific copy of the template. -Additional instances can be described for additional definitions of Profiles, if needed. +Additional instances can be described for additional definitions of _Profiles_, if needed. ### Commenting -The template of the ProfileList and the ProfileInstanceList is prepared in such a way that comments (## TODO:) have to be replaced by changes that are individual to the application under specification. -If this initial concept would be followed, the ProfileList and the ProfileInstanceList would be finalized as soon as all "## TODO:" would either be replaced or deleted. -If someone would find it helpful to add his thoughts into the ProfileList or the ProfileInstanceList, he would be free to add own comments, but these comments should not start with "TODO:" after finalizing the respective list. -If someone would decide to add comments into the ProfileList or the ProfileInstanceList, it would be strongly recommended to properly indent the additional lines. +The template of the _ProfileList_ and the _ProfileInstanceList_ is prepared in such a way that comments (## TODO:) have to be replaced by changes that are individual to the application under specification. +If this initial concept would be followed, the _ProfileList_ and the _ProfileInstanceList_ would be finalized as soon as all "## TODO:" would either be replaced or deleted. +If someone would find it helpful to add his thoughts into the _ProfileList_ or the ProfileInstanceList, he would be free to add own comments, but these comments should not start with "TODO:" after finalizing the respective list. +If someone would decide to add comments into the _ProfileList_ or the _ProfileInstanceList_, it would be strongly recommended to properly indent the additional lines. ### Profiles and ProfileInstances diff --git a/doc/SpecifyingApplications/CreatingProfileInstanceList/CreatingProfileInstanceList.md b/doc/SpecifyingApplications/CreatingProfileInstanceList/CreatingProfileInstanceList.md index fd9d4edb..22314137 100644 --- a/doc/SpecifyingApplications/CreatingProfileInstanceList/CreatingProfileInstanceList.md +++ b/doc/SpecifyingApplications/CreatingProfileInstanceList/CreatingProfileInstanceList.md @@ -1,77 +1,83 @@ # Creating a ProfileInstanceList -This is a step by step cookbook for creating the ProfileInstanceList. +This is a step by step cookbook for creating the _ProfileInstanceList_. -**Please, read the background information about the [Concept of Profiles](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and the [Concept of the ProfileInstanceList](../ConceptOfProfileList/ConceptOfProfileList.md) before working at the ProfileList.** +**Please, read the background information about the [Concept of _Profiles_](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and the [Concept of the _ProfileInstanceList_](../ConceptOfProfileList/ConceptOfProfileList.md) before working at the _ProfileList_.** -### File Handling +### Preparation -* Assure that there is a copy of the latest [template for the ProfileInstanceList](https://github.com/openBackhaul/ApplicationPattern/blob/develop/ApplicationPattern%2BprofileInstances.yaml) in the develop Branch of your application's repository. The latest ApplicationPattern+profileInstances.yaml can be downloaded from the [ApplicationPattern repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop). +* If not yet existing, create an _Issue_ for elaborating the _ProfileInstanceList_. +* Open a local feature branch for elaborating the _ProfileInstanceList_. + + +### File Handling + +* Assure that there is a copy of the latest [template of the _ProfileInstanceList_](https://github.com/openBackhaul/ApplicationPattern/blob/develop/spec/ApplicationPattern%2BprofileInstances.yaml) in the _develop_ branch of your application's repository. The latest _ApplicationPattern+profileInstances.yaml_ can be downloaded from the [_ApplicationPattern_ repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop). * Rename the file, by replacing "ApplicationPattern" by your application's name. ### General -* Re-using already existing descriptions of instances of Profiles from ProfileInstanceLists of other applications is very much recommended. +* Re-using already existing descriptions of instances of _Profiles_ from _ProfileInstanceLists_ of other applications is very much recommended. ### Further Instances of ActionProfile -* Check your ServiceList for services that are implementing the concept of generic representation. -* If you would need to add further instances of ActionProfile please look into existing applications' ProfileInstanceLists and the template to get familiar with the concept. -* Copy/paste and alter additional instances of ActionProfile for configuring a step-by-step-clicking-through-process after starting with /v1/start-application-in-generic-representation. +* Check your _ServiceList_ for services that are implementing the concept of _GenericRepresentation_. +* If you would need to add further instances of _ActionProfile_ please look into existing applications' _ProfileInstanceLists_ and the template to get familiar with the concept. +* Copy/paste and alter additional instances of _ActionProfile_ for configuring a step-by-step-clicking-through-process after starting with _/v1/start-application-in-generic-representation_. * Finally, just delete the form that waits for completion. **ProfileName** -* The ProfileName shall be set on "ActionProfile". +* The _ProfileName_ shall be set on "ActionProfile". **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* The LayerID shall be set on "action". -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* The _LayerID_ shall be set on "action". +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same _LayerID_. **OperationName** -* Fill in the path of the request that shall transport the information about labels, input values and consequent requests in its response body to the GenericRepresentation. +* Fill in the name of the operation (e.g. _/v1/start-application-in-generic-representation_) that shall transport the information about labels, input values and consequent requests in its response body to the _GenericRepresentation_. **Label** -* Fill in the text that shall be printed on the label, which shall be represented in the GenericRepresentation. +* Fill in the text (e.g. 'Inform about Application') that shall be printed on a button, which shall be represented in the _GenericRepresentation._ **InputValueList::FieldName** -* If the Request needs to send parameters in its body, these parameters have to be defined in the InputValueList. -* Don't represent the InputValueList, if not required. -* Be aware that the FieldName will not just be sent as an attribute's name in the body of the request, but also be represented by the GenericRepresentation besides an input field. -* Fill in the FieldName in UpperCamelCase notation. +* If the request needs to send parameters in its body, these parameters have to be defined in the _InputValueList_. +* Don't represent the _InputValueList_, if not required. +* Be aware that the _FieldName_ will not just be sent as an attribute's name in the body of the request, but also be represented by the _GenericRepresentation_ besides an input field. +* Fill in the _FieldName_ in UpperCamelCase notation. **InputValueList::Unit** -* The Unit will be represented by the GenericRepresentation besides an input field. +* The _Unit_ will be represented by the _GenericRepresentation_ besides an input field. * Don't represent this stereotype, if not required. **DisplayInNewBrowserWindow** -* Usually, DisplayInNewBrowserWindow is set on false and the response to the described request will be presented in the same browser window. -* If the response to clicking the button shall be represented in a new window of the GenericRepresentation, DisplayInNewBrowserWindow has to be set on true. +* Usually, _DisplayInNewBrowserWindow_ is set on false and the response to the described request will be presented in the same browser window. +* If the response to clicking the button shall be represented in a new window of the _GenericRepresentation_, _DisplayInNewBrowserWindow_ has to be set on true. -**Request** -* Fill in the complete URL that shall be addressed by the GenericRepresentation whenever the button gets pressed. -* Several parts (e.g. IP address, TCP port, operationName) of the URL might be subject to the configuration of some interface. These parts have to be substituted by references into the data tree. The references have to be put into cornered brackets "[]". -* UUIDs comprised in the references have to match the ServiceList content (otherwise the implementers will fill wrong data into the response bodies of the generic representation requests). +**ConsequentOperationReference** +* Operation that shall be called, whenever the button gets pressed in the _GenericRepresentation_. +* Because several parts (e.g. IP address, TCP port, _OperationName_) of the URL that has to be called by the _GenericRepresentation_ might be subject to configuration in your application, there shall be just a reference to the operation here. The actual URL will then be generated by your application right before responding on a request reaching the _OperationName_. +* UUIDs comprised in the references have to match the _ServiceList_ content (otherwise the application will fill wrong data into the response bodies of the _GenericRepresentationRequests_ during run-time). ### Instances of FileProfile -* Whenever your application is supposed to use one or several files for storing data, a corresponding number of instances of FileProfile is required. -* Just copy/paste the form prepared for completion or copy from existing ProfileInstanceLists of other applications. +* Whenever your application is supposed to use one or several files for storing data, a corresponding number of instances of _FileProfile_ is required. +* Just copy/paste the form prepared for completion or copy from existing _ProfileInstanceLists_ of other applications. * Finally, just delete the form that waits for completion. **ProfileName** -* The ProfileName shall be set on "FileProfile". +* The _ProfileName_ shall be set on "FileProfile". **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* The LayerID shall be set on "file". -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* The _LayerID_ shall be set on "file". +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same _LayerID_. **FileIdentifier** * Document an invariant identifier of the file. @@ -102,53 +108,60 @@ This is a step by step cookbook for creating the ProfileInstanceList. ### Further Instances of GenericResponseProfile -* Check your ServiceList for services that are implementing the concept of generic representation. -* If you would need to add further instances of GenericResponseProfile please look into existing applications' ProfileInstanceLists and the template to get familiar with the concept. -* Copy/paste and alter additional instances of GenericResponseProfile for configuring the responses given by the *-in-generic-representation requests. +* Check your _ServiceList_ for services that are implementing the concept of _GenericRepresentation_. +* If you would need to add further instances of _GenericResponseProfile_ please look into existing applications' _ProfileInstanceLists_ and the template to get familiar with the concept. +* Copy/paste and alter additional instances of _GenericResponseProfile_ for configuring the responses given by the _GenericRepresentationRequests_. * Finally, just delete the form that waits for completion. **ProfileName** -* The ProfileName shall be set on "GenericResponseProfile". +* The _ProfileName_ shall be set on "GenericResponseProfile". **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* The LayerID shall be set on "response". -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* The _LayerID_ shall be set on "response". +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same _LayerID_. **OperationName** * Fill in the path of the request that shall contain provide the response. -**FieldName** -* Fill in the name of the field that shall represent the response value. +**StaticFieldName** +* The response will be represented in a field. This field will have a name/title. If this field name would be static, you could state it here. + +**FieldNameReference** +* The response will be represented in a field. This field will have a name/title. If this field name would be stored somewhere in the internal data tree, you could reference this possition here. **Description** * This attribute is just for documenting the meaning of the defined field. -* It is explanatory only and will not be passed to the application that is consuming the *-in-generic-representation request. +* It is explanatory only and will not be passed to the _GenericRepresentation_. **Datatype** * Fill in the datatype of the response value. * Chose from 'string', 'integer', 'boolean'. -**Value** -* Fill in the value, which shall be represented in the field. -* The value has to be transported as a string, but might be interpreted according to the Datatype at the receiving side. +**StaticValue** +* The response will represent a value. If this value would be static, you could state it here. +* The value has to be transported as a string, but might be interpreted according to the _Datatype_ at the receiving side. + +**ValueReference** +* The response will represent a value. If this value would be stored somewhere in the internal data tree, you could reference this possition here. +* The value has to be transported as a string, but might be interpreted according to the _Datatype_ at the receiving side. ### Instances of IntegerProfile -* Whenever you would like to make an aspect of the application's behavior configurable and this aspect can be expressed as an Integer value, an additional instance of IntegerProfile is required. -* Just copy/paste the form prepared for completion or copy from existing ProfileInstanceLists of other applications. +* Whenever you would like to make an aspect of the application's behavior configurable and this aspect can be expressed as an Integer value, an additional instance of _IntegerProfile_ is required. +* Just copy/paste the form prepared for completion or copy from existing _ProfileInstanceLists_ of other applications. * Finally, just delete the form that waits for completion. **ProfileName** -* The ProfileName shall be set on "IntegerProfile". +* The _ProfileName_ shall be set on "IntegerProfile". **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* The LayerID shall be set on "integer". -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* The _LayerID_ shall be set on "integer". +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same _LayerID_. **IntegerName** * Document the attribute's name. @@ -171,18 +184,18 @@ This is a step by step cookbook for creating the ProfileInstanceList. ### Instances of StringProfile -* Whenever you would like to make an aspect of the application's behavior configurable and this aspect needs to be expressed as a String, an additional instance of StringProfile is required. -* Just copy/paste the form prepared for completion or copy from existing ProfileInstanceLists of other applications. +* Whenever you would like to make an aspect of the application's behavior configurable and this aspect needs to be expressed as a String, an additional instance of _StringProfile_ is required. +* Just copy/paste the form prepared for completion or copy from existing _ProfileInstanceLists_ of other applications. * Finally, just delete the form that waits for completion. **ProfileName** -* The ProfileName shall be set on "StringProfile". +* The _ProfileName_ shall be set on "StringProfile". **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* The LayerID shall be set on "string". -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* The _LayerID_ shall be set on "string". +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same _LayerID_. **StringName** * Document the attribute's name. @@ -203,27 +216,30 @@ This is a step by step cookbook for creating the ProfileInstanceList. ### New Profiles -* You are free to instantiate as many objects based on the self-defined Profiles as you like. -* Just copy/paste the lines for ProfileName and UUID from an existing definition and the additional stereotypes of your attribute or composed datatype. +* You are free to instantiate as many objects based on the self-defined _Profiles_ as you like. +* Just copy/paste the lines for _ProfileName_ and UUID from an existing definition and the additional stereotypes of your attribute or composed datatype. * Be aware that you just need to describe the structuring of configuration information. Application data shall be encapsulated by the application. **ProfileName** -* The ProfileName shall comply with the rules stated in [Concept of Profiles](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md). +* The _ProfileName_ shall comply with the rules stated in [Concept of _Profiles_](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md). **UUID** * The UUID shall follow the [Structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -* Choose a meaningful LayerID. -* The ObjectType shall be set on "p" (Profile). -* The SequenceNumber shall start at "000" and must be unique within the scope of instances of Profiles with the same LayerID. +* Choose a meaningful _LayerID_. +* The _ObjectType_ shall be set on "p" (_Profile_). +* The _SequenceNumber_ shall start at "000" and must be unique within the scope of instances of _Profiles_ with the same LayerID. **Further Stereotypes** -* Add the stereotypes of your profile definition. +* Add the stereotypes of your _Profile_ definition. * Don't forget to define the attribute's value during instantiation of the application. -### Validation +### Validation and Finalization -* Open the YAML validator at [www.yamllint.com](http://www.yamllint.com/) -* Click into the ProfileList, Control+A, Control+C -* Click into YAML validator editor, Control+V, Push "Go" button -* Syntax of ProfileList is fine, if YAML validator indicates "Valid YAML!" +* Double check your _ProfileInstanceList_. +* _Commit_ to your local feature branch. +* _Push_ your local feature branch to the remote repository. +* Create a _Pull-Request_. +* Please, regard the test results of the YAML linting in the _Pull-Request_. Correct the syntax of the _ProfileList_, if errors are indicated (warnings need not to be regarded), and _commit_ and _push_ again until the _ProfileList_ in the remote repository is successfully validated. +* Select a _Reviewer_ from the team. +* Assign the _Pull-Request_ to yourself. \ No newline at end of file diff --git a/doc/SpecifyingApplications/CreatingProfileList/CreatingProfileList.md b/doc/SpecifyingApplications/CreatingProfileList/CreatingProfileList.md index 4106eced..1a979e46 100644 --- a/doc/SpecifyingApplications/CreatingProfileList/CreatingProfileList.md +++ b/doc/SpecifyingApplications/CreatingProfileList/CreatingProfileList.md @@ -1,29 +1,38 @@ -# Creating a ProfileList +# Creating a ProfileList -This is a step by step cookbook for creating the ProfileList. +This is a step by step cookbook for creating the _ProfileList_. -**Please, read the background information about the [Concept of Profiles](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and the [Concept of the ProfileList](../ConceptOfProfileList/ConceptOfProfileList.md) before working at the ProfileList.** +**Please, read the background information about the [Concept of _Profiles_](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and the [Concept of the _ProfileList_](../ConceptOfProfileList/ConceptOfProfileList.md) before working at the _ProfileList_.** -### File Handling +### Preparation -* Assure that there is a copy of the latest [template for the ProfileList](https://github.com/openBackhaul/ApplicationPattern/blob/develop/ApplicationPattern+profiles.yaml) in the develop Branch of your application's repository. The latest ApplicationPattern+profiles.yaml can be downloaded from the [ApplicationPattern repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop). +* If not yet existing, create an _Issue_ for elaborating the _ProfileList_. +* Open a local feature branch for elaborating the _ProfileList_. + +### File Handling + +* Assure that there is a copy of the latest [template for the _ProfileList_](https://github.com/openBackhaul/ApplicationPattern/blob/develop/spec/ApplicationPattern+profiles.yaml) in the _develop_ branch of your application's repository. The latest _ApplicationPattern+profiles.yaml_ can be downloaded from the [_ApplicationPattern_ repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop). * Rename the file, by replacing "ApplicationPattern" by your application's name. -### Definitions +### Definitions -* The ActionProfile and the GenericResponseProfile are needed for representing the application in the GenericRepresentation, which is obligatory. Consequently, the ActionProfile and the GenericResponseProfile are assumed to be kept in the ProfileList. -* Remove unnecessary Profile definitions from the template. -* Add required Profile definitions according to the specifications made in [Concept of Profiles](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and [Concept of the ProfileList](../ConceptOfProfileList/ConceptOfProfileList.md) at the end of the file. -* Re-using already existing definitions of Profiles from ProfileLists of other applications is very much recommended. +* The _ActionProfile_ and the _GenericResponseProfile_ are needed for representing the application in the _GenericRepresentation_ application, which is obligatory. Consequently, the _ActionProfile_ and the _GenericResponseProfile_ must be kept in the _ProfileList_. +* Remove unnecessary _Profile_ definitions from the template. +* Add required _Profile_ definitions according to the specifications made in [Concept of _Profiles_](../../ElementsApplicationPattern/Functions/ConceptOfProfiles/ConceptOfProfiles.md) and [Concept of the _ProfileList_](../ConceptOfProfileList/ConceptOfProfileList.md) at the end of the file. +* Re-using already existing definitions of _Profiles_ from _ProfileLists_ of other applications is recommended. * Define patterns for String attributes, wherever reasonable (Potentially [this documentation](https://user.phil.hhu.de/~seyffarth/classes/python2020/09-01%20Regular%20Expressions%20schreiben.html) might be helpful. [Test the Regex](https://regex101.com/).). * Put attributes, which are invariant during runtime of the application into a capability section. * Put attributes, which shall be available for configuration during runtime of the application into a configuration section. -### Validation -* Open the YAML validator at [www.yamllint.com](http://www.yamllint.com/) -* Click into the ProfileList, Control+A, Control+C -* Click into YAML validator editor, Control+V, Push "Go" button -* Syntax of ProfileList is fine, if YAML validator indicates "Valid YAML!" +### Validation and Finalization + +* Double check your _ProfileList_. +* _Commit_ to your local feature branch. +* _Push_ your local feature branch to the remote repository. +* Create a _Pull-Request_. +* Please, regard the test results of the YAML linting in the _Pull-Request_. Correct the syntax of the _ProfileList_, if errors are indicated (warnings need not to be regarded), and _commit_ and _push_ again until the _ProfileList_ in the remote repository is successfully validated. +* Select a _Reviewer_ from the team. +* Assign the _Pull-Request_ to yourself. \ No newline at end of file diff --git a/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md b/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md index fabfbebe..32bbb5ca 100644 --- a/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md +++ b/doc/SpecifyingApplications/CreatingServiceList/CreatingServiceList.md @@ -6,26 +6,32 @@ This is a step by step cookbook for creating the _ServiceList_. **Be aware that the template must not be altered outside the zones indicated by comments starting with '##'.** -### File Handling +### Preparation + +* If not yet existing, create an _Issue_ for elaborating the _ServiceList_. +* Open a local feature branch for elaborating the _ServiceList_. + + +### File Handling * Assure that there is a copy of the latest [template for the _ServiceList_](https://github.com/openBackhaul/ApplicationPattern/blob/develop/spec/ApplicationPattern+services.yaml) in the _develop_ branch of your application's repository. The latest ApplicationPattern+services.yaml can be downloaded from the [ApplicationPattern repository](https://github.com/openBackhaul/ApplicationPattern/tree/develop/spec). * Rename the file, by replacing "ApplicationPattern" by your application's name. -### General +### General * Re-using already implemented function at other applications is very much recommended. * Information about existing applications can be found e.g. in the _GenericRepresentationApplication_. * In case clarification about existing _Operations_ would be needed, the responsible _ApplicationOwner_ has to be addressed for complementing the documentation of his application. -### HttpServer and TcpServer +### HttpServer and TcpServer * Add the official _ApplicationName_ and _ReleaseNumber_ of the application. * Add fake IP address and TCP port from [official List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IpAddresses.md). -### OperationServers +### OperationServers * Add _OperationServers_ that are specific to this application. * Add the following two lines for every _OperationServer_ the application shall provide: @@ -38,19 +44,19 @@ This is a step by step cookbook for creating the _ServiceList_. * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -### ElasticSearch +### ElasticSearch * If connecting a database would be required, add official [Fake Index Alias from the List](../../TestingApplications/Infrastructure/SdnLaboratory/FakeAddresses/IndexAliases.md). * Otherwise, just delete the _ElasticSearchClient_ from the _ServiceList_. -### OldRelease +### OldRelease * Add official _ReleaseNumber_ of the operational version of the application. In case of new application, put the same value as in _HttpServer_ above. * Add fake IP address and TCP port of the operational version of the application. In case of new application, put the same value as in TcpServer above. -### NewRelease +### NewRelease * Add same value as in _HttpServer_ above as the substituting _ReleaseNumber_. * Add fake IP address and TCP port from _TcpServer_ above as IP address and TCP port of the substituting release. @@ -65,7 +71,7 @@ This is a step by step cookbook for creating the _ServiceList_. * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -### From RegistryOffice to OperationKeyManagement +### From RegistryOffice to OperationKeyManagement * If your application would address one or several applications of the _TinyApplicationController_, * the following two lines for defining an _OperationClient_ have to be added into the individual service section of the affected applications of the _TinyApplicationController_: @@ -77,7 +83,7 @@ This is a step by step cookbook for creating the _ServiceList_. * Fill in UUIDs according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -### Further OperationClients +### Further OperationClients * If further applications would have to be addressed, create additional entries into the clients list. * Take the last entry as a template (and delete it, if no longer needed). @@ -95,6 +101,12 @@ This is a step by step cookbook for creating the _ServiceList_. * Fill in a UUID according to [structure of UUIDs](../../ElementsApplicationPattern/Names/StructureOfUuids/StructureOfUuids.md). -### Validation +### Validation and Finalization -* Please, regard the test results of the YAML linting in the _Pull-Request_ and correct the syntax, if errors are indicated (warnings need not to be regarded). +* Double check your _ServiceList_. +* _Commit_ to your local feature branch. +* _Push_ your local feature branch to the remote repository. +* Create a _Pull-Request_. +* Please, regard the test results of the YAML linting in the _Pull-Request_. Correct the syntax of the _ServiceList_, if errors are indicated (warnings need not to be regarded), and _commit_ and _push_ again until the _ServiceList_ in the remote repository is successfully validated. +* Select a _Reviewer_ from the team. +* Assign the _Pull-Request_ to yourself. \ No newline at end of file From 23822eea44c8b07acffb2c4f2f12d937d6b4e270 Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Tue, 17 Jan 2023 18:40:44 +0100 Subject: [PATCH 66/79] Develop Forwarding documentation Improve ConceptsOfForwarding.md Formulate StructureOfCallbackNames.md --- .../ElementsApplicationPattern.md | 2 +- .../ConceptsOfForwarding.md | 110 ++++++++++-------- .../StructureOfCallbackNames.md | 46 +++++++- 3 files changed, 107 insertions(+), 51 deletions(-) diff --git a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md index 200ef28e..b01b9b33 100644 --- a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md +++ b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md @@ -12,7 +12,7 @@ **Functions** * [Structure of Services](./Functions/StructureOfServices/StructureOfServices.md) * [Concept of Profiles](./Functions/ConceptOfProfiles/ConceptOfProfiles.md) -* [Concepts of Forwarding](./Functions/ConceptsOfForwarding/ConceptsOfForwarding.md) +* [Concepts of Internal Forwarding](./Functions/ConceptsOfForwarding/ConceptsOfForwarding.md) **Names and IDs** * [Structure of ApplicationNames](./Names/StructureOfApplicationNames/StructureOfApplicationNames.md) diff --git a/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md b/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md index 3491c4b9..2b696c3f 100644 --- a/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md +++ b/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md @@ -1,80 +1,94 @@ -# Concept of Forwarding - - -## Concept of Internal Forwarding +# Concept of Internal Forwarding ### Purpose of Internal Forwarding There are a lot of interactions between the applications of the modular application layer. -For example, whenever an application receives a request, it has to send one to the ExecutionAndTraceLog application for documenting processing of the received request. +For example, whenever an application receives a request, it has to send one to the _ExecutionAndTraceLog_ application for documenting processing of the received request. + All these interactions between the applications are based on REST requests. -These REST requests comprise TCP/IP address and service name. -Certainly, somehow an application needs to know, which TCP/IP address and service name to use for example for documenting successful processing of a request. -If the information would be hard coded, the implementation of an application would out-date as soon as the TCP/IP address of one of its serving applications would change. -Thus, TCP/IP addresses and service names must at least be stored in parameter files, but manual changes on that files don't really fit together with an application layer of several tens or hundrets of applications. -This is why we did not just put these values into a CONFIGfile, but also made them available for configuration via the REST interface of the application. -Even better, communication and configuration of many changes to the traffic relationships between the applications got automated, - but also these automations require to be documented as Forwardings. +The URIs of these REST requests must comprise e.g. TCP/IP address and _OperationName_. +Thus, every individual application needs to know these information about other applications for properly addressing them. + +If these information would be hard coded, the implementation of an individual application would out-date as soon as the TCP/IP address of one of its serving applications would change. +Thus, TCP/IP addresses and _OperationName_ get documented in the CONFIGfiles of the individual applications. + +A stack of _TcpClient_, _HttpClient_ and _OperationClient_ is used for documenting the information, which is required for addressing a consumed service. +Address information of an already known application could be altered by modifying the values of the attributes inside these _Clients_. +This could be done manually in the CONFIGfile or via the OaM segment of the REST API during runtime. +To some extend it is even automated via the service segment of the REST API. + +So there are relationships between _OperationServers_ and _OperationClients_ (see example in the first paragraph). +If these relationships would be hardcoded, it would not be possible to redirect the flow from event to reaction, and a dynamic change of the application layer would not be possible. +Thus, the relationships need to be documented in the CONFIGfiles of the individual applications, too. + +_ForwardingDomains_ and _ForwardingConstructs_ are used for documenting the relationships between received (_OperationServer_) and to be sent requests (_OperationClients_). +_ForwardingConstructs_ are used for representing process flows as well as calculations. +Alike the _Clients_, the _ForwardingConstructs_ could be changed manually in the CONFIGfile or via the OaM segment of the REST API or in automated way via the service segment of the REST API. + +The _ForwardingList_ is supporting designing the relationships before documenting them syntactically correct in the OpenApiSpecification and the CONFIGfile. ### Structure of Internal Forwardings -Forwardings are describing relationships between Events and Reactions. +_ForwardingConstructs_ are describing relationships between events and reactions. Since we are dealing with REST servers, -- an Event is a request, which has been received on one of the services offered by the application and -- the Reaction is a request, which has to be sent to another application. - -As described above, these relationships shall be configurable. -Since we are dealing with REST servers, also configuration of the Forwardings is done by requests addressing a service offered by the application. +- an event is a request, which has been received on one of the _OperationServers_ offered by the application and +- the reaction is a request, which has to be sent via one of the _OperationClients_ that are connecting another applications. +Obviously, a definition of a _ForwardingConstruct_ must comprise an _Input_ (_OperationServer_) and at least one _Output_ (one or several _OperationClients_). -Thus, a Forwarding has to be described by requests for Input, Output and Management. -Obviously, Input and Management are represented by references on OperationServers and Output by references on OperationClients. +As described above, we are documenting the relationships, because we want to be able to modify them. +If we want to automate modification, there must be services available on the REST API for facilitating this. +Thus, a definition of a _ForwardingConstruct_ must also comprise a _Management_ (_OperationServer_), whenever it shall be possible to automate changes (otherwise the _ForwardingConstruct_ could still be changed manually via OaM segment or altering the CONFIGfile). -Example: The TypeApprovalRegister is requesting for notifications about registrations at the RegistryOffice. -Management: The TypeApprovalRegister is informing about its TCP/IP address and service name by addressing the /v1/inquire-application-type-approvals service at the RegistryOffice. -Input/Event: Some new application is addressing the /v1/register-application service at the RegistryOffice. -Output/Reaction: The RegistryOffice is addressing the service that has been prescribed by the TypeApprovalRegister in the initial Management request. +Example: +The _TypeApprovalRegister_ is subscribing for notifications about new registrations at the _RegistryOffice_. +A _Forwarding_ from registration to notifying the _TypeApprovalRegister_ has to be defined in the _RegistryOffice_. +This _Forwarding_ has to comprise the following _Servers_ and _Clients_: +- _Management_: The _TypeApprovalRegister_ is informing the _RegistryOffice_ about its TCP/IP address and _OperationName_ for receiving notifications about new registrations by addressing the _RegistryOffice's OperationServer _/v1/inquire-application-type-approvals_. The _RegistryOffice_ creates or updates a stack of _Clients_ from these information and it complements the corresponding _ForwardingConstruct_ by an _Output_ reference to the _OperationClient_. +- _Input_/event: Some new application is addressing the _RegistryOffice's OperationServer /v1/register-application_ for registering. +- _Output_/reaction: The _RegistryOffice_ is activating its _OperationClient /v1/regard-application_ for sending the notification to the _TypeApprovalRegister_. ### Types of Internal Forwardings -Forwardings can be distinguished by the way of reacting on Management requests. +_Forwardings_ can be distinguished by the way of reacting on _Management_. **InvariantProcessSnippet** -Whenever an InvariantProcessSnippet receives new contact information at its Management, it updates the existing Output. -Example: Every application has to inform the OamLog about requests that are addressing its OaM part of the REST interface. +Whenever an _InvariantProcessSnippet_ receives new address information at its _Management_, it updates the existing _OperationClient_, which is referenced as _Output_. +Example: Every application has to inform the _OamLog_ about requests that are addressing the OaM segment of its REST API. Of course, it would not be wished, if third parties would receive copies of this information. -Thus, the Forwarding to the OamLog is made in such a way that only a single OperationClient (Reaction) gets activated by an Event. +Thus, the _Forwarding_ to the _OamLog_ is made in such a way that only a single _OperationClient_ (_Output_) could get activated. **Subscription** -Whenever a Subscription receives new contact information at its Management, it adds another Output. -Consequently, the Subscription needs a second Management for removing an Output from the list. -In case of the Subscription, all the existing OperationClients react on an Event. +Whenever a _Subscription_ receives new contact information at its _Management_, it creates another stack of _Clients_ and adds another _Output_. +Consequently, the _Subscription_ needs a second _Management_ for removing an _Output_ from the list. +In case of the _Subscription_, all the existing _Outputs_ are reacting on an _Input_. **ProcessSnippet** -Whenever a ProcessSnippet receives new contact information at its Management, it updates one out of the already existing Outputs. -In principle, the number of Outputs is not restricted, but it is invariant after the specification of the application has been handed over to implementation. -The ProcessSnippet is activating one or several of the OperationClients for reacting on an Event. -The reactions usually depend on the content of the Input, and it requires an internal decision to determine. -Obviously, the ProcessSnippet is at least close to, maybe even crossing the boundaries between Forwarding and Processing. -Up to now, the only way of describing Processing is scripting TestCases. +Whenever a _ProcessSnippet_ receives new contact information at its _Management_, it updates one out of the already existing _Outputs_. +In principle, the number of _Outputs_ is not restricted, but it is invariant after the specification of the application has been handed over to implementation. +The _ProcessSnippet_ is activating one or several of the _Outputs_ for reacting on an Event. +The reactions usually depend on the content of the _Input_, and it requires an internal decision to determine. +Obviously, the _ProcessSnippet_ is at least close to, maybe even crossing the boundaries between _Forwarding_ and _Processing_. +Up to now, the only way of describing _Processing_ is scripting _TestCases_. -Anyway, meaningful ServiceNames and ForwardingNames are supporting understanding the application from reading the OpenApiSpecification. +Anyway, meaningful _OperationNames_ and _ForwardingNames_ are supporting understanding the application from reading the OpenApiSpecification. -### Management of Internal Forwarding +### Substructure of Management of Internal Forwarding -In principle, Forwarding defines an Event-Reaction-relationship between at least two interfaces. -These interfaces can exist idenpendently from the Forwarding. -Thus, management of the Forwarding must destinguish e.g. removing the interface from the Forwarding and deleting it, because it might still be used for other purposes. -In practice, creating the interface and connecting it with the Forwarding is usually done by the same Management request, and it is left to the implementation to just create the interface, in case it is not already existing. -Also disconnecting the interface from the Forwarding and deleting it is usually done by the same Management request, and it is left to the implementation to just delete the interface (only clients!), if it is not referenced by any other Forwarding. -Nevertheless, the FowardingList allows expressing: +As you could see from the _ServiceList_ of the _RegistryOffice_, it provides separate _Operations_ for subscribing and unsubscribing. +The _OperationServer /v1/register-application_ is creating _Clients_ and adding references to the _ForwardingConstruct_. +The _OperationServer /v1/end-subscription_ is removing references from the _ForwardingConstruct_ and potentially deleting the _Clients_. +Thus, in general there might be several _Managements_ defined on a forwarding and the _ForwardingList_ is distinguishing their roles. + +In principle, _Forwarding_ defines an _Input_-_Output_-relationship between at least two interfaces. +These interfaces can exist idenpendently from the _ForwardingConstruct_. +Thus, management of the _Forwarding_ must destinguish e.g. removing the _Output_ from the _ForwardingConstruct_ and deleting the stack of _Clients_. +In practice, creating the _OperationClient_ and connecting it with the _ForwardingConstruct_ is usually done by the same _Management_. Also disconnecting the _Output_ from the _ForwardingConstruct_ and deleting the _Clients_ (if they are not referenced by any other _Forwarding_) is usually done by the same _Management_. +Nevertheless, the _FowardingList_ allows expressing: - Just changing already existing and connected interfaces - Just connecting already existing interfaces - Just disconnecting, but not deleting an interface (Deleting, but not disconnecting doesn't make sense.) - - -## Concept of External Forwarding -_Documentation about External Forwarding to be added_ diff --git a/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md b/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md index b4bfdbe6..c35838bc 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md @@ -1,5 +1,47 @@ # Structure of Names of Callbacks -Same names are used for callbacks in the OAS and ForwardingConstructs in the CONFIGfile. -The have to be defined as a part of the high level design in the ForwardingList already. +The _ForwardingName_, which is identifying a _Forwarding_ in the _ForwardingList_, will be re-used for identifying the resulting _ForwardingConstruct_ in the _CONFIGfile_ and for identifying the resulting callback in the OpenApiSpecification. +It is very much recommended to invest sufficient time and energy into definition of very descriptive names. +Ideally, even uninformed readers get enabled to understand the target of some callback or the relationship described by some _ForwardingConstruct_ exclusively from its naming. + +_ForwardingNames_ shall follow the UpperCamelCase spelling, means they shall start with a capital letter and every new word shall be indicated by a capital letter, too. + +In principle, there is no limitation to the length of the _ForwardingNames_. Because they shall explain the _Forwarding_, they are accepted to be a little longer, - maybe like a short sentence. Of course, transporting the same information with less words, would be preferred. + + +### ProcessSnippets + +_InvariantProcessSnippets_ are describing process flows, their _ForwardingName_ shall have the following structure: +_[description of the input]_**causes**_[description of the output]_ + +Description of the input: +If the _OperationName_ of the _Input_ indicates an order to do something (e.g. _/v1/register-yourself_, _/v1/embed-yourself_), it might make sense to start the description of the input with 'PromptFor' and to complete it with the ordered activity (e.g. PromptForRegistering, PromptForEmbedding). +If the nature of the _Input_ is more like a notification, which is indicating an event, it might make sense to just state the event (e.g. TypeApproval, OamRequest) + +Description of the output: +The description of the output should indicate the nature of the consequent request: +- 'Request', might indicate a request for providing a service (e.g. RequestForBroadcastingInfoAboutServerReplacement, LoggingRequest) +- 'Inquiry', might indicate a request for information (e.g. InquiryForAuthentication) + +In general, it is assumed that the addressed application is providing the service or information to the requesting application. If this would not be the case, this should be expressed in the description of the output. Source and destination should be indicated (e.g. RObeingRequestedToNotifyWithdrawnApprovalsToNewRelease). +If the _Output_ might involve multiple consequent requests of the same or even different kinds, it might make sense to express their result in the description of the output (e.g. TransferOfListOfApplications, CalculateCapacity) + +Examples: +- PromptForEmbeddingCausesRequestForBequeathingData +- TypeApprovalCausesRequestForEmbedding +- PromptForBequeathingDataCausesRObeingRequestedToNotifyWithdrawnApprovalsToNewRelease +- PromptForBequeathingDataCausesTransferOfListOfApplications + + +### Subscriptions + +In case of _Subscriptions_, it should suffice stating the type of notification. +If the notification is meant to address all applications of the application layer, this should be expressed by naming it broadcast. + +Examples: +- ApprovalNotification +- DeregistrationNotification +- LinkChangeNotification +- ServerReplacementBroadcast +- OperationUpdateBroadcast From 8fb0f454faa461d4a185f4784e884cf52a995aba Mon Sep 17 00:00:00 2001 From: openBackhaul Date: Tue, 17 Jan 2023 19:07:13 +0100 Subject: [PATCH 67/79] Add dox for OAS, CONFIGfile and TestCases --- .../ElementsApplicationPattern.md | 92 ++++++++++--------- .../ConceptOfConfigFile.md | 0 .../Functions/ConceptOfOas/ConceptOfOas.md | 0 .../ConceptOfTestCases/ConceptOfTestCases.md | 0 .../StructureOfConfigFile.md | 0 .../StructureOfOas/StructureOfOas.md | 0 .../StructureOfTestCases.md | 0 7 files changed, 49 insertions(+), 43 deletions(-) create mode 100644 doc/ElementsApplicationPattern/Functions/ConceptOfConfigFile/ConceptOfConfigFile.md create mode 100644 doc/ElementsApplicationPattern/Functions/ConceptOfOas/ConceptOfOas.md create mode 100644 doc/ElementsApplicationPattern/Functions/ConceptOfTestCases/ConceptOfTestCases.md create mode 100644 doc/ElementsApplicationPattern/Functions/StructureOfConfigFile/StructureOfConfigFile.md create mode 100644 doc/ElementsApplicationPattern/Functions/StructureOfOas/StructureOfOas.md create mode 100644 doc/ElementsApplicationPattern/Functions/StructureOfTestCases/StructureOfTestCases.md diff --git a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md index b01b9b33..3e735625 100644 --- a/doc/ElementsApplicationPattern/ElementsApplicationPattern.md +++ b/doc/ElementsApplicationPattern/ElementsApplicationPattern.md @@ -4,22 +4,28 @@ ### Concepts **General Design Principles** -* [API-First Approach](./Principles/ApiFirst/ApiFirst.md) -* [RESTful](./Principles/Restful/Restful.md) -* [Microservice](./Principles/Microservice/Microservice.md) -* [CONFIGfile](./Principles/ConfigFile/ConfigFile.md) +- [API-First Approach](./Principles/ApiFirst/ApiFirst.md) +- [RESTful](./Principles/Restful/Restful.md) +- [Microservice](./Principles/Microservice/Microservice.md) +- [CONFIGfile](./Principles/ConfigFile/ConfigFile.md) **Functions** -* [Structure of Services](./Functions/StructureOfServices/StructureOfServices.md) -* [Concept of Profiles](./Functions/ConceptOfProfiles/ConceptOfProfiles.md) -* [Concepts of Internal Forwarding](./Functions/ConceptsOfForwarding/ConceptsOfForwarding.md) +- [Structure of Services](./Functions/StructureOfServices/StructureOfServices.md) +- [Concept of Profiles](./Functions/ConceptOfProfiles/ConceptOfProfiles.md) +- [Concepts of Internal Forwarding](./Functions/ConceptsOfForwarding/ConceptsOfForwarding.md) +- [Concept of _CONFIGfile_](./Functions/ConceptOfConfigFile/ConceptOfConfigFile.md) +- [Structure of _CONFIGfile_](./Functions/StructureOfConfigFile/StructureOfConfigFile.md) +- [Concept of OpenApiSpecification](./Functions/ConceptOfOas/ConceptOfOas.md) +- [Structure of OpenApiSpecification](./Functions/StructureOfOas/StructureOfOas.md) +- [Concept of TestCases](./Functions/ConceptOfTestCases/ConceptOfTestCases.md) +- [Structure of TestCases](./Functions/StructureOfTestCases/StructureOfTestCases.md) **Names and IDs** -* [Structure of ApplicationNames](./Names/StructureOfApplicationNames/StructureOfApplicationNames.md) -* [Structure of ServiceNames](./Names/StructureOfServiceNames/StructureOfServiceNames.md) -* [Structure of Release Numbers](./Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md) -* [Structure of UUIDs](./Names/StructureOfUuids/StructureOfUuids.md) -* [Structure of CallbackNames](./Names/StructureOfCallbackNames/StructureOfCallbackNames.md) +- [Structure of ApplicationNames](./Names/StructureOfApplicationNames/StructureOfApplicationNames.md) +- [Structure of ServiceNames](./Names/StructureOfServiceNames/StructureOfServiceNames.md) +- [Structure of Release Numbers](./Names/StructureOfReleaseNumbers/StructureOfReleaseNumbers.md) +- [Structure of UUIDs](./Names/StructureOfUuids/StructureOfUuids.md) +- [Structure of CallbackNames](./Names/StructureOfCallbackNames/StructureOfCallbackNames.md) ### Underlying Information Model @@ -27,42 +33,42 @@ **Overview Information Model** **Classes** -* [ControlConstruct](./InformationModel/ControlConstruct/ControlConstruct.md) -* [LogicalTerminationPoint](./InformationModel/LogicalTerminationPoint/LogicalTerminationPoint.md) -* LayerProtocol -* Profile -* **ForwardingDomain**: The ForwardingDomain(FD) aggregates one or more ForrwardingConstruct(FC). Theoretically CC consists of a list of FDs. But practically a Microservice consists of a single FD instance. FDs are identified by a uuid. -* [ForwardingConstruct](./InformationModel/ForwardingConstruct/ForwardingConstruct.md) -* ForwardingConstructPort -* NetworkControlDomain -* Link +- [ControlConstruct](./InformationModel/ControlConstruct/ControlConstruct.md) +- [LogicalTerminationPoint](./InformationModel/LogicalTerminationPoint/LogicalTerminationPoint.md) +- LayerProtocol +- Profile +- **ForwardingDomain**: The ForwardingDomain(FD) aggregates one or more ForrwardingConstruct(FC). Theoretically CC consists of a list of FDs. But practically a Microservice consists of a single FD instance. FDs are identified by a uuid. +- [ForwardingConstruct](./InformationModel/ForwardingConstruct/ForwardingConstruct.md) +- ForwardingConstructPort +- NetworkControlDomain +- Link ### Basic Services -* /v1/bequeath-your-data-and-die -* /v1/start-application-in-generic-representation -* /v1/register-yourself -* /v1/embed-yourself -* /v1/redirect-service-request-information -* /v1/redirect-oam-request-information -* /v1/end-subscription -* /v1/inquire-oam-request-approvals -* /v1/update-client -* /v1/list-ltps-and-fcs -* /v1/redirect-topology-change-information -* /v1/update-operation-key -* /v1/update-operation-client -* /v1/inform-about-application -* /v1/inform-about-application-in-generic-representation -* /v1/inform-about-release-history -* /v1/inform-about-release-history-in-generic-representation +- /v1/bequeath-your-data-and-die +- /v1/start-application-in-generic-representation +- /v1/register-yourself +- /v1/embed-yourself +- /v1/redirect-service-request-information +- /v1/redirect-oam-request-information +- /v1/end-subscription +- /v1/inquire-oam-request-approvals +- /v1/update-client +- /v1/list-ltps-and-fcs +- /v1/redirect-topology-change-information +- /v1/update-operation-key +- /v1/update-operation-client +- /v1/inform-about-application +- /v1/inform-about-application-in-generic-representation +- /v1/inform-about-release-history +- /v1/inform-about-release-history-in-generic-representation ### Headers -* user -* originator -* x-correlator -* trace-indicator -* customer-journey +- user +- originator +- x-correlator +- trace-indicator +- customer-journey diff --git a/doc/ElementsApplicationPattern/Functions/ConceptOfConfigFile/ConceptOfConfigFile.md b/doc/ElementsApplicationPattern/Functions/ConceptOfConfigFile/ConceptOfConfigFile.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/ElementsApplicationPattern/Functions/ConceptOfOas/ConceptOfOas.md b/doc/ElementsApplicationPattern/Functions/ConceptOfOas/ConceptOfOas.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/ElementsApplicationPattern/Functions/ConceptOfTestCases/ConceptOfTestCases.md b/doc/ElementsApplicationPattern/Functions/ConceptOfTestCases/ConceptOfTestCases.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfConfigFile/StructureOfConfigFile.md b/doc/ElementsApplicationPattern/Functions/StructureOfConfigFile/StructureOfConfigFile.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfOas/StructureOfOas.md b/doc/ElementsApplicationPattern/Functions/StructureOfOas/StructureOfOas.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/ElementsApplicationPattern/Functions/StructureOfTestCases/StructureOfTestCases.md b/doc/ElementsApplicationPattern/Functions/StructureOfTestCases/StructureOfTestCases.md new file mode 100644 index 00000000..e69de29b From 31448e3adb996d004072a96d0880c0f278a23936 Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:11:36 +0100 Subject: [PATCH 68/79] Update ConceptsOfForwarding.md --- .../ConceptsOfForwarding.md | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md b/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md index 2b696c3f..c3c34c7a 100644 --- a/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md +++ b/doc/ElementsApplicationPattern/Functions/ConceptsOfForwarding/ConceptsOfForwarding.md @@ -4,7 +4,7 @@ ### Purpose of Internal Forwarding There are a lot of interactions between the applications of the modular application layer. -For example, whenever an application receives a request, it has to send one to the _ExecutionAndTraceLog_ application for documenting processing of the received request. +For example, whenever an application receives a request, it has to send one to the _ExecutionAndTraceLog_ application for documenting the processing of the received request. All these interactions between the applications are based on REST requests. The URIs of these REST requests must comprise e.g. TCP/IP address and _OperationName_. @@ -18,7 +18,7 @@ Address information of an already known application could be altered by modifyin This could be done manually in the CONFIGfile or via the OaM segment of the REST API during runtime. To some extend it is even automated via the service segment of the REST API. -So there are relationships between _OperationServers_ and _OperationClients_ (see example in the first paragraph). +'... whenever an application receives a request, it has to send one to the _ExecutionAndTraceLog_...' represents an example for the relationships between _OperationServers_ and _OperationClients_. If these relationships would be hardcoded, it would not be possible to redirect the flow from event to reaction, and a dynamic change of the application layer would not be possible. Thus, the relationships need to be documented in the CONFIGfiles of the individual applications, too. @@ -33,21 +33,21 @@ The _ForwardingList_ is supporting designing the relationships before documentin _ForwardingConstructs_ are describing relationships between events and reactions. Since we are dealing with REST servers, -- an event is a request, which has been received on one of the _OperationServers_ offered by the application and -- the reaction is a request, which has to be sent via one of the _OperationClients_ that are connecting another applications. -Obviously, a definition of a _ForwardingConstruct_ must comprise an _Input_ (_OperationServer_) and at least one _Output_ (one or several _OperationClients_). +- an event is a request, which has been received (_Input_) by one of the _OperationServers_ offered by the application and +- the reaction is a request, which has to be sent (_Output_) via one of the _OperationClients_ that are for connecting another application. +Obviously, a definition of a _ForwardingConstruct_ must comprise at least one _Input_ (reference to an _OperationServer_) and at least one _Output_ (reference to an _OperationClient_). As described above, we are documenting the relationships, because we want to be able to modify them. -If we want to automate modification, there must be services available on the REST API for facilitating this. -Thus, a definition of a _ForwardingConstruct_ must also comprise a _Management_ (_OperationServer_), whenever it shall be possible to automate changes (otherwise the _ForwardingConstruct_ could still be changed manually via OaM segment or altering the CONFIGfile). +If we want to automate the modification, there must be services available on the REST API for facilitating this. +Thus, a definition of a _ForwardingConstruct_ needs also to comprise a _Management_ (reference to an _OperationServer_), whenever it shall be possible to automate changes (otherwise the _ForwardingConstruct_ could still be changed manually via OaM segment or altering the CONFIGfile). Example: The _TypeApprovalRegister_ is subscribing for notifications about new registrations at the _RegistryOffice_. A _Forwarding_ from registration to notifying the _TypeApprovalRegister_ has to be defined in the _RegistryOffice_. This _Forwarding_ has to comprise the following _Servers_ and _Clients_: -- _Management_: The _TypeApprovalRegister_ is informing the _RegistryOffice_ about its TCP/IP address and _OperationName_ for receiving notifications about new registrations by addressing the _RegistryOffice's OperationServer _/v1/inquire-application-type-approvals_. The _RegistryOffice_ creates or updates a stack of _Clients_ from these information and it complements the corresponding _ForwardingConstruct_ by an _Output_ reference to the _OperationClient_. -- _Input_/event: Some new application is addressing the _RegistryOffice's OperationServer /v1/register-application_ for registering. -- _Output_/reaction: The _RegistryOffice_ is activating its _OperationClient /v1/regard-application_ for sending the notification to the _TypeApprovalRegister_. +- _Management_: The _TypeApprovalRegister_ is informing the _RegistryOffice_ about its TCP/IP address and _OperationName_ for receiving notifications about new registrations by addressing the _RegistryOffice's OperationServer /v1/inquire-application-type-approvals_. The _RegistryOffice_ creates or updates a stack of _Clients_ with these information and it complements the corresponding _ForwardingConstruct_ by an _Output_ reference to the _OperationClient_. +- _Input_: Some new application is addressing the _RegistryOffice's OperationServer /v1/register-application_ for registering. +- _Output_: The _RegistryOffice_ is activating its _OperationClient /v1/regard-application_ for sending the notification to the _TypeApprovalRegister_. ### Types of Internal Forwardings @@ -58,37 +58,38 @@ _Forwardings_ can be distinguished by the way of reacting on _Management_. Whenever an _InvariantProcessSnippet_ receives new address information at its _Management_, it updates the existing _OperationClient_, which is referenced as _Output_. Example: Every application has to inform the _OamLog_ about requests that are addressing the OaM segment of its REST API. Of course, it would not be wished, if third parties would receive copies of this information. -Thus, the _Forwarding_ to the _OamLog_ is made in such a way that only a single _OperationClient_ (_Output_) could get activated. +Thus, the _Forwarding_ towards the _OamLog_ is defined in such a way that just a single _OperationClient_ can be referenced as _Output_. **Subscription** -Whenever a _Subscription_ receives new contact information at its _Management_, it creates another stack of _Clients_ and adds another _Output_. -Consequently, the _Subscription_ needs a second _Management_ for removing an _Output_ from the list. -In case of the _Subscription_, all the existing _Outputs_ are reacting on an _Input_. +Whenever a _Subscription_ receives new contact information at its _Management_, it creates another stack of _Clients_ and adds another _Output_ to the _ForwardingConstruct_. +Consequently, the _Subscription_ needs a second _Management_ for removing an _Output_ from the _ForwardingConstruct_. +In case of the _Subscription_, all the existing _Outputs_ are reacting on an event at the _Input_. **ProcessSnippet** Whenever a _ProcessSnippet_ receives new contact information at its _Management_, it updates one out of the already existing _Outputs_. In principle, the number of _Outputs_ is not restricted, but it is invariant after the specification of the application has been handed over to implementation. -The _ProcessSnippet_ is activating one or several of the _Outputs_ for reacting on an Event. +This restriction is due to the individual logic, which is implemented by the _ProcessSnippet_. +The _ProcessSnippet_ is activating one or several of the _Outputs_ for reacting on an event. The reactions usually depend on the content of the _Input_, and it requires an internal decision to determine. Obviously, the _ProcessSnippet_ is at least close to, maybe even crossing the boundaries between _Forwarding_ and _Processing_. -Up to now, the only way of describing _Processing_ is scripting _TestCases_. - -Anyway, meaningful _OperationNames_ and _ForwardingNames_ are supporting understanding the application from reading the OpenApiSpecification. +Up to now, the only way of describing the logic, which is implemented by the _ProcessSnippet_, is scripting _TestCases_. ### Substructure of Management of Internal Forwarding -As you could see from the _ServiceList_ of the _RegistryOffice_, it provides separate _Operations_ for subscribing and unsubscribing. -The _OperationServer /v1/register-application_ is creating _Clients_ and adding references to the _ForwardingConstruct_. -The _OperationServer /v1/end-subscription_ is removing references from the _ForwardingConstruct_ and potentially deleting the _Clients_. -Thus, in general there might be several _Managements_ defined on a forwarding and the _ForwardingList_ is distinguishing their roles. - -In principle, _Forwarding_ defines an _Input_-_Output_-relationship between at least two interfaces. -These interfaces can exist idenpendently from the _ForwardingConstruct_. -Thus, management of the _Forwarding_ must destinguish e.g. removing the _Output_ from the _ForwardingConstruct_ and deleting the stack of _Clients_. -In practice, creating the _OperationClient_ and connecting it with the _ForwardingConstruct_ is usually done by the same _Management_. Also disconnecting the _Output_ from the _ForwardingConstruct_ and deleting the _Clients_ (if they are not referenced by any other _Forwarding_) is usually done by the same _Management_. -Nevertheless, the _FowardingList_ allows expressing: -- Just changing already existing and connected interfaces -- Just connecting already existing interfaces -- Just disconnecting, but not deleting an interface -(Deleting, but not disconnecting doesn't make sense.) +As already mentioned above, separate _Managements_ are used for subscribing and unsubscribing. +Subscribing is creating _Clients_ and adding references to the _ForwardingConstruct_. +Unsubscribing is removing references from the _ForwardingConstruct_ and potentially deleting the _Clients_. +Thus, in general there might be several _Managements_ defined on a _Forwarding_ and the _ForwardingList_ allows to distinguish their roles. + +In principle, _Forwarding_ defines just an _Input_-_Output_-relationship between at least two interfaces. +These interfaces could exist idenpendently from the _ForwardingConstruct_. + +The _ForwardingList_ allows distinguishing the following kinds of _Management_ by an individual _OperationServer_: +- Just changing already existing and connected interfaces +- Just connecting already existing interfaces +- Just disconnecting, but not deleting an interface + +(Deleting, but not disconnecting doesn't make sense.) +Unfortunately, the _ForwardingList_ is exceeding the capabilities of the syntax of the OpenApiSpecification v3.0 is these regards. +How to code the information into description statements will be described in later chapters. From ab1a4e64ed7ff72dd024057ea5484482df05742e Mon Sep 17 00:00:00 2001 From: Thorsten Heinze <46722892+openBackhaul@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:29:35 +0100 Subject: [PATCH 69/79] Update StructureOfCallbackNames.md --- .../StructureOfCallbackNames.md | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md b/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md index c35838bc..67237409 100644 --- a/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md +++ b/doc/ElementsApplicationPattern/Names/StructureOfCallbackNames/StructureOfCallbackNames.md @@ -1,47 +1,50 @@ -# Structure of Names of Callbacks +# Structure of ForwardingNames The _ForwardingName_, which is identifying a _Forwarding_ in the _ForwardingList_, will be re-used for identifying the resulting _ForwardingConstruct_ in the _CONFIGfile_ and for identifying the resulting callback in the OpenApiSpecification. It is very much recommended to invest sufficient time and energy into definition of very descriptive names. -Ideally, even uninformed readers get enabled to understand the target of some callback or the relationship described by some _ForwardingConstruct_ exclusively from its naming. +Ideally, even uninformed readers could understand the logic, which is implemented by some _Forwarding_, from its naming. _ForwardingNames_ shall follow the UpperCamelCase spelling, means they shall start with a capital letter and every new word shall be indicated by a capital letter, too. -In principle, there is no limitation to the length of the _ForwardingNames_. Because they shall explain the _Forwarding_, they are accepted to be a little longer, - maybe like a short sentence. Of course, transporting the same information with less words, would be preferred. +In principle, there are no limitations to the length of the _ForwardingNames_. +Because they shall actually explain the _Forwarding_, they are accepted to be a little longer, - maybe like a short sentence. +Of course, transporting the same information with less words, would be preferred. -### ProcessSnippets +### ProcessSnippets _InvariantProcessSnippets_ are describing process flows, their _ForwardingName_ shall have the following structure: _[description of the input]_**causes**_[description of the output]_ Description of the input: -If the _OperationName_ of the _Input_ indicates an order to do something (e.g. _/v1/register-yourself_, _/v1/embed-yourself_), it might make sense to start the description of the input with 'PromptFor' and to complete it with the ordered activity (e.g. PromptForRegistering, PromptForEmbedding). -If the nature of the _Input_ is more like a notification, which is indicating an event, it might make sense to just state the event (e.g. TypeApproval, OamRequest) +If the _OperationName_, which is referenced as the _Input_, indicates an order to do something (e.g. _/v1/register-yourself_, _/v1/embed-yourself_), it might make sense to start the description of the input with 'PromptFor' and to complete it with the ordered activity (e.g. PromptForRegistering, PromptForEmbedding). +If the nature of the _Input_ is more like a notification, which is indicating an event, it might make sense to just state the kind of event (e.g. TypeApproval, OamRequest). Description of the output: -The description of the output should indicate the nature of the consequent request: -- 'Request', might indicate a request for providing a service (e.g. RequestForBroadcastingInfoAboutServerReplacement, LoggingRequest) -- 'Inquiry', might indicate a request for information (e.g. InquiryForAuthentication) +The description of the output should indicate the nature of the consequent action: +- 'Request', might indicate asking for provissioning of a service (e.g. RequestForBroadcastingInfoAboutServerReplacement, LoggingRequest) +- 'Inquiry', might indicate asking for information (e.g. InquiryForAuthentication) In general, it is assumed that the addressed application is providing the service or information to the requesting application. If this would not be the case, this should be expressed in the description of the output. Source and destination should be indicated (e.g. RObeingRequestedToNotifyWithdrawnApprovalsToNewRelease). -If the _Output_ might involve multiple consequent requests of the same or even different kinds, it might make sense to express their result in the description of the output (e.g. TransferOfListOfApplications, CalculateCapacity) +If the _Output_ might involve multiple consequent requests of the same or even different kinds, it might make sense to express their consolidated result in the description of the output (e.g. TransferOfListOfApplications, RetrievingLiveNetworkInput) -Examples: -- PromptForEmbeddingCausesRequestForBequeathingData -- TypeApprovalCausesRequestForEmbedding -- PromptForBequeathingDataCausesRObeingRequestedToNotifyWithdrawnApprovalsToNewRelease -- PromptForBequeathingDataCausesTransferOfListOfApplications +Examples: +- PromptForEmbeddingCausesRequestForBequeathingData +- TypeApprovalCausesRequestForEmbedding +- PromptForBequeathingDataCausesRObeingRequestedToNotifyWithdrawnApprovalsToNewRelease +- PromptForBequeathingDataCausesTransferOfListOfApplications +- PromptForCapacityCalculationCausesRetrievingLiveNetworkInput -### Subscriptions +### Subscriptions In case of _Subscriptions_, it should suffice stating the type of notification. If the notification is meant to address all applications of the application layer, this should be expressed by naming it broadcast. -Examples: -- ApprovalNotification -- DeregistrationNotification -- LinkChangeNotification -- ServerReplacementBroadcast -- OperationUpdateBroadcast +Examples: +- ApprovalNotification +- DeregistrationNotification +- LinkChangeNotification +- ServerReplacementBroadcast +- OperationUpdateBroadcast From ef1f3cc311ea420dd0e17637ba52b5821506dc86 Mon Sep 17 00:00:00 2001 From: Martin Sunal Date: Thu, 19 Jan 2023 10:53:37 +0100 Subject: [PATCH 70/79] Added openbackhaul-oas3-tools - project is forked from https://github.com/paxet-io/oas3-tools/releases/tag/v2.3.1 - removed .github - branding changes in package.json fixes #209 Signed-off-by: Martin Sunal --- server/oas3-tools/.gitignore | 13 + server/oas3-tools/.jshintrc | 22 + server/oas3-tools/LICENSE | 21 + server/oas3-tools/README.md | 3 + .../examples/petstore/api/petstore.yaml | 218 ++ .../examples/petstore/controllers/Pet.js | 36 + .../oas3-tools/examples/petstore/example.js | 42 + .../examples/petstore/package-lock.json | 70 + .../oas3-tools/examples/petstore/package.json | 16 + .../examples/petstore/services/PetService.js | 87 + .../examples/petstore/utils/writer.js | 43 + server/oas3-tools/oas2.yaml | 707 ++++++ server/oas3-tools/oas3.yaml | 700 ++++++ server/oas3-tools/package-lock.json | 2167 +++++++++++++++++ server/oas3-tools/package.json | 35 + server/oas3-tools/src/index.ts | 7 + .../src/middleware/express.app.config.ts | 95 + server/oas3-tools/src/middleware/helpers.ts | 72 + .../src/middleware/logging.options.ts | 10 + .../oas3-tools/src/middleware/oas3.options.ts | 25 + .../middleware/swagger-ui/favicon-16x16.png | Bin 0 -> 665 bytes .../middleware/swagger-ui/favicon-32x32.png | Bin 0 -> 628 bytes .../src/middleware/swagger-ui/index.html | 73 + .../swagger-ui/oauth2-redirect.html | 67 + .../swagger-ui/swagger-ui-bundle.js | 100 + .../swagger-ui-standalone-preset.js | 14 + .../swagger-ui-standalone-preset.js.map | 1 + .../src/middleware/swagger-ui/swagger-ui.css | 3 + .../middleware/swagger-ui/swagger-ui.css.map | 1 + .../src/middleware/swagger-ui/swagger-ui.js | 9 + .../middleware/swagger-ui/swagger-ui.js.map | 1 + .../src/middleware/swagger.parameters.ts | 61 + .../src/middleware/swagger.router.ts | 144 ++ .../src/middleware/swagger.ui.options.ts | 23 + .../oas3-tools/src/middleware/swagger.ui.ts | 102 + server/oas3-tools/tsconfig.json | 17 + 36 files changed, 5005 insertions(+) create mode 100644 server/oas3-tools/.gitignore create mode 100644 server/oas3-tools/.jshintrc create mode 100644 server/oas3-tools/LICENSE create mode 100644 server/oas3-tools/README.md create mode 100644 server/oas3-tools/examples/petstore/api/petstore.yaml create mode 100644 server/oas3-tools/examples/petstore/controllers/Pet.js create mode 100644 server/oas3-tools/examples/petstore/example.js create mode 100644 server/oas3-tools/examples/petstore/package-lock.json create mode 100644 server/oas3-tools/examples/petstore/package.json create mode 100644 server/oas3-tools/examples/petstore/services/PetService.js create mode 100644 server/oas3-tools/examples/petstore/utils/writer.js create mode 100644 server/oas3-tools/oas2.yaml create mode 100644 server/oas3-tools/oas3.yaml create mode 100644 server/oas3-tools/package-lock.json create mode 100644 server/oas3-tools/package.json create mode 100644 server/oas3-tools/src/index.ts create mode 100644 server/oas3-tools/src/middleware/express.app.config.ts create mode 100644 server/oas3-tools/src/middleware/helpers.ts create mode 100644 server/oas3-tools/src/middleware/logging.options.ts create mode 100644 server/oas3-tools/src/middleware/oas3.options.ts create mode 100644 server/oas3-tools/src/middleware/swagger-ui/favicon-16x16.png create mode 100644 server/oas3-tools/src/middleware/swagger-ui/favicon-32x32.png create mode 100644 server/oas3-tools/src/middleware/swagger-ui/index.html create mode 100644 server/oas3-tools/src/middleware/swagger-ui/oauth2-redirect.html create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui-bundle.js create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui-standalone-preset.js create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui-standalone-preset.js.map create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui.css create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui.css.map create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui.js create mode 100644 server/oas3-tools/src/middleware/swagger-ui/swagger-ui.js.map create mode 100644 server/oas3-tools/src/middleware/swagger.parameters.ts create mode 100644 server/oas3-tools/src/middleware/swagger.router.ts create mode 100644 server/oas3-tools/src/middleware/swagger.ui.options.ts create mode 100644 server/oas3-tools/src/middleware/swagger.ui.ts create mode 100644 server/oas3-tools/tsconfig.json diff --git a/server/oas3-tools/.gitignore b/server/oas3-tools/.gitignore new file mode 100644 index 00000000..9dba71cc --- /dev/null +++ b/server/oas3-tools/.gitignore @@ -0,0 +1,13 @@ +*.iml +**/node_modules/ +**/npm-debug.log +bower_components/ +coverage/ +.idea/ +dist/ +test/1.2/test-specs-browser.js +test/2.0/test-specs-browser.js +test/*/browser +.tern-project +.project +.settings/ diff --git a/server/oas3-tools/.jshintrc b/server/oas3-tools/.jshintrc new file mode 100644 index 00000000..ae855597 --- /dev/null +++ b/server/oas3-tools/.jshintrc @@ -0,0 +1,22 @@ +{ + "bitwise": true, + "browser": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "esnext": true, + "immed": true, + "indent": 2, + "latedef": true, + "laxcomma": true, + "newcap": true, + "noarg": true, + "node": true, + "quotmark": "single", + "regexp": true, + "smarttabs": true, + "strict": true, + "trailing": true, + "undef": true, + "unused": true +} diff --git a/server/oas3-tools/LICENSE b/server/oas3-tools/LICENSE new file mode 100644 index 00000000..06d2bcd0 --- /dev/null +++ b/server/oas3-tools/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Apigee Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/server/oas3-tools/README.md b/server/oas3-tools/README.md new file mode 100644 index 00000000..ae16f5f9 --- /dev/null +++ b/server/oas3-tools/README.md @@ -0,0 +1,3 @@ +# Swagger-UI and API REST Routing for Open API v3. + +Project is forked from https://github.com/paxet-io/oas3-tools release v2.3.1 \ No newline at end of file diff --git a/server/oas3-tools/examples/petstore/api/petstore.yaml b/server/oas3-tools/examples/petstore/api/petstore.yaml new file mode 100644 index 00000000..8c79abb0 --- /dev/null +++ b/server/oas3-tools/examples/petstore/api/petstore.yaml @@ -0,0 +1,218 @@ +openapi: 3.0.1 +info: + title: Swagger Petstore + description: | + This is a sample Petstore server. You can find + out more about Swagger at + [http://swagger.io](http://swagger.io) or on + [irc.freenode.net, #swagger](http://swagger.io/irc/). + termsOfService: http://swagger.io/terms/ + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.0 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: + - url: / +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: http://swagger.io +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + operationId: addPet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + x-swagger-router-controller: Pet + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + style: form + explode: true + schema: + type: array + items: + type: string + default: available + enum: + - available + - pending + - sold + - name: sessionid + in: cookie + required: false + style: form + explode: true + schema: + type: string + responses: + "200": + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + x-content-type: application/json + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid status value + security: + - petstore_auth: + - write:pets + - read:pets + x-swagger-router-controller: Pet + + /pet/{petId}: + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + style: simple + explode: false + schema: + type: integer + format: int64 + responses: + "200": + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + x-swagger-router-controller: Pet + +components: + schemas: + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + example: + name: name + id: 6 + xml: + name: Category + Pet: + required: + - name + - photoUrls + type: object + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + example: + photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + xml: + name: Pet + requestBodies: + Pet: + description: Pet object that needs to be added to the store + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + required: true + securitySchemes: + bearer: + type: http + scheme: bearer + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: http://petstore.swagger.io/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + api_key: + type: apiKey + name: api_key + in: header diff --git a/server/oas3-tools/examples/petstore/controllers/Pet.js b/server/oas3-tools/examples/petstore/controllers/Pet.js new file mode 100644 index 00000000..2f5c8955 --- /dev/null +++ b/server/oas3-tools/examples/petstore/controllers/Pet.js @@ -0,0 +1,36 @@ +'use strict'; + +var utils = require('../utils/writer.js'); +var Pet = require('../services/PetService'); + +module.exports.addPet = function addPet (req, res, next, body) { + Pet.addPet(body) + .then(function (response) { + utils.writeJson(res, response); + }) + .catch(function (response) { + utils.writeJson(res, response); + }); +}; + +module.exports.findPetsByStatus = function findPetsByStatus (req, res, next, status, sessionid) { + + Pet.findPetsByStatus(status,sessionid) + .then(function (response) { + utils.writeJson(res, response); + }) + .catch(function (response) { + utils.writeJson(res, response); + }); +}; + +module.exports.getPetById = function getPetById (req, res, next, petId) { + Pet.getPetById(petId) + .then(function (response) { + utils.writeJson(res, response); + }) + .catch(function (response) { + utils.writeJson(res, response); + }); +}; + diff --git a/server/oas3-tools/examples/petstore/example.js b/server/oas3-tools/examples/petstore/example.js new file mode 100644 index 00000000..d33681df --- /dev/null +++ b/server/oas3-tools/examples/petstore/example.js @@ -0,0 +1,42 @@ +'use strict'; + +var path = require('path'); +var http = require('http'); + +var oas3Tools = require('oas3-tools'); +var serverPort = 8080; + +function validate(request, scopes, schema) { + // security stuff here + return true; +} + +// swaggerRouter configuration +var options = { + routing: { + controllers: path.join(__dirname, './controllers') + }, + logging: { + format: 'combined', + errorLimit: 400 + }, + openApiValidator: { + + validateSecurity: { + handlers: { + petstore_auth: validate, + api_key: validate + } + } + } +}; + + +var expressAppConfig = oas3Tools.expressAppConfig(path.join(__dirname, 'api/petstore.yaml'), options); +var app = expressAppConfig.getApp(); + +// Initialize the Swagger middleware +http.createServer(app).listen(serverPort, function () { + console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort); + console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort); +}); diff --git a/server/oas3-tools/examples/petstore/package-lock.json b/server/oas3-tools/examples/petstore/package-lock.json new file mode 100644 index 00000000..d0531738 --- /dev/null +++ b/server/oas3-tools/examples/petstore/package-lock.json @@ -0,0 +1,70 @@ +{ + "name": "petstore-example", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "petstore-example", + "version": "1.0.0", + "license": "Unlicense", + "dependencies": { + "oas3-tools": "file:../../" + } + }, + "../..": { + "name": "openbackhaul-oas3-tools", + "version": "2.3.1", + "license": "MIT", + "dependencies": { + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "debug": "^4.3.4", + "express": "^4.18.1", + "express-openapi-validator": "^4.13.8", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "morgan": "^1.10.0", + "parseurl": "^1.3.3", + "serve-static": "^1.15.0" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/express": "^4.17.13", + "@types/js-yaml": "^4.0.5", + "@types/lodash": "^4.14.182", + "@types/parseurl": "^1.3.1", + "@types/serve-static": "^1.15.0", + "typescript": "^4.7.4" + } + }, + "node_modules/oas3-tools": { + "resolved": "../..", + "link": true + } + }, + "dependencies": { + "oas3-tools": { + "version": "file:../..", + "requires": { + "@types/debug": "^4.1.7", + "@types/express": "^4.17.13", + "@types/js-yaml": "^4.0.5", + "@types/lodash": "^4.14.182", + "@types/parseurl": "^1.3.1", + "@types/serve-static": "^1.15.0", + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "debug": "^4.3.4", + "express": "^4.18.1", + "express-openapi-validator": "^4.13.8", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "morgan": "^1.10.0", + "parseurl": "^1.3.3", + "serve-static": "^1.15.0", + "typescript": "^4.7.4" + } + } + } +} diff --git a/server/oas3-tools/examples/petstore/package.json b/server/oas3-tools/examples/petstore/package.json new file mode 100644 index 00000000..ae9c66fd --- /dev/null +++ b/server/oas3-tools/examples/petstore/package.json @@ -0,0 +1,16 @@ +{ + "name": "petstore-example", + "version": "1.0.0", + "description": "", + "scripts": { + "start": "node example.js" + }, + "keywords": [ + "swagger" + ], + "license": "Unlicense", + "private": true, + "dependencies": { + "oas3-tools": "file:../../" + } +} diff --git a/server/oas3-tools/examples/petstore/services/PetService.js b/server/oas3-tools/examples/petstore/services/PetService.js new file mode 100644 index 00000000..fc835a39 --- /dev/null +++ b/server/oas3-tools/examples/petstore/services/PetService.js @@ -0,0 +1,87 @@ +'use strict'; + + +/** + * Add a new pet to the store + * + * body Pet Pet object that needs to be added to the store + * no response value expected for this operation + **/ +exports.addPet = function(body) { + return new Promise(function(resolve, reject) { + resolve(); + }); +}; + +/** + * Finds Pets by status + * Multiple status values can be provided with comma separated strings + * + * status List Status values that need to be considered for filter + * sessionid String (optional) + * returns List + **/ +exports.findPetsByStatus = function(status,sessionid) { + return new Promise(function(resolve, reject) { + var examples = {}; + examples['application/json'] = [{ + 'photoUrls': [ 'photoUrls', 'photoUrls' ], + 'name' : 'doggie', + 'id' : 0, + 'category' : { + 'name' : 'name', + 'id' : 6 + }, + 'tags' : [ { + 'name' : 'name', + 'id' : 1 + }, { + 'name' : 'name', + 'id' : 1 + } ], + 'status' : 'available' + } ]; + if (Object.keys(examples).length > 0) { + resolve(examples[Object.keys(examples)[0]]); + } else { + resolve(); + } + }); +}; + +/** + * Find pet by ID + * Returns a single pet + * + * petId Long ID of pet to return + * returns Pet + **/ +exports.getPetById = function(petId) { + + return new Promise(function(resolve, reject) { + var examples = {}; + examples['application/json'] = { + 'photoUrls' : [ 'photoUrls', 'photoUrls' ], + 'name' : 'doggie', + 'id' : 0, + 'category' : { + 'name' : 'name', + 'id' : 6 + }, + 'tags' : [ { + 'name' : 'name', + 'id' : 1 + }, { + 'name' : 'name', + 'id' : 1 + } ], + 'status' : 'available' + }; + if (Object.keys(examples).length > 0) { + resolve(examples[Object.keys(examples)[0]]); + } else { + resolve(); + } + }); +}; + diff --git a/server/oas3-tools/examples/petstore/utils/writer.js b/server/oas3-tools/examples/petstore/utils/writer.js new file mode 100644 index 00000000..4f92ead9 --- /dev/null +++ b/server/oas3-tools/examples/petstore/utils/writer.js @@ -0,0 +1,43 @@ +var ResponsePayload = function(code, payload) { + this.code = code; + this.payload = payload; +} + +exports.respondWithCode = function(code, payload) { + return new ResponsePayload(code, payload); +} + +var writeJson = exports.writeJson = function(response, arg1, arg2) { + var code; + var payload; + + if(arg1 && arg1 instanceof ResponsePayload) { + writeJson(response, arg1.payload, arg1.code); + return; + } + + if(arg2 && Number.isInteger(arg2)) { + code = arg2; + } + else { + if(arg1 && Number.isInteger(arg1)) { + code = arg1; + } + } + if(code && arg1) { + payload = arg1; + } + else if(arg1) { + payload = arg1; + } + + if(!code) { + // if no response code given, we default to 200 + code = 200; + } + if(typeof payload === 'object') { + payload = JSON.stringify(payload, null, 2); + } + response.writeHead(code, {'Content-Type': 'application/json'}); + response.end(payload); +} diff --git a/server/oas3-tools/oas2.yaml b/server/oas3-tools/oas2.yaml new file mode 100644 index 00000000..5a30bdc0 --- /dev/null +++ b/server/oas3-tools/oas2.yaml @@ -0,0 +1,707 @@ +swagger: '2.0' +info: + description: 'This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.' + version: 1.0.0 + title: Swagger Petstore + termsOfService: 'http://swagger.io/terms/' + contact: + email: apiteam@swagger.io + license: + name: Apache-2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +host: petstore.swagger.io +basePath: /v2 +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: 'http://swagger.io' + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user + externalDocs: + description: Find out more about our store + url: 'http://swagger.io' +schemes: + - http +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + description: '' + operationId: addPet + consumes: + - application/json + - application/xml + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: Pet object that needs to be added to the store + required: true + schema: + $ref: '#/definitions/Pet' + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + put: + tags: + - pet + summary: Update an existing pet + description: '' + operationId: updatePet + consumes: + - application/json + - application/xml + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: Pet object that needs to be added to the store + required: true + schema: + $ref: '#/definitions/Pet' + responses: + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + produces: + - application/xml + - application/json + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + type: array + items: + type: string + enum: + - available + - pending + - sold + default: available + collectionFormat: csv + responses: + '200': + description: successful operation + schema: + type: array + items: + $ref: '#/definitions/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.' + operationId: findPetsByTags + produces: + - application/xml + - application/json + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + type: array + items: + type: string + collectionFormat: csv + responses: + '200': + description: successful operation + schema: + type: array + items: + $ref: '#/definitions/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + deprecated: true + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + produces: + - application/xml + - application/json + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + type: integer + format: int64 + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + consumes: + - application/x-www-form-urlencoded + produces: + - application/xml + - application/json + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + type: integer + format: int64 + - name: name + in: formData + description: Updated name of the pet + required: false + type: string + - name: status + in: formData + description: Updated status of the pet + required: false + type: string + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + produces: + - application/xml + - application/json + parameters: + - name: api_key + in: header + required: false + type: string + - name: petId + in: path + description: Pet id to delete + required: true + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + consumes: + - multipart/form-data + produces: + - application/json + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + type: integer + format: int64 + - name: additionalMetadata + in: formData + description: Additional data to pass to server + required: false + type: string + - name: file + in: formData + description: file to upload + required: false + type: file + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + produces: + - application/json + parameters: [] + responses: + '200': + description: successful operation + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: '' + operationId: placeOrder + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: order placed for purchasing the pet + required: true + schema: + $ref: '#/definitions/Order' + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/Order' + '400': + description: Invalid Order + '/store/order/{orderId}': + get: + tags: + - store + summary: Find purchase order by ID + description: 'For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions' + operationId: getOrderById + produces: + - application/xml + - application/json + parameters: + - name: orderId + in: path + description: ID of pet that needs to be fetched + required: true + type: integer + maximum: 5 + minimum: 1 + format: int64 + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + operationId: deleteOrder + produces: + - application/xml + - application/json + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + type: string + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: Created user object + required: true + schema: + $ref: '#/definitions/User' + responses: + default: + description: successful operation + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithArrayInput + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: List of user object + required: true + schema: + type: array + items: + $ref: '#/definitions/User' + responses: + default: + description: successful operation + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithListInput + produces: + - application/xml + - application/json + parameters: + - in: body + name: body + description: List of user object + required: true + schema: + type: array + items: + $ref: '#/definitions/User' + responses: + default: + description: successful operation + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + produces: + - application/xml + - application/json + parameters: + - name: username + in: query + description: The user name for login + required: true + type: string + - name: password + in: query + description: The password for login in clear text + required: true + type: string + responses: + '200': + description: successful operation + schema: + type: string + headers: + X-Rate-Limit: + type: integer + format: int32 + description: calls per hour allowed by the user + X-Expires-After: + type: string + format: date-time + description: date in UTC when toekn expires + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + produces: + - application/xml + - application/json + parameters: [] + responses: + default: + description: successful operation + '/user/{username}': + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + produces: + - application/xml + - application/json + parameters: + - name: username + in: path + description: 'The name that needs to be fetched. Use user1 for testing. ' + required: true + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Updated user + description: This can only be done by the logged in user. + operationId: updateUser + produces: + - application/xml + - application/json + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + type: string + - in: body + name: body + description: Updated user object + required: true + schema: + $ref: '#/definitions/User' + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + produces: + - application/xml + - application/json + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found +securityDefinitions: + petstore_auth: + type: oauth2 + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' + flow: implicit + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header +definitions: + Order: + title: Pet Order + description: An order for a pets from the pet store + type: object + properties: + id: + type: integer + format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + type: boolean + default: false + xml: + name: Order + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Category + User: + title: a User + description: A User who is purchasing from the pet store + type: object + properties: + id: + type: integer + format: int64 + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + type: string + userStatus: + type: integer + format: int32 + description: User Status + xml: + name: User + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Tag + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/definitions/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/definitions/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: Pet + ApiResponse: + title: An uploaded response + description: Describes the result of uploading an image resource + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' diff --git a/server/oas3-tools/oas3.yaml b/server/oas3-tools/oas3.yaml new file mode 100644 index 00000000..765afd90 --- /dev/null +++ b/server/oas3-tools/oas3.yaml @@ -0,0 +1,700 @@ +openapi: 3.0.1 +servers: [] +info: + description: | + This is a sample Petstore server. You can find + out more about Swagger at + [http://swagger.io](http://swagger.io) or on + [irc.freenode.net, #swagger](http://swagger.io/irc/). + version: "1.0.0" + title: Swagger Petstore + termsOfService: 'http://swagger.io/terms/' + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: 'http://swagger.io' + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user + externalDocs: + description: Find out more about our store + url: 'http://swagger.io' +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + operationId: addPet + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + put: + tags: + - pet + summary: Update an existing pet + operationId: updatePet + responses: + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + explode: true + schema: + type: array + items: + type: string + enum: + - available + - pending + - sold + default: available + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: >- + Muliple tags can be provided with comma separated strings. Use\ \ tag1, + tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + deprecated: true + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + post: + tags: + - pet + summary: Updates a pet in the store with form data + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + delete: + tags: + - pet + summary: Deletes a pet + operationId: deletePet + parameters: + - name: api_key + in: header + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': + post: + tags: + - pet + summary: uploads an image + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + operationId: placeOrder + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid Order + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + '/store/order/{orderId}': + get: + tags: + - store + summary: Find purchase order by ID + description: >- + For valid response try integer IDs with value >= 1 and <= 10.\ \ Other + values will generated exceptions + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of pet that needs to be fetched + required: true + schema: + type: integer + format: int64 + minimum: 1 + maximum: 10 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/xml: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: >- + For valid response try integer IDs with positive integer value.\ \ + Negative or non-integer values will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: integer + format: int64 + minimum: 1 + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + responses: + default: + description: successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + operationId: createUsersWithArrayInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + operationId: createUsersWithListInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/login: + get: + tags: + - user + summary: Logs user into the system + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: true + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: true + schema: + type: string + responses: + '200': + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when token expires + schema: + type: string + format: date-time + content: + application/json: + schema: + type: string + application/xml: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + operationId: logoutUser + responses: + default: + description: successful operation + '/user/{username}': + get: + tags: + - user + summary: Get user by user name + operationId: getUserByName + parameters: + - name: username + in: path + description: The name that needs to be fetched. Use user1 for testing. + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/xml: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Updated user + description: This can only be done by the logged in user. + parameters: + - name: username + in: path + description: name that need to be updated + required: true + schema: + type: string + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found + /test: + get: + security: + - bearer: [] + operationId: testMethod + responses: + 200: + description: peticion realizada con exito + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Test' +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' +components: + schemas: + Order: + type: object + properties: + id: + type: integer + format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + type: boolean + default: false + xml: + name: Order + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Category + User: + type: object + properties: + id: + type: integer + format: int64 + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + type: string + userStatus: + type: integer + format: int32 + description: User Status + xml: + name: User + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Tag + Pet: + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: Pet + ApiResponse: + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string + Test: + type: string + example: "" + requestBodies: + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + UserArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: List of user object + required: true + securitySchemes: + bearer: + type: http + scheme: bearer + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header \ No newline at end of file diff --git a/server/oas3-tools/package-lock.json b/server/oas3-tools/package-lock.json new file mode 100644 index 00000000..c8f60ddb --- /dev/null +++ b/server/oas3-tools/package-lock.json @@ -0,0 +1,2167 @@ +{ + "name": "openbackhaul-oas3-tools", + "version": "2.3.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "openbackhaul-oas3-tools", + "version": "2.3.1", + "license": "MIT", + "dependencies": { + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "debug": "^4.3.4", + "express": "^4.18.1", + "express-openapi-validator": "^4.13.8", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "morgan": "^1.10.0", + "parseurl": "^1.3.3", + "serve-static": "^1.15.0" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/express": "^4.17.13", + "@types/js-yaml": "^4.0.5", + "@types/lodash": "^4.14.182", + "@types/parseurl": "^1.3.1", + "@types/serve-static": "^1.15.0", + "typescript": "^4.7.4" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", + "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "18.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.5.tgz", + "integrity": "sha512-NcKK6Ts+9LqdHJaW6HQmgr7dT/i3GOHG+pt6BiWv++5SnjtRd4NXeiuN2kA153SjhXPR/AhHIPHPbrsbpUVOww==" + }, + "node_modules/@types/parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha512-sAfjGAYgJ/MZsk95f3ByThfJgasZk1hWJROghBwfKnLLNANEAG/WHckAcT6HNqx2sHwVlci7OAX7k1KYpOcgMw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-openapi-validator": { + "version": "4.13.8", + "resolved": "https://registry.npmjs.org/express-openapi-validator/-/express-openapi-validator-4.13.8.tgz", + "integrity": "sha512-89/sdkq+BKBuIyykaMl/vR9grFc3WFUPTjFo0THHbu+5g+q8rA7fKeoMfz+h84yOQIBcztmJ5ZJdk5uhEls31A==", + "dependencies": { + "@types/multer": "^1.4.7", + "ajv": "^6.12.6", + "content-type": "^1.0.4", + "json-schema-ref-parser": "^9.0.9", + "lodash.clonedeep": "^4.5.0", + "lodash.get": "^4.4.2", + "lodash.uniq": "^4.5.0", + "lodash.zipobject": "^4.1.3", + "media-typer": "^1.1.0", + "multer": "^1.4.5-lts.1", + "ono": "^7.1.3", + "path-to-regexp": "^6.2.0" + } + }, + "node_modules/express-openapi-validator/node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "node_modules/express/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-ref-parser": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", + "integrity": "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "9.0.9" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/lodash.zipobject": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz", + "integrity": "sha512-A9SzX4hMKWS25MyalwcOnNoplyHbkNVsjidhTp8ru0Sj23wY9GWBKS8gAIGDSAqeWjIjvE4KBEl24XXAs+v4wQ==" + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ==", + "dependencies": { + "@jsdevtools/ono": "7.1.3" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + } + }, + "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", + "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", + "requires": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "requires": { + "@types/express": "*" + } + }, + "@types/node": { + "version": "18.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.5.tgz", + "integrity": "sha512-NcKK6Ts+9LqdHJaW6HQmgr7dT/i3GOHG+pt6BiWv++5SnjtRd4NXeiuN2kA153SjhXPR/AhHIPHPbrsbpUVOww==" + }, + "@types/parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha512-sAfjGAYgJ/MZsk95f3ByThfJgasZk1hWJROghBwfKnLLNANEAG/WHckAcT6HNqx2sHwVlci7OAX7k1KYpOcgMw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "express-openapi-validator": { + "version": "4.13.8", + "resolved": "https://registry.npmjs.org/express-openapi-validator/-/express-openapi-validator-4.13.8.tgz", + "integrity": "sha512-89/sdkq+BKBuIyykaMl/vR9grFc3WFUPTjFo0THHbu+5g+q8rA7fKeoMfz+h84yOQIBcztmJ5ZJdk5uhEls31A==", + "requires": { + "@types/multer": "^1.4.7", + "ajv": "^6.12.6", + "content-type": "^1.0.4", + "json-schema-ref-parser": "^9.0.9", + "lodash.clonedeep": "^4.5.0", + "lodash.get": "^4.4.2", + "lodash.uniq": "^4.5.0", + "lodash.zipobject": "^4.1.3", + "media-typer": "^1.1.0", + "multer": "^1.4.5-lts.1", + "ono": "^7.1.3", + "path-to-regexp": "^6.2.0" + }, + "dependencies": { + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-ref-parser": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", + "integrity": "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==", + "requires": { + "@apidevtools/json-schema-ref-parser": "9.0.9" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "lodash.zipobject": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz", + "integrity": "sha512-A9SzX4hMKWS25MyalwcOnNoplyHbkNVsjidhTp8ru0Sj23wY9GWBKS8gAIGDSAqeWjIjvE4KBEl24XXAs+v4wQ==" + }, + "media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ==", + "requires": { + "@jsdevtools/ono": "7.1.3" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "dependencies": { + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + } + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } +} diff --git a/server/oas3-tools/package.json b/server/oas3-tools/package.json new file mode 100644 index 00000000..46724354 --- /dev/null +++ b/server/oas3-tools/package.json @@ -0,0 +1,35 @@ +{ + "name": "openbackhaul-oas3-tools", + "version": "2.3.1", + "description": "Swagger-UI and API Rest Routing for Open API v3.", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "rm -rf dist/ && tsc && cp -R src/middleware/swagger-ui dist/middleware/swagger-ui" + }, + "license": "MIT", + "files": [ + "dist" + ], + "dependencies": { + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "debug": "^4.3.4", + "express": "^4.18.1", + "express-openapi-validator": "^4.13.8", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "morgan": "^1.10.0", + "parseurl": "^1.3.3", + "serve-static": "^1.15.0" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/express": "^4.17.13", + "@types/js-yaml": "^4.0.5", + "@types/lodash": "^4.14.182", + "@types/parseurl": "^1.3.1", + "@types/serve-static": "^1.15.0", + "typescript": "^4.7.4" + } +} \ No newline at end of file diff --git a/server/oas3-tools/src/index.ts b/server/oas3-tools/src/index.ts new file mode 100644 index 00000000..3826f286 --- /dev/null +++ b/server/oas3-tools/src/index.ts @@ -0,0 +1,7 @@ +'use strict'; +import { ExpressAppConfig } from "./middleware/express.app.config"; +import { Oas3AppOptions } from "./middleware/oas3.options"; + +export function expressAppConfig(definitionPath: string, appOptions: Oas3AppOptions): ExpressAppConfig { + return new ExpressAppConfig(definitionPath, appOptions); +} diff --git a/server/oas3-tools/src/middleware/express.app.config.ts b/server/oas3-tools/src/middleware/express.app.config.ts new file mode 100644 index 00000000..3716e373 --- /dev/null +++ b/server/oas3-tools/src/middleware/express.app.config.ts @@ -0,0 +1,95 @@ +'use strict'; + +import * as express from 'express'; +import cookieParser = require('cookie-parser'); +import cors = require('cors'); +import { SwaggerUI } from './swagger.ui'; +import { SwaggerRouter } from './swagger.router'; +import { SwaggerParameters } from './swagger.parameters'; +import * as logger from 'morgan'; +import * as fs from 'fs'; +import * as jsyaml from 'js-yaml'; +import * as OpenApiValidator from 'express-openapi-validator'; +import { Oas3AppOptions } from './oas3.options'; + +export class ExpressAppConfig { + private app: express.Application; + private routingOptions; + private definitionPath; + private openApiValidatorOptions; + + constructor(definitionPath: string, appOptions: Oas3AppOptions) { + this.definitionPath = definitionPath; + this.routingOptions = appOptions.routing; + this.setOpenApiValidatorOptions(definitionPath, appOptions); + + // Create new express app only if not passed by options + this.app = appOptions.app || express(); + + this.app.use(cors(appOptions.cors)); + + const spec = fs.readFileSync(definitionPath, 'utf8'); + const swaggerDoc = jsyaml.load(spec); + + this.app.use(express.urlencoded({ limit: '50mb', extended: true })); + this.app.use(express.text({ limit: '50mb' })); + this.app.use(express.json({ limit: '50mb' })); + this.app.use(express.raw({ limit: '50mb', type: 'application/pdf' })); + + this.app.use(this.configureLogger(appOptions.logging)); + this.app.use(cookieParser()); + + const swaggerUi = new SwaggerUI(swaggerDoc, appOptions.swaggerUI); + this.app.use(swaggerUi.serveStaticContent()); + + this.app.use(OpenApiValidator.middleware(this.openApiValidatorOptions)); + this.app.use(new SwaggerParameters().checkParameters()); + this.app.use(new SwaggerRouter().initialize(this.routingOptions)); + + this.app.use(this.errorHandler); + } + + private setOpenApiValidatorOptions(definitionPath: string, appOptions: Oas3AppOptions) { + //If no options or no openApiValidator Options given, create empty options with api definition path + if (!appOptions || !appOptions.openApiValidator) { + this.openApiValidatorOptions = { apiSpec: definitionPath }; + return; + } + + // use the given options + this.openApiValidatorOptions = appOptions.openApiValidator; + + // Override apiSpec with definition Path to keep the prior behavior + this.openApiValidatorOptions.apiSpec = definitionPath; + } + + public configureLogger(loggerOptions) { + let format = 'dev'; + let options:{} = {}; + + if (loggerOptions != undefined) { + if(loggerOptions.format != undefined + && typeof loggerOptions.format === 'string'){ + format = loggerOptions.format; + } + + if(loggerOptions.errorLimit != undefined + && (typeof loggerOptions.errorLimit === 'string' || typeof loggerOptions.errorLimit === 'number')){ + options['skip'] = function (req, res) { return res.statusCode < parseInt(loggerOptions.errorLimit); }; + } + } + + return logger(format, options); + } + + private errorHandler(error, request, response, next) { + response.status(error.status || 500).json({ + message: error.message, + errors: error.errors, + }); + } + + public getApp(): express.Application { + return this.app; + } +} diff --git a/server/oas3-tools/src/middleware/helpers.ts b/server/oas3-tools/src/middleware/helpers.ts new file mode 100644 index 00000000..1517d39b --- /dev/null +++ b/server/oas3-tools/src/middleware/helpers.ts @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 Apigee Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +'use strict'; + +import { each, capitalize, split } from 'lodash'; + +export function debugError(err, debug) { + var reason = err.message.replace(/^.*validation failed: /, ''); + + reason = reason.charAt(0).toUpperCase() + reason.substring(1); + + debug(' Reason: %s', reason); + + if (err.failedValidation === true) { + if (err.results) { + debug(' Errors:'); + + each(err.results.errors, function (error, index: number) { + debug(' %d:', index); + debug(' code: %s', error.code); + debug(' message: %s', error.message); + debug(' path: %s', JSON.stringify(error.path)); + }); + } + } + + if (err.stack) { + debug(' Stack:'); + + each(err.stack.split('\n'), function (line, index: number) { + // Skip the first line since it's in the reasonx + if (index > 0) { + debug(' %s', line); + } + }); + } +}; + +export function removeDashElementToCamelCase(str) { + const pieces = split(str, '-'); + + if (pieces.length <= 1) { + return str; + } + let result = pieces[0]; + for (let index = 1; index < pieces.length; index++) { + result += capitalize(pieces[index]); + } + return result; +} diff --git a/server/oas3-tools/src/middleware/logging.options.ts b/server/oas3-tools/src/middleware/logging.options.ts new file mode 100644 index 00000000..7abaaa01 --- /dev/null +++ b/server/oas3-tools/src/middleware/logging.options.ts @@ -0,0 +1,10 @@ +export class LoggingOptions { + public format: string; + public errorLimit: string | number; + + constructor(format: string, errorLimit:string | number) + { + this.format = format; + this.errorLimit = errorLimit; + } +} \ No newline at end of file diff --git a/server/oas3-tools/src/middleware/oas3.options.ts b/server/oas3-tools/src/middleware/oas3.options.ts new file mode 100644 index 00000000..04face4f --- /dev/null +++ b/server/oas3-tools/src/middleware/oas3.options.ts @@ -0,0 +1,25 @@ +import { OpenApiValidatorOpts } from 'express-openapi-validator/dist/framework/types'; +import { LoggingOptions } from './logging.options' +import { SwaggerUiOptions } from './swagger.ui.options'; +import * as express from 'express'; + +export class Oas3AppOptions { + public routing: any; + public openApiValidator: OpenApiValidatorOpts; + public logging: LoggingOptions; + public swaggerUI: SwaggerUiOptions; + public app: express.Application; + public cors: any; + + constructor(routingOpts: any, openApiValidatorOpts: OpenApiValidatorOpts, logging: LoggingOptions, swaggerUI: SwaggerUiOptions, app: express.Application, cors: any) { + + this.routing = routingOpts; + this.openApiValidator = openApiValidatorOpts; + this.swaggerUI = swaggerUI; + if (!logging) + logging = new LoggingOptions(null, null); + this.logging = logging; + this.app = app; + this.cors = cors; + } +} \ No newline at end of file diff --git a/server/oas3-tools/src/middleware/swagger-ui/favicon-16x16.png b/server/oas3-tools/src/middleware/swagger-ui/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..8b194e617af1c135e6b37939591d24ac3a5efa18 GIT binary patch literal 665 zcmV;K0%rY*P)}JKSduyL>)s!A4EhTMMEM%Q;aL6%l#xiZiF>S;#Y{N2Zz%pvTGHJduXuC6Lx-)0EGfRy*N{Tv4i8@4oJ41gw zKzThrcRe|7J~(YYIBq{SYCkn-KQm=N8$CrEK1CcqMI1dv9z#VRL_{D)L|`QmF8}}l zJ9JV`Q}p!p_4f7m_U`WQ@apR4;o;!mnU<7}iG_qr zF(e)x9~BG-3IzcG2M4an0002kNkl41`ZiN1i62V%{PM@Ry|IS_+Yc7{bb`MM~xm(7p4|kMHP&!VGuDW4kFixat zXw43VmgwEvB$hXt_u=vZ>+v4i7E}n~eG6;n4Z=zF1n?T*yg<;W6kOfxpC6nao>VR% z?fpr=asSJ&`L*wu^rLJ5Peq*PB0;alL#XazZCBxJLd&giTfw@!hW167F^`7kobi;( ze<<>qNlP|xy7S1zl@lZNIBR7#o9ybJsptO#%}P0hz~sBp00000NkvXXu0mjfUsDF? literal 0 HcmV?d00001 diff --git a/server/oas3-tools/src/middleware/swagger-ui/favicon-32x32.png b/server/oas3-tools/src/middleware/swagger-ui/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..249737fe44558e679f0b67134e274461d988fa98 GIT binary patch literal 628 zcmV-)0*n2LP)Ma*GM0}OV<074bNCP7P7GVd{iMr*I6y~TMLss@FjvgL~HxU z%Vvj33AwpD(Z4*$Mfx=HaU16axM zt2xG_rloN<$iy9j9I5 + + + + + Swagger UI + + + + + + + +
+ + + + + + + + diff --git a/server/oas3-tools/src/middleware/swagger-ui/oauth2-redirect.html b/server/oas3-tools/src/middleware/swagger-ui/oauth2-redirect.html new file mode 100644 index 00000000..fb68399d --- /dev/null +++ b/server/oas3-tools/src/middleware/swagger-ui/oauth2-redirect.html @@ -0,0 +1,67 @@ + + + + + + diff --git a/server/oas3-tools/src/middleware/swagger-ui/swagger-ui-bundle.js b/server/oas3-tools/src/middleware/swagger-ui/swagger-ui-bundle.js new file mode 100644 index 00000000..8df29203 --- /dev/null +++ b/server/oas3-tools/src/middleware/swagger-ui/swagger-ui-bundle.js @@ -0,0 +1,100 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIBundle=t():e.SwaggerUIBundle=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist",n(n.s=449)}([function(e,t,n){"use strict";e.exports=n(78)},function(e,t,n){e.exports=n(855)()},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";t.__esModule=!0;var r,o=n(265),a=(r=o)&&r.__esModule?r:{default:r};t.default=function(){function e(e,t){for(var n=0;n>>0;if(""+n!==t||4294967295===n)return NaN;t=n}return t<0?C(e)+t:t}function A(){return!0}function O(e,t,n){return(0===e||void 0!==n&&e<=-n)&&(void 0===t||void 0!==n&&t>=n)}function P(e,t){return T(e,t,0)}function M(e,t){return T(e,t,t)}function T(e,t,n){return void 0===e?n:e<0?Math.max(0,t+e):void 0===t?e:Math.min(t,e)}var I=0,j=1,N=2,R="function"==typeof Symbol&&Symbol.iterator,D="@@iterator",L=R||D;function U(e){this.next=e}function q(e,t,n,r){var o=0===e?t:1===e?n:[t,n];return r?r.value=o:r={value:o,done:!1},r}function F(){return{value:void 0,done:!0}}function z(e){return!!H(e)}function B(e){return e&&"function"==typeof e.next}function V(e){var t=H(e);return t&&t.call(e)}function H(e){var t=e&&(R&&e[R]||e[D]);if("function"==typeof t)return t}function W(e){return e&&"number"==typeof e.length}function J(e){return null===e||void 0===e?ae():i(e)?e.toSeq():function(e){var t=se(e)||"object"==typeof e&&new te(e);if(!t)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+e);return t}(e)}function K(e){return null===e||void 0===e?ae().toKeyedSeq():i(e)?u(e)?e.toSeq():e.fromEntrySeq():ie(e)}function Y(e){return null===e||void 0===e?ae():i(e)?u(e)?e.entrySeq():e.toIndexedSeq():ue(e)}function G(e){return(null===e||void 0===e?ae():i(e)?u(e)?e.entrySeq():e:ue(e)).toSetSeq()}U.prototype.toString=function(){return"[Iterator]"},U.KEYS=I,U.VALUES=j,U.ENTRIES=N,U.prototype.inspect=U.prototype.toSource=function(){return this.toString()},U.prototype[L]=function(){return this},t(J,n),J.of=function(){return J(arguments)},J.prototype.toSeq=function(){return this},J.prototype.toString=function(){return this.__toString("Seq {","}")},J.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},J.prototype.__iterate=function(e,t){return le(this,e,t,!0)},J.prototype.__iterator=function(e,t){return ce(this,e,t,!0)},t(K,J),K.prototype.toKeyedSeq=function(){return this},t(Y,J),Y.of=function(){return Y(arguments)},Y.prototype.toIndexedSeq=function(){return this},Y.prototype.toString=function(){return this.__toString("Seq [","]")},Y.prototype.__iterate=function(e,t){return le(this,e,t,!1)},Y.prototype.__iterator=function(e,t){return ce(this,e,t,!1)},t(G,J),G.of=function(){return G(arguments)},G.prototype.toSetSeq=function(){return this},J.isSeq=oe,J.Keyed=K,J.Set=G,J.Indexed=Y;var $,Z,X,Q="@@__IMMUTABLE_SEQ__@@";function ee(e){this._array=e,this.size=e.length}function te(e){var t=Object.keys(e);this._object=e,this._keys=t,this.size=t.length}function ne(e){this._iterable=e,this.size=e.length||e.size}function re(e){this._iterator=e,this._iteratorCache=[]}function oe(e){return!(!e||!e[Q])}function ae(){return $||($=new ee([]))}function ie(e){var t=Array.isArray(e)?new ee(e).fromEntrySeq():B(e)?new re(e).fromEntrySeq():z(e)?new ne(e).fromEntrySeq():"object"==typeof e?new te(e):void 0;if(!t)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+e);return t}function ue(e){var t=se(e);if(!t)throw new TypeError("Expected Array or iterable object of values: "+e);return t}function se(e){return W(e)?new ee(e):B(e)?new re(e):z(e)?new ne(e):void 0}function le(e,t,n,r){var o=e._cache;if(o){for(var a=o.length-1,i=0;i<=a;i++){var u=o[n?a-i:i];if(!1===t(u[1],r?u[0]:i,e))return i+1}return i}return e.__iterateUncached(t,n)}function ce(e,t,n,r){var o=e._cache;if(o){var a=o.length-1,i=0;return new U(function(){var e=o[n?a-i:i];return i++>a?{value:void 0,done:!0}:q(t,r?e[0]:i-1,e[1])})}return e.__iteratorUncached(t,n)}function fe(e,t){return t?function e(t,n,r,o){if(Array.isArray(n))return t.call(o,r,Y(n).map(function(r,o){return e(t,r,o,n)}));if(de(n))return t.call(o,r,K(n).map(function(r,o){return e(t,r,o,n)}));return n}(t,e,"",{"":e}):pe(e)}function pe(e){return Array.isArray(e)?Y(e).map(pe).toList():de(e)?K(e).map(pe).toMap():e}function de(e){return e&&(e.constructor===Object||void 0===e.constructor)}function he(e,t){if(e===t||e!=e&&t!=t)return!0;if(!e||!t)return!1;if("function"==typeof e.valueOf&&"function"==typeof t.valueOf){if((e=e.valueOf())===(t=t.valueOf())||e!=e&&t!=t)return!0;if(!e||!t)return!1}return!("function"!=typeof e.equals||"function"!=typeof t.equals||!e.equals(t))}function ve(e,t){if(e===t)return!0;if(!i(t)||void 0!==e.size&&void 0!==t.size&&e.size!==t.size||void 0!==e.__hash&&void 0!==t.__hash&&e.__hash!==t.__hash||u(e)!==u(t)||s(e)!==s(t)||c(e)!==c(t))return!1;if(0===e.size&&0===t.size)return!0;var n=!l(e);if(c(e)){var r=e.entries();return t.every(function(e,t){var o=r.next().value;return o&&he(o[1],e)&&(n||he(o[0],t))})&&r.next().done}var o=!1;if(void 0===e.size)if(void 0===t.size)"function"==typeof e.cacheResult&&e.cacheResult();else{o=!0;var a=e;e=t,t=a}var f=!0,p=t.__iterate(function(t,r){if(n?!e.has(t):o?!he(t,e.get(r,y)):!he(e.get(r,y),t))return f=!1,!1});return f&&e.size===p}function me(e,t){if(!(this instanceof me))return new me(e,t);if(this._value=e,this.size=void 0===t?1/0:Math.max(0,t),0===this.size){if(Z)return Z;Z=this}}function ge(e,t){if(!e)throw new Error(t)}function ye(e,t,n){if(!(this instanceof ye))return new ye(e,t,n);if(ge(0!==n,"Cannot step a Range by 0"),e=e||0,void 0===t&&(t=1/0),n=void 0===n?1:Math.abs(n),tr?{value:void 0,done:!0}:q(e,o,n[t?r-o++:o++])})},t(te,K),te.prototype.get=function(e,t){return void 0===t||this.has(e)?this._object[e]:t},te.prototype.has=function(e){return this._object.hasOwnProperty(e)},te.prototype.__iterate=function(e,t){for(var n=this._object,r=this._keys,o=r.length-1,a=0;a<=o;a++){var i=r[t?o-a:a];if(!1===e(n[i],i,this))return a+1}return a},te.prototype.__iterator=function(e,t){var n=this._object,r=this._keys,o=r.length-1,a=0;return new U(function(){var i=r[t?o-a:a];return a++>o?{value:void 0,done:!0}:q(e,i,n[i])})},te.prototype[h]=!0,t(ne,Y),ne.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);var n=V(this._iterable),r=0;if(B(n))for(var o;!(o=n.next()).done&&!1!==e(o.value,r++,this););return r},ne.prototype.__iteratorUncached=function(e,t){if(t)return this.cacheResult().__iterator(e,t);var n=V(this._iterable);if(!B(n))return new U(F);var r=0;return new U(function(){var t=n.next();return t.done?t:q(e,r++,t.value)})},t(re,Y),re.prototype.__iterateUncached=function(e,t){if(t)return this.cacheResult().__iterate(e,t);for(var n,r=this._iterator,o=this._iteratorCache,a=0;a=r.length){var t=n.next();if(t.done)return t;r[o]=t.value}return q(e,o,r[o++])})},t(me,Y),me.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},me.prototype.get=function(e,t){return this.has(e)?this._value:t},me.prototype.includes=function(e){return he(this._value,e)},me.prototype.slice=function(e,t){var n=this.size;return O(e,t,n)?this:new me(this._value,M(t,n)-P(e,n))},me.prototype.reverse=function(){return this},me.prototype.indexOf=function(e){return he(this._value,e)?0:-1},me.prototype.lastIndexOf=function(e){return he(this._value,e)?this.size:-1},me.prototype.__iterate=function(e,t){for(var n=0;n=0&&t=0&&nn?{value:void 0,done:!0}:q(e,a++,i)})},ye.prototype.equals=function(e){return e instanceof ye?this._start===e._start&&this._end===e._end&&this._step===e._step:ve(this,e)},t(be,n),t(_e,be),t(we,be),t(Ee,be),be.Keyed=_e,be.Indexed=we,be.Set=Ee;var xe="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function(e,t){var n=65535&(e|=0),r=65535&(t|=0);return n*r+((e>>>16)*r+n*(t>>>16)<<16>>>0)|0};function Se(e){return e>>>1&1073741824|3221225471&e}function Ce(e){if(!1===e||null===e||void 0===e)return 0;if("function"==typeof e.valueOf&&(!1===(e=e.valueOf())||null===e||void 0===e))return 0;if(!0===e)return 1;var t=typeof e;if("number"===t){if(e!=e||e===1/0)return 0;var n=0|e;for(n!==e&&(n^=4294967295*e);e>4294967295;)n^=e/=4294967295;return Se(n)}if("string"===t)return e.length>je?function(e){var t=De[e];void 0===t&&(t=ke(e),Re===Ne&&(Re=0,De={}),Re++,De[e]=t);return t}(e):ke(e);if("function"==typeof e.hashCode)return e.hashCode();if("object"===t)return function(e){var t;if(Me&&void 0!==(t=Pe.get(e)))return t;if(void 0!==(t=e[Ie]))return t;if(!Oe){if(void 0!==(t=e.propertyIsEnumerable&&e.propertyIsEnumerable[Ie]))return t;if(void 0!==(t=function(e){if(e&&e.nodeType>0)switch(e.nodeType){case 1:return e.uniqueID;case 9:return e.documentElement&&e.documentElement.uniqueID}}(e)))return t}t=++Te,1073741824&Te&&(Te=0);if(Me)Pe.set(e,t);else{if(void 0!==Ae&&!1===Ae(e))throw new Error("Non-extensible objects are not allowed as keys.");if(Oe)Object.defineProperty(e,Ie,{enumerable:!1,configurable:!1,writable:!1,value:t});else if(void 0!==e.propertyIsEnumerable&&e.propertyIsEnumerable===e.constructor.prototype.propertyIsEnumerable)e.propertyIsEnumerable=function(){return this.constructor.prototype.propertyIsEnumerable.apply(this,arguments)},e.propertyIsEnumerable[Ie]=t;else{if(void 0===e.nodeType)throw new Error("Unable to set a non-enumerable property on object.");e[Ie]=t}}return t}(e);if("function"==typeof e.toString)return ke(e.toString());throw new Error("Value type "+t+" cannot be hashed.")}function ke(e){for(var t=0,n=0;n=t.length)throw new Error("Missing value for key: "+t[n]);e.set(t[n],t[n+1])}})},Ue.prototype.toString=function(){return this.__toString("Map {","}")},Ue.prototype.get=function(e,t){return this._root?this._root.get(0,void 0,e,t):t},Ue.prototype.set=function(e,t){return Qe(this,e,t)},Ue.prototype.setIn=function(e,t){return this.updateIn(e,y,function(){return t})},Ue.prototype.remove=function(e){return Qe(this,e,y)},Ue.prototype.deleteIn=function(e){return this.updateIn(e,function(){return y})},Ue.prototype.update=function(e,t,n){return 1===arguments.length?e(this):this.updateIn([e],t,n)},Ue.prototype.updateIn=function(e,t,n){n||(n=t,t=void 0);var r=function e(t,n,r,o){var a=t===y;var i=n.next();if(i.done){var u=a?r:t,s=o(u);return s===u?t:s}ge(a||t&&t.set,"invalid keyPath");var l=i.value;var c=a?y:t.get(l,y);var f=e(c,n,r,o);return f===c?t:f===y?t.remove(l):(a?Xe():t).set(l,f)}(this,nn(e),t,n);return r===y?void 0:r},Ue.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Xe()},Ue.prototype.merge=function(){return rt(this,void 0,arguments)},Ue.prototype.mergeWith=function(t){return rt(this,t,e.call(arguments,1))},Ue.prototype.mergeIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,Xe(),function(e){return"function"==typeof e.merge?e.merge.apply(e,n):n[n.length-1]})},Ue.prototype.mergeDeep=function(){return rt(this,ot,arguments)},Ue.prototype.mergeDeepWith=function(t){var n=e.call(arguments,1);return rt(this,at(t),n)},Ue.prototype.mergeDeepIn=function(t){var n=e.call(arguments,1);return this.updateIn(t,Xe(),function(e){return"function"==typeof e.mergeDeep?e.mergeDeep.apply(e,n):n[n.length-1]})},Ue.prototype.sort=function(e){return Pt(Wt(this,e))},Ue.prototype.sortBy=function(e,t){return Pt(Wt(this,t,e))},Ue.prototype.withMutations=function(e){var t=this.asMutable();return e(t),t.wasAltered()?t.__ensureOwner(this.__ownerID):this},Ue.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new x)},Ue.prototype.asImmutable=function(){return this.__ensureOwner()},Ue.prototype.wasAltered=function(){return this.__altered},Ue.prototype.__iterator=function(e,t){return new Ye(this,e,t)},Ue.prototype.__iterate=function(e,t){var n=this,r=0;return this._root&&this._root.iterate(function(t){return r++,e(t[1],t[0],n)},t),r},Ue.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?Ze(this.size,this._root,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},Ue.isMap=qe;var Fe,ze="@@__IMMUTABLE_MAP__@@",Be=Ue.prototype;function Ve(e,t){this.ownerID=e,this.entries=t}function He(e,t,n){this.ownerID=e,this.bitmap=t,this.nodes=n}function We(e,t,n){this.ownerID=e,this.count=t,this.nodes=n}function Je(e,t,n){this.ownerID=e,this.keyHash=t,this.entries=n}function Ke(e,t,n){this.ownerID=e,this.keyHash=t,this.entry=n}function Ye(e,t,n){this._type=t,this._reverse=n,this._stack=e._root&&$e(e._root)}function Ge(e,t){return q(e,t[0],t[1])}function $e(e,t){return{node:e,index:0,__prev:t}}function Ze(e,t,n,r){var o=Object.create(Be);return o.size=e,o._root=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function Xe(){return Fe||(Fe=Ze(0))}function Qe(e,t,n){var r,o;if(e._root){var a=w(b),i=w(_);if(r=et(e._root,e.__ownerID,0,void 0,t,n,a,i),!i.value)return e;o=e.size+(a.value?n===y?-1:1:0)}else{if(n===y)return e;o=1,r=new Ve(e.__ownerID,[[t,n]])}return e.__ownerID?(e.size=o,e._root=r,e.__hash=void 0,e.__altered=!0,e):r?Ze(o,r):Xe()}function et(e,t,n,r,o,a,i,u){return e?e.update(t,n,r,o,a,i,u):a===y?e:(E(u),E(i),new Ke(t,r,[o,a]))}function tt(e){return e.constructor===Ke||e.constructor===Je}function nt(e,t,n,r,o){if(e.keyHash===r)return new Je(t,r,[e.entry,o]);var a,i=(0===n?e.keyHash:e.keyHash>>>n)&g,u=(0===n?r:r>>>n)&g;return new He(t,1<>1&1431655765))+(e>>2&858993459))+(e>>4)&252645135,e+=e>>8,127&(e+=e>>16)}function st(e,t,n,r){var o=r?e:S(e);return o[t]=n,o}Be[ze]=!0,Be.delete=Be.remove,Be.removeIn=Be.deleteIn,Ve.prototype.get=function(e,t,n,r){for(var o=this.entries,a=0,i=o.length;a=lt)return function(e,t,n,r){e||(e=new x);for(var o=new Ke(e,Ce(n),[n,r]),a=0;a>>e)&g),a=this.bitmap;return 0==(a&o)?r:this.nodes[ut(a&o-1)].get(e+v,t,n,r)},He.prototype.update=function(e,t,n,r,o,a,i){void 0===n&&(n=Ce(r));var u=(0===t?n:n>>>t)&g,s=1<=ct)return function(e,t,n,r,o){for(var a=0,i=new Array(m),u=0;0!==n;u++,n>>>=1)i[u]=1&n?t[a++]:void 0;return i[r]=o,new We(e,a+1,i)}(e,p,l,u,h);if(c&&!h&&2===p.length&&tt(p[1^f]))return p[1^f];if(c&&h&&1===p.length&&tt(h))return h;var b=e&&e===this.ownerID,_=c?h?l:l^s:l|s,w=c?h?st(p,f,h,b):function(e,t,n){var r=e.length-1;if(n&&t===r)return e.pop(),e;for(var o=new Array(r),a=0,i=0;i>>e)&g,a=this.nodes[o];return a?a.get(e+v,t,n,r):r},We.prototype.update=function(e,t,n,r,o,a,i){void 0===n&&(n=Ce(r));var u=(0===t?n:n>>>t)&g,s=o===y,l=this.nodes,c=l[u];if(s&&!c)return this;var f=et(c,e,t+v,n,r,o,a,i);if(f===c)return this;var p=this.count;if(c){if(!f&&--p0&&r=0&&e=e.size||t<0)return e.withMutations(function(e){t<0?kt(e,t).set(0,n):kt(e,0,t+1).set(t,n)});t+=e._origin;var r=e._tail,o=e._root,a=w(_);t>=Ot(e._capacity)?r=xt(r,e.__ownerID,0,t,n,a):o=xt(o,e.__ownerID,e._level,t,n,a);if(!a.value)return e;if(e.__ownerID)return e._root=o,e._tail=r,e.__hash=void 0,e.__altered=!0,e;return wt(e._origin,e._capacity,e._level,o,r)}(this,e,t)},pt.prototype.remove=function(e){return this.has(e)?0===e?this.shift():e===this.size-1?this.pop():this.splice(e,1):this},pt.prototype.insert=function(e,t){return this.splice(e,0,t)},pt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=this._origin=this._capacity=0,this._level=v,this._root=this._tail=null,this.__hash=void 0,this.__altered=!0,this):Et()},pt.prototype.push=function(){var e=arguments,t=this.size;return this.withMutations(function(n){kt(n,0,t+e.length);for(var r=0;r>>t&g;if(r>=this.array.length)return new mt([],e);var o,a=0===r;if(t>0){var i=this.array[r];if((o=i&&i.removeBefore(e,t-v,n))===i&&a)return this}if(a&&!o)return this;var u=St(this,e);if(!a)for(var s=0;s>>t&g;if(o>=this.array.length)return this;if(t>0){var a=this.array[o];if((r=a&&a.removeAfter(e,t-v,n))===a&&o===this.array.length-1)return this}var i=St(this,e);return i.array.splice(o+1),r&&(i.array[o]=r),i};var gt,yt,bt={};function _t(e,t){var n=e._origin,r=e._capacity,o=Ot(r),a=e._tail;return i(e._root,e._level,0);function i(e,u,s){return 0===u?function(e,i){var u=i===o?a&&a.array:e&&e.array,s=i>n?0:n-i,l=r-i;l>m&&(l=m);return function(){if(s===l)return bt;var e=t?--l:s++;return u&&u[e]}}(e,s):function(e,o,a){var u,s=e&&e.array,l=a>n?0:n-a>>o,c=1+(r-a>>o);c>m&&(c=m);return function(){for(;;){if(u){var e=u();if(e!==bt)return e;u=null}if(l===c)return bt;var n=t?--c:l++;u=i(s&&s[n],o-v,a+(n<>>n&g,s=e&&u0){var l=e&&e.array[u],c=xt(l,t,n-v,r,o,a);return c===l?e:((i=St(e,t)).array[u]=c,i)}return s&&e.array[u]===o?e:(E(a),i=St(e,t),void 0===o&&u===i.array.length-1?i.array.pop():i.array[u]=o,i)}function St(e,t){return t&&e&&t===e.ownerID?e:new mt(e?e.array.slice():[],t)}function Ct(e,t){if(t>=Ot(e._capacity))return e._tail;if(t<1<0;)n=n.array[t>>>r&g],r-=v;return n}}function kt(e,t,n){void 0!==t&&(t|=0),void 0!==n&&(n|=0);var r=e.__ownerID||new x,o=e._origin,a=e._capacity,i=o+t,u=void 0===n?a:n<0?a+n:o+n;if(i===o&&u===a)return e;if(i>=u)return e.clear();for(var s=e._level,l=e._root,c=0;i+c<0;)l=new mt(l&&l.array.length?[void 0,l]:[],r),c+=1<<(s+=v);c&&(i+=c,o+=c,u+=c,a+=c);for(var f=Ot(a),p=Ot(u);p>=1<f?new mt([],r):d;if(d&&p>f&&iv;y-=v){var b=f>>>y&g;m=m.array[b]=St(m.array[b],r)}m.array[f>>>v&g]=d}if(u=p)i-=p,u-=p,s=v,l=null,h=h&&h.removeBefore(r,0,i);else if(i>o||p>>s&g;if(_!==p>>>s&g)break;_&&(c+=(1<o&&(l=l.removeBefore(r,s,i-c)),l&&pa&&(a=l.size),i(s)||(l=l.map(function(e){return fe(e)})),r.push(l)}return a>e.size&&(e=e.setSize(a)),it(e,t,r)}function Ot(e){return e>>v<=m&&i.size>=2*a.size?(r=(o=i.filter(function(e,t){return void 0!==e&&u!==t})).toKeyedSeq().map(function(e){return e[0]}).flip().toMap(),e.__ownerID&&(r.__ownerID=o.__ownerID=e.__ownerID)):(r=a.remove(t),o=u===i.size-1?i.pop():i.set(u,void 0))}else if(s){if(n===i.get(u)[1])return e;r=a,o=i.set(u,[t,n])}else r=a.set(t,i.size),o=i.set(i.size,[t,n]);return e.__ownerID?(e.size=r.size,e._map=r,e._list=o,e.__hash=void 0,e):Tt(r,o)}function Nt(e,t){this._iter=e,this._useKeys=t,this.size=e.size}function Rt(e){this._iter=e,this.size=e.size}function Dt(e){this._iter=e,this.size=e.size}function Lt(e){this._iter=e,this.size=e.size}function Ut(e){var t=Qt(e);return t._iter=e,t.size=e.size,t.flip=function(){return e},t.reverse=function(){var t=e.reverse.apply(this);return t.flip=function(){return e.reverse()},t},t.has=function(t){return e.includes(t)},t.includes=function(t){return e.has(t)},t.cacheResult=en,t.__iterateUncached=function(t,n){var r=this;return e.__iterate(function(e,n){return!1!==t(n,e,r)},n)},t.__iteratorUncached=function(t,n){if(t===N){var r=e.__iterator(t,n);return new U(function(){var e=r.next();if(!e.done){var t=e.value[0];e.value[0]=e.value[1],e.value[1]=t}return e})}return e.__iterator(t===j?I:j,n)},t}function qt(e,t,n){var r=Qt(e);return r.size=e.size,r.has=function(t){return e.has(t)},r.get=function(r,o){var a=e.get(r,y);return a===y?o:t.call(n,a,r,e)},r.__iterateUncached=function(r,o){var a=this;return e.__iterate(function(e,o,i){return!1!==r(t.call(n,e,o,i),o,a)},o)},r.__iteratorUncached=function(r,o){var a=e.__iterator(N,o);return new U(function(){var o=a.next();if(o.done)return o;var i=o.value,u=i[0];return q(r,u,t.call(n,i[1],u,e),o)})},r}function Ft(e,t){var n=Qt(e);return n._iter=e,n.size=e.size,n.reverse=function(){return e},e.flip&&(n.flip=function(){var t=Ut(e);return t.reverse=function(){return e.flip()},t}),n.get=function(n,r){return e.get(t?n:-1-n,r)},n.has=function(n){return e.has(t?n:-1-n)},n.includes=function(t){return e.includes(t)},n.cacheResult=en,n.__iterate=function(t,n){var r=this;return e.__iterate(function(e,n){return t(e,n,r)},!n)},n.__iterator=function(t,n){return e.__iterator(t,!n)},n}function zt(e,t,n,r){var o=Qt(e);return r&&(o.has=function(r){var o=e.get(r,y);return o!==y&&!!t.call(n,o,r,e)},o.get=function(r,o){var a=e.get(r,y);return a!==y&&t.call(n,a,r,e)?a:o}),o.__iterateUncached=function(o,a){var i=this,u=0;return e.__iterate(function(e,a,s){if(t.call(n,e,a,s))return u++,o(e,r?a:u-1,i)},a),u},o.__iteratorUncached=function(o,a){var i=e.__iterator(N,a),u=0;return new U(function(){for(;;){var a=i.next();if(a.done)return a;var s=a.value,l=s[0],c=s[1];if(t.call(n,c,l,e))return q(o,r?l:u++,c,a)}})},o}function Bt(e,t,n,r){var o=e.size;if(void 0!==t&&(t|=0),void 0!==n&&(n===1/0?n=o:n|=0),O(t,n,o))return e;var a=P(t,o),i=M(n,o);if(a!=a||i!=i)return Bt(e.toSeq().cacheResult(),t,n,r);var u,s=i-a;s==s&&(u=s<0?0:s);var l=Qt(e);return l.size=0===u?u:e.size&&u||void 0,!r&&oe(e)&&u>=0&&(l.get=function(t,n){return(t=k(this,t))>=0&&tu)return{value:void 0,done:!0};var e=o.next();return r||t===j?e:q(t,s-1,t===I?void 0:e.value[1],e)})},l}function Vt(e,t,n,r){var o=Qt(e);return o.__iterateUncached=function(o,a){var i=this;if(a)return this.cacheResult().__iterate(o,a);var u=!0,s=0;return e.__iterate(function(e,a,l){if(!u||!(u=t.call(n,e,a,l)))return s++,o(e,r?a:s-1,i)}),s},o.__iteratorUncached=function(o,a){var i=this;if(a)return this.cacheResult().__iterator(o,a);var u=e.__iterator(N,a),s=!0,l=0;return new U(function(){var e,a,c;do{if((e=u.next()).done)return r||o===j?e:q(o,l++,o===I?void 0:e.value[1],e);var f=e.value;a=f[0],c=f[1],s&&(s=t.call(n,c,a,i))}while(s);return o===N?e:q(o,a,c,e)})},o}function Ht(e,t,n){var r=Qt(e);return r.__iterateUncached=function(r,o){var a=0,u=!1;return function e(s,l){var c=this;s.__iterate(function(o,s){return(!t||l0}function Yt(e,t,r){var o=Qt(e);return o.size=new ee(r).map(function(e){return e.size}).min(),o.__iterate=function(e,t){for(var n,r=this.__iterator(j,t),o=0;!(n=r.next()).done&&!1!==e(n.value,o++,this););return o},o.__iteratorUncached=function(e,o){var a=r.map(function(e){return e=n(e),V(o?e.reverse():e)}),i=0,u=!1;return new U(function(){var n;return u||(n=a.map(function(e){return e.next()}),u=n.some(function(e){return e.done})),u?{value:void 0,done:!0}:q(e,i++,t.apply(null,n.map(function(e){return e.value})))})},o}function Gt(e,t){return oe(e)?t:e.constructor(t)}function $t(e){if(e!==Object(e))throw new TypeError("Expected [K, V] tuple: "+e)}function Zt(e){return Le(e.size),C(e)}function Xt(e){return u(e)?r:s(e)?o:a}function Qt(e){return Object.create((u(e)?K:s(e)?Y:G).prototype)}function en(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):J.prototype.cacheResult.call(this)}function tn(e,t){return e>t?1:e=0;n--)t={value:arguments[n],next:t};return this.__ownerID?(this.size=e,this._head=t,this.__hash=void 0,this.__altered=!0,this):An(e,t)},En.prototype.pushAll=function(e){if(0===(e=o(e)).size)return this;Le(e.size);var t=this.size,n=this._head;return e.reverse().forEach(function(e){t++,n={value:e,next:n}}),this.__ownerID?(this.size=t,this._head=n,this.__hash=void 0,this.__altered=!0,this):An(t,n)},En.prototype.pop=function(){return this.slice(1)},En.prototype.unshift=function(){return this.push.apply(this,arguments)},En.prototype.unshiftAll=function(e){return this.pushAll(e)},En.prototype.shift=function(){return this.pop.apply(this,arguments)},En.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):On()},En.prototype.slice=function(e,t){if(O(e,t,this.size))return this;var n=P(e,this.size);if(M(t,this.size)!==this.size)return we.prototype.slice.call(this,e,t);for(var r=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=r,this._head=o,this.__hash=void 0,this.__altered=!0,this):An(r,o)},En.prototype.__ensureOwner=function(e){return e===this.__ownerID?this:e?An(this.size,this._head,e,this.__hash):(this.__ownerID=e,this.__altered=!1,this)},En.prototype.__iterate=function(e,t){if(t)return this.reverse().__iterate(e);for(var n=0,r=this._head;r&&!1!==e(r.value,n++,this);)r=r.next;return n},En.prototype.__iterator=function(e,t){if(t)return this.reverse().__iterator(e);var n=0,r=this._head;return new U(function(){if(r){var t=r.value;return r=r.next,q(e,n++,t)}return{value:void 0,done:!0}})},En.isStack=xn;var Sn,Cn="@@__IMMUTABLE_STACK__@@",kn=En.prototype;function An(e,t,n,r){var o=Object.create(kn);return o.size=e,o._head=t,o.__ownerID=n,o.__hash=r,o.__altered=!1,o}function On(){return Sn||(Sn=An(0))}function Pn(e,t){var n=function(n){e.prototype[n]=t[n]};return Object.keys(t).forEach(n),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(t).forEach(n),e}kn[Cn]=!0,kn.withMutations=Be.withMutations,kn.asMutable=Be.asMutable,kn.asImmutable=Be.asImmutable,kn.wasAltered=Be.wasAltered,n.Iterator=U,Pn(n,{toArray:function(){Le(this.size);var e=new Array(this.size||0);return this.valueSeq().__iterate(function(t,n){e[n]=t}),e},toIndexedSeq:function(){return new Rt(this)},toJS:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJS?e.toJS():e}).__toJS()},toJSON:function(){return this.toSeq().map(function(e){return e&&"function"==typeof e.toJSON?e.toJSON():e}).__toJS()},toKeyedSeq:function(){return new Nt(this,!0)},toMap:function(){return Ue(this.toKeyedSeq())},toObject:function(){Le(this.size);var e={};return this.__iterate(function(t,n){e[n]=t}),e},toOrderedMap:function(){return Pt(this.toKeyedSeq())},toOrderedSet:function(){return mn(u(this)?this.valueSeq():this)},toSet:function(){return sn(u(this)?this.valueSeq():this)},toSetSeq:function(){return new Dt(this)},toSeq:function(){return s(this)?this.toIndexedSeq():u(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return En(u(this)?this.valueSeq():this)},toList:function(){return pt(u(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(e,t){return 0===this.size?e+t:e+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+t},concat:function(){return Gt(this,function(e,t){var n=u(e),o=[e].concat(t).map(function(e){return i(e)?n&&(e=r(e)):e=n?ie(e):ue(Array.isArray(e)?e:[e]),e}).filter(function(e){return 0!==e.size});if(0===o.length)return e;if(1===o.length){var a=o[0];if(a===e||n&&u(a)||s(e)&&s(a))return a}var l=new ee(o);return n?l=l.toKeyedSeq():s(e)||(l=l.toSetSeq()),(l=l.flatten(!0)).size=o.reduce(function(e,t){if(void 0!==e){var n=t.size;if(void 0!==n)return e+n}},0),l}(this,e.call(arguments,0)))},includes:function(e){return this.some(function(t){return he(t,e)})},entries:function(){return this.__iterator(N)},every:function(e,t){Le(this.size);var n=!0;return this.__iterate(function(r,o,a){if(!e.call(t,r,o,a))return n=!1,!1}),n},filter:function(e,t){return Gt(this,zt(this,e,t,!0))},find:function(e,t,n){var r=this.findEntry(e,t);return r?r[1]:n},forEach:function(e,t){return Le(this.size),this.__iterate(t?e.bind(t):e)},join:function(e){Le(this.size),e=void 0!==e?""+e:",";var t="",n=!0;return this.__iterate(function(r){n?n=!1:t+=e,t+=null!==r&&void 0!==r?r.toString():""}),t},keys:function(){return this.__iterator(I)},map:function(e,t){return Gt(this,qt(this,e,t))},reduce:function(e,t,n){var r,o;return Le(this.size),arguments.length<2?o=!0:r=t,this.__iterate(function(t,a,i){o?(o=!1,r=t):r=e.call(n,r,t,a,i)}),r},reduceRight:function(e,t,n){var r=this.toKeyedSeq().reverse();return r.reduce.apply(r,arguments)},reverse:function(){return Gt(this,Ft(this,!0))},slice:function(e,t){return Gt(this,Bt(this,e,t,!0))},some:function(e,t){return!this.every(Nn(e),t)},sort:function(e){return Gt(this,Wt(this,e))},values:function(){return this.__iterator(j)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some(function(){return!0})},count:function(e,t){return C(e?this.toSeq().filter(e,t):this)},countBy:function(e,t){return function(e,t,n){var r=Ue().asMutable();return e.__iterate(function(o,a){r.update(t.call(n,o,a,e),0,function(e){return e+1})}),r.asImmutable()}(this,e,t)},equals:function(e){return ve(this,e)},entrySeq:function(){var e=this;if(e._cache)return new ee(e._cache);var t=e.toSeq().map(jn).toIndexedSeq();return t.fromEntrySeq=function(){return e.toSeq()},t},filterNot:function(e,t){return this.filter(Nn(e),t)},findEntry:function(e,t,n){var r=n;return this.__iterate(function(n,o,a){if(e.call(t,n,o,a))return r=[o,n],!1}),r},findKey:function(e,t){var n=this.findEntry(e,t);return n&&n[0]},findLast:function(e,t,n){return this.toKeyedSeq().reverse().find(e,t,n)},findLastEntry:function(e,t,n){return this.toKeyedSeq().reverse().findEntry(e,t,n)},findLastKey:function(e,t){return this.toKeyedSeq().reverse().findKey(e,t)},first:function(){return this.find(A)},flatMap:function(e,t){return Gt(this,function(e,t,n){var r=Xt(e);return e.toSeq().map(function(o,a){return r(t.call(n,o,a,e))}).flatten(!0)}(this,e,t))},flatten:function(e){return Gt(this,Ht(this,e,!0))},fromEntrySeq:function(){return new Lt(this)},get:function(e,t){return this.find(function(t,n){return he(n,e)},void 0,t)},getIn:function(e,t){for(var n,r=this,o=nn(e);!(n=o.next()).done;){var a=n.value;if((r=r&&r.get?r.get(a,y):y)===y)return t}return r},groupBy:function(e,t){return function(e,t,n){var r=u(e),o=(c(e)?Pt():Ue()).asMutable();e.__iterate(function(a,i){o.update(t.call(n,a,i,e),function(e){return(e=e||[]).push(r?[i,a]:a),e})});var a=Xt(e);return o.map(function(t){return Gt(e,a(t))})}(this,e,t)},has:function(e){return this.get(e,y)!==y},hasIn:function(e){return this.getIn(e,y)!==y},isSubset:function(e){return e="function"==typeof e.includes?e:n(e),this.every(function(t){return e.includes(t)})},isSuperset:function(e){return(e="function"==typeof e.isSubset?e:n(e)).isSubset(this)},keyOf:function(e){return this.findKey(function(t){return he(t,e)})},keySeq:function(){return this.toSeq().map(In).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(e){return this.toKeyedSeq().reverse().keyOf(e)},max:function(e){return Jt(this,e)},maxBy:function(e,t){return Jt(this,t,e)},min:function(e){return Jt(this,e?Rn(e):Un)},minBy:function(e,t){return Jt(this,t?Rn(t):Un,e)},rest:function(){return this.slice(1)},skip:function(e){return this.slice(Math.max(0,e))},skipLast:function(e){return Gt(this,this.toSeq().reverse().skip(e).reverse())},skipWhile:function(e,t){return Gt(this,Vt(this,e,t,!0))},skipUntil:function(e,t){return this.skipWhile(Nn(e),t)},sortBy:function(e,t){return Gt(this,Wt(this,t,e))},take:function(e){return this.slice(0,Math.max(0,e))},takeLast:function(e){return Gt(this,this.toSeq().reverse().take(e).reverse())},takeWhile:function(e,t){return Gt(this,function(e,t,n){var r=Qt(e);return r.__iterateUncached=function(r,o){var a=this;if(o)return this.cacheResult().__iterate(r,o);var i=0;return e.__iterate(function(e,o,u){return t.call(n,e,o,u)&&++i&&r(e,o,a)}),i},r.__iteratorUncached=function(r,o){var a=this;if(o)return this.cacheResult().__iterator(r,o);var i=e.__iterator(N,o),u=!0;return new U(function(){if(!u)return{value:void 0,done:!0};var e=i.next();if(e.done)return e;var o=e.value,s=o[0],l=o[1];return t.call(n,l,s,a)?r===N?e:q(r,s,l,e):(u=!1,{value:void 0,done:!0})})},r}(this,e,t))},takeUntil:function(e,t){return this.takeWhile(Nn(e),t)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=function(e){if(e.size===1/0)return 0;var t=c(e),n=u(e),r=t?1:0;return function(e,t){return t=xe(t,3432918353),t=xe(t<<15|t>>>-15,461845907),t=xe(t<<13|t>>>-13,5),t=xe((t=(t+3864292196|0)^e)^t>>>16,2246822507),t=Se((t=xe(t^t>>>13,3266489909))^t>>>16)}(e.__iterate(n?t?function(e,t){r=31*r+qn(Ce(e),Ce(t))|0}:function(e,t){r=r+qn(Ce(e),Ce(t))|0}:t?function(e){r=31*r+Ce(e)|0}:function(e){r=r+Ce(e)|0}),r)}(this))}});var Mn=n.prototype;Mn[f]=!0,Mn[L]=Mn.values,Mn.__toJS=Mn.toArray,Mn.__toStringMapper=Dn,Mn.inspect=Mn.toSource=function(){return this.toString()},Mn.chain=Mn.flatMap,Mn.contains=Mn.includes,Pn(r,{flip:function(){return Gt(this,Ut(this))},mapEntries:function(e,t){var n=this,r=0;return Gt(this,this.toSeq().map(function(o,a){return e.call(t,[a,o],r++,n)}).fromEntrySeq())},mapKeys:function(e,t){var n=this;return Gt(this,this.toSeq().flip().map(function(r,o){return e.call(t,r,o,n)}).flip())}});var Tn=r.prototype;function In(e,t){return t}function jn(e,t){return[t,e]}function Nn(e){return function(){return!e.apply(this,arguments)}}function Rn(e){return function(){return-e.apply(this,arguments)}}function Dn(e){return"string"==typeof e?JSON.stringify(e):String(e)}function Ln(){return S(arguments)}function Un(e,t){return et?-1:0}function qn(e,t){return e^t+2654435769+(e<<6)+(e>>2)|0}return Tn[p]=!0,Tn[L]=Mn.entries,Tn.__toJS=Mn.toObject,Tn.__toStringMapper=function(e,t){return JSON.stringify(t)+": "+Dn(e)},Pn(o,{toKeyedSeq:function(){return new Nt(this,!1)},filter:function(e,t){return Gt(this,zt(this,e,t,!1))},findIndex:function(e,t){var n=this.findEntry(e,t);return n?n[0]:-1},indexOf:function(e){var t=this.keyOf(e);return void 0===t?-1:t},lastIndexOf:function(e){var t=this.lastKeyOf(e);return void 0===t?-1:t},reverse:function(){return Gt(this,Ft(this,!1))},slice:function(e,t){return Gt(this,Bt(this,e,t,!1))},splice:function(e,t){var n=arguments.length;if(t=Math.max(0|t,0),0===n||2===n&&!t)return this;e=P(e,e<0?this.count():this.size);var r=this.slice(0,e);return Gt(this,1===n?r:r.concat(S(arguments,2),this.slice(e+t)))},findLastIndex:function(e,t){var n=this.findLastEntry(e,t);return n?n[0]:-1},first:function(){return this.get(0)},flatten:function(e){return Gt(this,Ht(this,e,!1))},get:function(e,t){return(e=k(this,e))<0||this.size===1/0||void 0!==this.size&&e>this.size?t:this.find(function(t,n){return n===e},void 0,t)},has:function(e){return(e=k(this,e))>=0&&(void 0!==this.size?this.size===1/0||e5e3)return e.textContent;return function(e){for(var n,r,o,a,i,u=e.textContent,s=0,l=u[0],c=1,f=e.innerHTML="",p=0;r=n,n=p<7&&"\\"==n?1:c;){if(c=l,l=u[++s],a=f.length>1,!c||p>8&&"\n"==c||[/\S/.test(c),1,1,!/[$\w]/.test(c),("/"==n||"\n"==n)&&a,'"'==n&&a,"'"==n&&a,u[s-4]+r+n=="--\x3e",r+n=="*/"][p])for(f&&(e.appendChild(i=t.createElement("span")).setAttribute("style",["color: #555; font-weight: bold;","","","color: #555;",""][p?p<3?2:p>6?4:p>3?3:+/^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/.test(f):0]),i.appendChild(t.createTextNode(f))),o=p&&p<7?p:o,f="",p=11;![1,/[\/{}[(\-+*=<>:;|\\.,?!&@~]/.test(c),/[\])]/.test(c),/[$\w]/.test(c),"/"==c&&o<2&&"<"!=n,'"'==c,"'"==c,c+l+u[s+1]+u[s+2]=="\x3c!--",c+l=="/*",c+l=="//","#"==c][--p];);f+=c}}(e)},t.mapToList=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"key";var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:l.default.Map();if(!l.default.Map.isMap(t)||!t.size)return l.default.List();Array.isArray(n)||(n=[n]);if(n.length<1)return t.merge(r);var i=l.default.List();var u=n[0];var s=!0;var c=!1;var f=void 0;try{for(var p,d=(0,a.default)(t.entries());!(s=(p=d.next()).done);s=!0){var h=p.value,v=(0,o.default)(h,2),m=v[0],g=v[1],y=e(g,n.slice(1),r.set(u,m));i=l.default.List.isList(y)?i.concat(y):i.push(y)}}catch(e){c=!0,f=e}finally{try{!s&&d.return&&d.return()}finally{if(c)throw f}}return i},t.extractFileNameFromContentDispositionHeader=function(e){var t=void 0;if([/filename\*=[^']+'\w*'"([^"]+)";?/i,/filename\*=[^']+'\w*'([^;]+);?/i,/filename="([^;]*);?"/i,/filename=([^;]*);?/i].some(function(n){return null!==(t=n.exec(e))}),null!==t&&t.length>1)try{return decodeURIComponent(t[1])}catch(e){console.error(e)}return null},t.pascalCase=C,t.pascalCaseFilename=function(e){return C(e.replace(/\.[^./]*$/,""))},t.sanitizeUrl=function(e){if("string"!=typeof e||""===e)return"";return(0,c.sanitizeUrl)(e)},t.getAcceptControllingResponse=function(e){if(!l.default.OrderedMap.isOrderedMap(e))return null;if(!e.size)return null;var t=e.find(function(e,t){return t.startsWith("2")&&(0,u.default)(e.get("content")||{}).length>0}),n=e.get("default")||l.default.OrderedMap(),r=(n.get("content")||l.default.OrderedMap()).keySeq().toJS().length?n:null;return t||r},t.deeplyStripKey=function e(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){return!0};if("object"!==(void 0===t?"undefined":(0,s.default)(t))||Array.isArray(t)||null===t||!n)return t;var o=(0,i.default)({},t);(0,u.default)(o).forEach(function(t){t===n&&r(o[t],t)?delete o[t]:o[t]=e(o[t],n,r)});return o},t.stringify=function(e){if("string"==typeof e)return e;e&&e.toJS&&(e=e.toJS());if("object"===(void 0===e?"undefined":(0,s.default)(e))&&null!==e)try{return(0,r.default)(e,null,2)}catch(t){return String(e)}if(null===e||void 0===e)return"";return e.toString()},t.numberToString=function(e){if("number"==typeof e)return e.toString();return e},t.paramToIdentifier=q,t.paramToValue=function(e,t){return q(e,{returnAll:!0}).map(function(e){return t[e]}).filter(function(e){return void 0!==e})[0]};var l=_(n(7)),c=n(574),f=_(n(575)),p=_(n(283)),d=_(n(287)),h=_(n(290)),v=_(n(653)),m=_(n(107)),g=n(198),y=_(n(32)),b=_(n(726));function _(e){return e&&e.__esModule?e:{default:e}}var w="default",E=t.isImmutable=function(e){return l.default.Iterable.isIterable(e)};function x(e){return Array.isArray(e)?e:[e]}function S(e){return!!e&&"object"===(void 0===e?"undefined":(0,s.default)(e))}t.memoize=d.default;function C(e){return(0,p.default)((0,f.default)(e))}t.propChecker=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:[];return(0,u.default)(e).length!==(0,u.default)(t).length||((0,v.default)(e,function(e,n){if(r.includes(n))return!1;var o=t[n];return l.default.Iterable.isIterable(e)?!l.default.is(e,o):("object"!==(void 0===e?"undefined":(0,s.default)(e))||"object"!==(void 0===o?"undefined":(0,s.default)(o)))&&e!==o})||n.some(function(n){return!(0,m.default)(e[n],t[n])}))};var k=t.validateMaximum=function(e,t){if(e>t)return"Value must be less than Maximum"},A=t.validateMinimum=function(e,t){if(et)return"Value must be less than MaxLength"},D=t.validateMinLength=function(e,t){if(e.length2&&void 0!==arguments[2]?arguments[2]:{},r=n.isOAS3,o=void 0!==r&&r,a=n.bypassRequiredCheck,i=void 0!==a&&a,u=[],c=e.get("required"),f=o?e.get("schema"):e;if(!f)return u;var p=f.get("maximum"),d=f.get("minimum"),h=f.get("type"),v=f.get("format"),m=f.get("maxLength"),g=f.get("minLength"),b=f.get("pattern");if(h&&(c||t)){var _="string"===h&&t,w="array"===h&&Array.isArray(t)&&t.length,E="array"===h&&l.default.List.isList(t)&&t.count(),x="file"===h&&t instanceof y.default.File,S="boolean"===h&&(t||!1===t),C="number"===h&&(t||0===t),U="integer"===h&&(t||0===t),q=!1;if(o&&"object"===h)if("object"===(void 0===t?"undefined":(0,s.default)(t)))q=!0;else if("string"==typeof t)try{JSON.parse(t),q=!0}catch(e){return u.push("Parameter string value must be valid JSON"),u}var F=[_,w,E,x,S,C,U,q].some(function(e){return!!e});if(c&&!F&&!i)return u.push("Required field is not provided"),u;if(b){var z=L(t,b);z&&u.push(z)}if(m||0===m){var B=R(t,m);B&&u.push(B)}if(g){var V=D(t,g);V&&u.push(V)}if(p||0===p){var H=k(t,p);H&&u.push(H)}if(d||0===d){var W=A(t,d);W&&u.push(W)}if("string"===h){var J=void 0;if(!(J="date-time"===v?j(t):"uuid"===v?N(t):I(t)))return u;u.push(J)}else if("boolean"===h){var K=T(t);if(!K)return u;u.push(K)}else if("number"===h){var Y=O(t);if(!Y)return u;u.push(Y)}else if("integer"===h){var G=P(t);if(!G)return u;u.push(G)}else if("array"===h){var $;if(!E||!t.count())return u;$=f.getIn(["items","type"]),t.forEach(function(e,t){var n=void 0;"number"===$?n=O(e):"integer"===$?n=P(e):"string"===$&&(n=I(e)),n&&u.push({index:t,error:n})})}else if("file"===h){var Z=M(t);if(!Z)return u;u.push(Z)}}return u},t.getSampleSchema=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(/xml/.test(t)){if(!e.xml||!e.xml.name){if(e.xml=e.xml||{},!e.$$ref)return e.type||e.items||e.properties||e.additionalProperties?'\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e':null;var o=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=o[1]}return(0,g.memoizedCreateXMLExample)(e,n)}var a=(0,g.memoizedSampleFromSchema)(e,n);return"object"===(void 0===a?"undefined":(0,s.default)(a))?(0,r.default)(a,null,2):a},t.parseSearch=function(){var e={},t=y.default.location.search;if(!t)return{};if(""!=t){var n=t.substr(1).split("&");for(var r in n)n.hasOwnProperty(r)&&(r=n[r].split("="),e[decodeURIComponent(r[0])]=r[1]&&decodeURIComponent(r[1])||"")}return e},t.serializeSearch=function(e){return(0,u.default)(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&")},t.btoa=function(t){return(t instanceof e?t:new e(t.toString(),"utf-8")).toString("base64")},t.sorters={operationsSorter:{alpha:function(e,t){return e.get("path").localeCompare(t.get("path"))},method:function(e,t){return e.get("method").localeCompare(t.get("method"))}},tagsSorter:{alpha:function(e,t){return e.localeCompare(t)}}},t.buildFormData=function(e){var t=[];for(var n in e){var r=e[n];void 0!==r&&""!==r&&t.push([n,"=",encodeURIComponent(r).replace(/%20/g,"+")].join(""))}return t.join("&")},t.shallowEqualKeys=function(e,t,n){return!!(0,h.default)(n,function(n){return(0,m.default)(e[n],t[n])})};var U=t.createDeepLinkPath=function(e){return"string"==typeof e||e instanceof String?e.trim().replace(/\s/g,"%20"):""};t.escapeDeepLinkPath=function(e){return(0,b.default)(U(e).replace(/%20/g,"_"))},t.getExtensions=function(e){return e.filter(function(e,t){return/^x-/.test(t)})},t.getCommonExtensions=function(e){return e.filter(function(e,t){return/^pattern|maxLength|minLength|maximum|minimum/.test(t)})};function q(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.returnAll,r=void 0!==n&&n,o=t.allowHashes,a=void 0===o||o;if(!l.default.Map.isMap(e))throw new Error("paramToIdentifier: received a non-Im.Map parameter as input");var i=e.get("name"),u=e.get("in"),s=[];return e&&e.hashCode&&u&&i&&a&&s.push(u+"."+i+".hash-"+e.hashCode()),u&&i&&s.push(u+"."+i),s.push(i),r?s:s[0]||""}}).call(t,n(54).Buffer)},function(e,t,n){"use strict";var r=n(7),o="<>",a={listOf:function(e){return l(e,"List",r.List.isList)},mapOf:function(e,t){return c(e,t,"Map",r.Map.isMap)},orderedMapOf:function(e,t){return c(e,t,"OrderedMap",r.OrderedMap.isOrderedMap)},setOf:function(e){return l(e,"Set",r.Set.isSet)},orderedSetOf:function(e){return l(e,"OrderedSet",r.OrderedSet.isOrderedSet)},stackOf:function(e){return l(e,"Stack",r.Stack.isStack)},iterableOf:function(e){return l(e,"Iterable",r.Iterable.isIterable)},recordOf:function(e){return u(function(t,n,o,a,u){for(var s=arguments.length,l=Array(s>5?s-5:0),c=5;c6?s-6:0),c=6;c5?l-5:0),f=5;f5?a-5:0),u=5;u key("+c[f]+")"].concat(i));if(d instanceof Error)return d}})).apply(void 0,a);var s})}function f(e){var t=void 0===arguments[1]?"Iterable":arguments[1],n=void 0===arguments[2]?r.Iterable.isIterable:arguments[2];return u(function(r,o,a,u,s){for(var l=arguments.length,c=Array(l>5?l-5:0),f=5;f?@[\]^_`{|}~-])/g;function i(e){return!(e>=55296&&e<=57343)&&(!(e>=64976&&e<=65007)&&(65535!=(65535&e)&&65534!=(65535&e)&&(!(e>=0&&e<=8)&&(11!==e&&(!(e>=14&&e<=31)&&(!(e>=127&&e<=159)&&!(e>1114111)))))))}function u(e){if(e>65535){var t=55296+((e-=65536)>>10),n=56320+(1023&e);return String.fromCharCode(t,n)}return String.fromCharCode(e)}var s=/&([a-z#][a-z0-9]{1,31});/gi,l=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i,c=n(421);function f(e,t){var n=0;return o(c,t)?c[t]:35===t.charCodeAt(0)&&l.test(t)&&i(n="x"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10))?u(n):e}var p=/[&<>"]/,d=/[&<>"]/g,h={"&":"&","<":"<",">":">",'"':"""};function v(e){return h[e]}t.assign=function(e){return[].slice.call(arguments,1).forEach(function(t){if(t){if("object"!=typeof t)throw new TypeError(t+"must be object");Object.keys(t).forEach(function(n){e[n]=t[n]})}}),e},t.isString=function(e){return"[object String]"===function(e){return Object.prototype.toString.call(e)}(e)},t.has=o,t.unescapeMd=function(e){return e.indexOf("\\")<0?e:e.replace(a,"$1")},t.isValidEntityCode=i,t.fromCodePoint=u,t.replaceEntities=function(e){return e.indexOf("&")<0?e:e.replace(s,f)},t.escapeHtml=function(e){return p.test(e)?e.replace(d,v):e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){var r=n(33),o=n(61),a=n(59),i=n(76),u=n(124),s=function(e,t,n){var l,c,f,p,d=e&s.F,h=e&s.G,v=e&s.S,m=e&s.P,g=e&s.B,y=h?r:v?r[t]||(r[t]={}):(r[t]||{}).prototype,b=h?o:o[t]||(o[t]={}),_=b.prototype||(b.prototype={});for(l in h&&(n=t),n)f=((c=!d&&y&&void 0!==y[l])?y:n)[l],p=g&&c?u(f,r):m&&"function"==typeof f?u(Function.call,f):f,y&&i(y,l,f,e&s.U),b[l]!=f&&a(b,l,p),m&&_[l]!=f&&(_[l]=f)};r.core=o,s.F=1,s.G=2,s.S=4,s.P=8,s.B=16,s.W=32,s.U=64,s.R=128,e.exports=s},function(e,t,n){var r=n(29),o=n(102),a=n(53),i=/"/g,u=function(e,t,n,r){var o=String(a(e)),u="<"+t;return""!==n&&(u+=" "+n+'="'+String(r).replace(i,""")+'"'),u+">"+o+""};e.exports=function(e,t){var n={};n[e]=t(u),r(r.P+r.F*o(function(){var t=""[e]('"');return t!==t.toLowerCase()||t.split('"').length>3}),"String",n)}},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r,o=n(94),a=(r=o)&&r.__esModule?r:{default:r};e.exports=function(){var e={location:{},history:{},open:function(){},close:function(){},File:function(){}};if("undefined"==typeof window)return e;try{e=window;var t=!0,n=!1,r=void 0;try{for(var o,i=(0,a.default)(["File","Blob","FormData"]);!(t=(o=i.next()).done);t=!0){var u=o.value;u in window&&(e[u]=window[u])}}catch(e){n=!0,r=e}finally{try{!t&&i.return&&i.return()}finally{if(n)throw r}}}catch(e){console.error(e)}return e}()},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){"use strict";function r(e){return function(){return e}}var o=function(){};o.thatReturns=r,o.thatReturnsFalse=r(!1),o.thatReturnsTrue=r(!0),o.thatReturnsNull=r(null),o.thatReturnsThis=function(){return this},o.thatReturnsArgument=function(e){return e},e.exports=o},function(e,t,n){var r=n(36),o=n(241),a=n(165),i=Object.defineProperty;t.f=n(41)?Object.defineProperty:function(e,t,n){if(r(e),t=a(t,!0),r(n),o)try{return i(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){var r=n(28);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){var r=n(281),o="object"==typeof self&&self&&self.Object===Object&&self,a=r||o||Function("return this")();e.exports=a},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t,n){"use strict";var r=null;e.exports={debugTool:r}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=a(n(25));t.isOAS3=i,t.isSwagger2=function(e){var t=e.get("swagger");if("string"!=typeof t)return!1;return t.startsWith("2.0")},t.OAS3ComponentWrapFactory=function(e){return function(t,n){return function(a){if(n&&n.specSelectors&&n.specSelectors.specJson){var u=n.specSelectors.specJson();return i(u)?o.default.createElement(e,(0,r.default)({},a,n,{Ori:t})):o.default.createElement(t,a)}return console.warn("OAS3 wrapper: couldn't get spec"),null}}};var o=a(n(0));function a(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=e.get("openapi");return"string"==typeof t&&(t.startsWith("3.0.")&&t.length>4)}},function(e,t,n){e.exports=!n(51)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,n){e.exports={default:n(519),__esModule:!0}},function(e,t,n){e.exports={default:n(520),__esModule:!0}},function(e,t,n){"use strict";var r=n(12),o=n(13),a=n(357),i=n(70),u=n(358),s=n(91),l=n(153),c=n(8),f=[],p=0,d=a.getPooled(),h=!1,v=null;function m(){E.ReactReconcileTransaction&&v||r("123")}var g=[{initialize:function(){this.dirtyComponentsLength=f.length},close:function(){this.dirtyComponentsLength!==f.length?(f.splice(0,this.dirtyComponentsLength),w()):f.length=0}},{initialize:function(){this.callbackQueue.reset()},close:function(){this.callbackQueue.notifyAll()}}];function y(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=a.getPooled(),this.reconcileTransaction=E.ReactReconcileTransaction.getPooled(!0)}function b(e,t){return e._mountOrder-t._mountOrder}function _(e){var t=e.dirtyComponentsLength;t!==f.length&&r("124",t,f.length),f.sort(b),p++;for(var n=0;n + * @license MIT + */ +var r=n(531),o=n(532),a=n(264);function i(){return s.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function u(e,t){if(i()=i())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i().toString(16)+" bytes");return 0|e}function h(e,t){if(s.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return z(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function m(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=s.from(t,r)),s.isBuffer(t))return 0===t.length?-1:g(e,t,n,r,o);if("number"==typeof t)return t&=255,s.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):g(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function g(e,t,n,r,o){var a,i=1,u=e.length,s=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;i=2,u/=2,s/=2,n/=2}function l(e,t){return 1===i?e[t]:e.readUInt16BE(t*i)}if(o){var c=-1;for(a=n;au&&(n=u-s),a=n;a>=0;a--){for(var f=!0,p=0;po&&(r=o):r=o;var a=t.length;if(a%2!=0)throw new TypeError("Invalid hex string");r>a/2&&(r=a/2);for(var i=0;i>8,o=n%256,a.push(o),a.push(r);return a}(t,e.length-n),e,n,r)}function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function C(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:l>223?3:l>191?2:1;if(o+f<=n)switch(f){case 1:l<128&&(c=l);break;case 2:128==(192&(a=e[o+1]))&&(s=(31&l)<<6|63&a)>127&&(c=s);break;case 3:a=e[o+1],i=e[o+2],128==(192&a)&&128==(192&i)&&(s=(15&l)<<12|(63&a)<<6|63&i)>2047&&(s<55296||s>57343)&&(c=s);break;case 4:a=e[o+1],i=e[o+2],u=e[o+3],128==(192&a)&&128==(192&i)&&128==(192&u)&&(s=(15&l)<<18|(63&a)<<12|(63&i)<<6|63&u)>65535&&s<1114112&&(c=s)}null===c?(c=65533,f=1):c>65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c),o+=f}return function(e){var t=e.length;if(t<=k)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return P(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return A(this,t,n);case"latin1":case"binary":return O(this,t,n);case"base64":return S(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return M(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},s.prototype.equals=function(e){if(!s.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===s.compare(this,e)},s.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},s.prototype.compare=function(e,t,n,r,o){if(!s.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(t>>>=0,n>>>=0,r>>>=0,o>>>=0,this===e)return 0;for(var a=o-r,i=n-t,u=Math.min(a,i),l=this.slice(r,o),c=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return y(this,e,t,n);case"utf8":case"utf-8":return b(this,e,t,n);case"ascii":return _(this,e,t,n);case"latin1":case"binary":return w(this,e,t,n);case"base64":return E(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,e,t,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},s.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var k=4096;function A(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",a=t;an)throw new RangeError("Trying to access beyond buffer length")}function I(e,t,n,r,o,a){if(!s.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function j(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,a=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function N(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,a=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function R(e,t,n,r,o,a){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,a){return a||R(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function L(e,t,n,r,a){return a||R(e,0,n,8),o.write(e,t,n,r,52,8),n+8}s.prototype.slice=function(e,t){var n,r=this.length;if(e=~~e,t=void 0===t?r:~~t,e<0?(e+=r)<0&&(e=0):e>r&&(e=r),t<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},s.prototype.readUInt8=function(e,t){return t||T(e,1,this.length),this[e]},s.prototype.readUInt16LE=function(e,t){return t||T(e,2,this.length),this[e]|this[e+1]<<8},s.prototype.readUInt16BE=function(e,t){return t||T(e,2,this.length),this[e]<<8|this[e+1]},s.prototype.readUInt32LE=function(e,t){return t||T(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},s.prototype.readUInt32BE=function(e,t){return t||T(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},s.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=this[e],o=1,a=0;++a=(o*=128)&&(r-=Math.pow(2,8*t)),r},s.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=t,o=1,a=this[e+--r];r>0&&(o*=256);)a+=this[e+--r]*o;return a>=(o*=128)&&(a-=Math.pow(2,8*t)),a},s.prototype.readInt8=function(e,t){return t||T(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},s.prototype.readInt16LE=function(e,t){t||T(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},s.prototype.readInt16BE=function(e,t){t||T(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},s.prototype.readInt32LE=function(e,t){return t||T(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},s.prototype.readInt32BE=function(e,t){return t||T(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},s.prototype.readFloatLE=function(e,t){return t||T(e,4,this.length),o.read(this,e,!0,23,4)},s.prototype.readFloatBE=function(e,t){return t||T(e,4,this.length),o.read(this,e,!1,23,4)},s.prototype.readDoubleLE=function(e,t){return t||T(e,8,this.length),o.read(this,e,!0,52,8)},s.prototype.readDoubleBE=function(e,t){return t||T(e,8,this.length),o.read(this,e,!1,52,8)},s.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||I(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,a=0;for(this[t]=255&e;++a=0&&(a*=256);)this[t+o]=e/a&255;return t+n},s.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,1,255,0),s.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},s.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,65535,0),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):j(this,e,t,!0),t+2},s.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,65535,0),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):j(this,e,t,!1),t+2},s.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,4294967295,0),s.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):N(this,e,t,!0),t+4},s.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,4294967295,0),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},s.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);I(this,e,t,n,o-1,-o)}var a=0,i=1,u=0;for(this[t]=255&e;++a>0)-u&255;return t+n},s.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);I(this,e,t,n,o-1,-o)}var a=n-1,i=1,u=0;for(this[t+a]=255&e;--a>=0&&(i*=256);)e<0&&0===u&&0!==this[t+a+1]&&(u=1),this[t+a]=(e/i>>0)-u&255;return t+n},s.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,1,127,-128),s.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},s.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,32767,-32768),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):j(this,e,t,!0),t+2},s.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,32767,-32768),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):j(this,e,t,!1),t+2},s.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,2147483647,-2147483648),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):N(this,e,t,!0),t+4},s.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):N(this,e,t,!1),t+4},s.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},s.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},s.prototype.writeDoubleLE=function(e,t,n){return L(this,e,t,!0,n)},s.prototype.writeDoubleBE=function(e,t,n){return L(this,e,t,!1,n)},s.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(a<1e3||!s.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(a=t;a55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&a.push(239,191,189);continue}if(i+1===r){(t-=3)>-1&&a.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&a.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&a.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;a.push(n)}else if(n<2048){if((t-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;a.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return a}function z(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function B(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(t,n(31))},function(e,t,n){var r=n(280);e.exports=function(e){return null==e?"":r(e)}},function(e,t){var n,r,o=e.exports={};function a(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function u(e){if(n===setTimeout)return setTimeout(e,0);if((n===a||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:a}catch(e){n=a}try{r="function"==typeof clearTimeout?clearTimeout:i}catch(e){r=i}}();var s,l=[],c=!1,f=-1;function p(){c&&s&&(c=!1,s.length?l=s.concat(l):f=-1,l.length&&d())}function d(){if(!c){var e=u(p);c=!0;for(var t=l.length;t;){for(s=l,l=[];++f1)for(var n=1;n1?t-1:0),r=1;r2?n-2:0),o=2;o=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var r=n(33),o=n(59),a=n(122),i=n(173)("src"),u=Function.toString,s=(""+u).split("toString");n(61).inspectSource=function(e){return u.call(e)},(e.exports=function(e,t,n,u){var l="function"==typeof n;l&&(a(n,"name")||o(n,"name",t)),e[t]!==n&&(l&&(a(n,i)||o(n,i,e[t]?""+e[t]:s.join(String(t)))),e===r?e[t]=n:u?e[t]?e[t]=n:o(e,t,n):(delete e[t],o(e,t,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[i]||u.call(this)})},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){"use strict";var r=n(13),o=n(267),a=n(539),i=n(544),u=n(79),s=n(545),l=n(548),c=n(549),f=n(551),p=u.createElement,d=u.createFactory,h=u.cloneElement,v=r,m=function(e){return e},g={Children:{map:a.map,forEach:a.forEach,count:a.count,toArray:a.toArray,only:f},Component:o.Component,PureComponent:o.PureComponent,createElement:p,cloneElement:h,isValidElement:u.isValidElement,PropTypes:s,createClass:c,createFactory:d,createMixin:m,DOM:i,version:l,__spread:v};e.exports=g},function(e,t,n){"use strict";var r=n(13),o=n(47),a=(n(11),n(269),Object.prototype.hasOwnProperty),i=n(270),u={key:!0,ref:!0,__self:!0,__source:!0};function s(e){return void 0!==e.ref}function l(e){return void 0!==e.key}var c=function(e,t,n,r,o,a,u){var s={$$typeof:i,type:e,key:t,ref:n,props:u,_owner:a};return s};c.createElement=function(e,t,n){var r,i={},f=null,p=null;if(null!=t)for(r in s(t)&&(p=t.ref),l(t)&&(f=""+t.key),void 0===t.__self?null:t.__self,void 0===t.__source?null:t.__source,t)a.call(t,r)&&!u.hasOwnProperty(r)&&(i[r]=t[r]);var d=arguments.length-2;if(1===d)i.children=n;else if(d>1){for(var h=Array(d),v=0;v1){for(var g=Array(m),y=0;y=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}},function(e,t,n){var r=n(45),o=n(331),a=n(332),i=n(36),u=n(118),s=n(171),l={},c={};(t=e.exports=function(e,t,n,f,p){var d,h,v,m,g=p?function(){return e}:s(e),y=r(n,f,t?2:1),b=0;if("function"!=typeof g)throw TypeError(e+" is not iterable!");if(a(g)){for(d=u(e.length);d>b;b++)if((m=t?y(i(h=e[b])[0],h[1]):y(e[b]))===l||m===c)return m}else for(v=g.call(e);!(h=v.next()).done;)if((m=o(v,y,h.value,t))===l||m===c)return m}).BREAK=l,t.RETURN=c},function(e,t,n){"use strict";function r(e){return void 0===e||null===e}e.exports.isNothing=r,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:r(e)?[]:[e]},e.exports.repeat=function(e,t){var n,r="";for(n=0;n0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(119)("meta"),o=n(28),a=n(52),i=n(35).f,u=0,s=Object.isExtensible||function(){return!0},l=!n(51)(function(){return s(Object.preventExtensions({}))}),c=function(e){i(e,r,{value:{i:"O"+ ++u,w:{}}})},f=e.exports={KEY:r,NEED:!1,fastKey:function(e,t){if(!o(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!a(e,r)){if(!s(e))return"F";if(!t)return"E";c(e)}return e[r].i},getWeak:function(e,t){if(!a(e,r)){if(!s(e))return!0;if(!t)return!1;c(e)}return e[r].w},onFreeze:function(e){return l&&f.NEED&&s(e)&&!a(e,r)&&c(e),e}}},function(e,t,n){"use strict";e.exports=function(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,r=0;rdocument.F=Object<\/script>"),e.close(),s=e.F;r--;)delete s.prototype[a[r]];return s()};e.exports=Object.create||function(e,t){var n;return null!==e?(u.prototype=r(e),n=new u,u.prototype=null,n[i]=e):n=s(),void 0===t?n:o(n,t)}},function(e,t,n){var r=n(167),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t,n){var r=n(95),o=n(20)("toStringTag"),a="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:a?r(t):"Object"==(i=r(t))&&"function"==typeof t.callee?"Arguments":i}},function(e,t,n){var r=n(60),o=n(462),a=n(463),i=Object.defineProperty;t.f=n(101)?Object.defineProperty:function(e,t,n){if(r(e),t=a(t,!0),r(n),o)try{return i(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){var r=n(125);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var r=n(468),o=n(53);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";var r=n(59),o=n(76),a=n(102),i=n(53),u=n(17);e.exports=function(e,t,n){var s=u(e),l=n(i,s,""[e]),c=l[0],f=l[1];a(function(){var t={};return t[s]=function(){return 7},7!=""[e](t)})&&(o(String.prototype,e,c),r(RegExp.prototype,s,2==t?function(e,t){return f.call(e,this,t)}:function(e){return f.call(e,this)}))}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t){},function(e,t,n){"use strict";var r={};e.exports=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CLEAR_BY=t.CLEAR=t.NEW_AUTH_ERR=t.NEW_SPEC_ERR_BATCH=t.NEW_SPEC_ERR=t.NEW_THROWN_ERR_BATCH=t.NEW_THROWN_ERR=void 0,t.newThrownErr=function(e){return{type:i,payload:(0,a.default)(e)}},t.newThrownErrBatch=function(e){return{type:u,payload:e}},t.newSpecErr=function(e){return{type:s,payload:e}},t.newSpecErrBatch=function(e){return{type:l,payload:e}},t.newAuthErr=function(e){return{type:c,payload:e}},t.clear=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:f,payload:e}},t.clearBy=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!0};return{type:p,payload:e}};var r,o=n(184),a=(r=o)&&r.__esModule?r:{default:r};var i=t.NEW_THROWN_ERR="err_new_thrown_err",u=t.NEW_THROWN_ERR_BATCH="err_new_thrown_err_batch",s=t.NEW_SPEC_ERR="err_new_spec_err",l=t.NEW_SPEC_ERR_BATCH="err_new_spec_err_batch",c=t.NEW_AUTH_ERR="err_new_auth_err",f=t.CLEAR="err_clear",p=t.CLEAR_BY="err_clear_by"},function(e,t,n){var r=n(62),o=n(48),a="[object Symbol]";e.exports=function(e){return"symbol"==typeof e||o(e)&&r(e)==a}},function(e,t,n){var r=n(63)(Object,"create");e.exports=r},function(e,t,n){var r=n(603),o=n(604),a=n(605),i=n(606),u=n(607);function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e1&&void 0!==arguments[1]?arguments[1]:"";if(u.List.isList(e))return e.some(function(e){return u.Map.isMap(e)&&e.get("in")===t})},t.parametersIncludeType=M,t.contentTypeValues=function(e,t){t=t||[];var n=d(e).getIn(["paths"].concat((0,o.default)(t)),(0,u.fromJS)({})),r=e.getIn(["meta","paths"].concat((0,o.default)(t)),(0,u.fromJS)({})),a=T(e,t),i=n.get("parameters")||new u.List,s=r.get("consumes_value")?r.get("consumes_value"):M(i,"file")?"multipart/form-data":M(i,"formData")?"application/x-www-form-urlencoded":void 0;return(0,u.fromJS)({requestContentType:s,responseContentType:a})},t.currentProducesFor=T,t.producesOptionsFor=function(e,t){t=t||[];var n=d(e),a=n.getIn(["paths"].concat((0,o.default)(t)),null);if(null===a)return;var i=t,u=(0,r.default)(i,1)[0],s=a.get("produces",null),l=n.getIn(["paths",u,"produces"],null),c=n.getIn(["produces"],null);return s||l||c},t.consumesOptionsFor=function(e,t){t=t||[];var n=d(e),a=n.getIn(["paths"].concat((0,o.default)(t)),null);if(null===a)return;var i=t,u=(0,r.default)(i,1)[0],s=a.get("consumes",null),l=n.getIn(["paths",u,"consumes"],null),c=n.getIn(["consumes"],null);return s||l||c};var a=n(58),i=n(9),u=n(7);function s(e){return e&&e.__esModule?e:{default:e}}var l=["get","put","post","delete","options","head","patch","trace"],c=function(e){return e||(0,u.Map)()},f=(t.lastError=(0,a.createSelector)(c,function(e){return e.get("lastError")}),t.url=(0,a.createSelector)(c,function(e){return e.get("url")}),t.specStr=(0,a.createSelector)(c,function(e){return e.get("spec")||""}),t.specSource=(0,a.createSelector)(c,function(e){return e.get("specSource")||"not-editor"}),t.specJson=(0,a.createSelector)(c,function(e){return e.get("json",(0,u.Map)())})),p=(t.specResolved=(0,a.createSelector)(c,function(e){return e.get("resolved",(0,u.Map)())}),t.specResolvedSubtree=function(e,t){return e.getIn(["resolvedSubtrees"].concat((0,o.default)(t)),void 0)},function e(t,n){return u.Map.isMap(t)&&u.Map.isMap(n)?n.get("$$ref")?n:(0,u.OrderedMap)().mergeWith(e,t,n):n}),d=t.specJsonWithResolvedSubtrees=(0,a.createSelector)(c,function(e){return(0,u.OrderedMap)().mergeWith(p,e.get("json"),e.get("resolvedSubtrees"))}),h=t.spec=function(e){return f(e)},v=(t.isOAS3=(0,a.createSelector)(h,function(){return!1}),t.info=(0,a.createSelector)(h,function(e){return j(e&&e.get("info"))})),m=(t.externalDocs=(0,a.createSelector)(h,function(e){return j(e&&e.get("externalDocs"))}),t.version=(0,a.createSelector)(v,function(e){return e&&e.get("version")})),g=(t.semver=(0,a.createSelector)(m,function(e){return/v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e).slice(1)}),t.paths=(0,a.createSelector)(d,function(e){return e.get("paths")})),y=t.operations=(0,a.createSelector)(g,function(e){if(!e||e.size<1)return(0,u.List)();var t=(0,u.List)();return e&&e.forEach?(e.forEach(function(e,n){if(!e||!e.forEach)return{};e.forEach(function(e,r){l.indexOf(r)<0||(t=t.push((0,u.fromJS)({path:n,method:r,operation:e,id:r+"-"+n})))})}),t):(0,u.List)()}),b=t.consumes=(0,a.createSelector)(h,function(e){return(0,u.Set)(e.get("consumes"))}),_=t.produces=(0,a.createSelector)(h,function(e){return(0,u.Set)(e.get("produces"))}),w=(t.security=(0,a.createSelector)(h,function(e){return e.get("security",(0,u.List)())}),t.securityDefinitions=(0,a.createSelector)(h,function(e){return e.get("securityDefinitions")}),t.findDefinition=function(e,t){var n=e.getIn(["resolvedSubtrees","definitions",t],null),r=e.getIn(["json","definitions",t],null);return n||r||null},t.definitions=(0,a.createSelector)(h,function(e){var t=e.get("definitions");return u.Map.isMap(t)?t:(0,u.Map)()}),t.basePath=(0,a.createSelector)(h,function(e){return e.get("basePath")}),t.host=(0,a.createSelector)(h,function(e){return e.get("host")}),t.schemes=(0,a.createSelector)(h,function(e){return e.get("schemes",(0,u.Map)())}),t.operationsWithRootInherited=(0,a.createSelector)(y,b,_,function(e,t,n){return e.map(function(e){return e.update("operation",function(e){if(e){if(!u.Map.isMap(e))return;return e.withMutations(function(e){return e.get("consumes")||e.update("consumes",function(e){return(0,u.Set)(e).merge(t)}),e.get("produces")||e.update("produces",function(e){return(0,u.Set)(e).merge(n)}),e})}return(0,u.Map)()})})})),E=t.tags=(0,a.createSelector)(h,function(e){var t=e.get("tags",(0,u.List)());return u.List.isList(t)?t.filter(function(e){return u.Map.isMap(e)}):(0,u.List)()}),x=t.tagDetails=function(e,t){return(E(e)||(0,u.List)()).filter(u.Map.isMap).find(function(e){return e.get("name")===t},(0,u.Map)())},S=t.operationsWithTags=(0,a.createSelector)(w,E,function(e,t){return e.reduce(function(e,t){var n=(0,u.Set)(t.getIn(["operation","tags"]));return n.count()<1?e.update("default",(0,u.List)(),function(e){return e.push(t)}):n.reduce(function(e,n){return e.update(n,(0,u.List)(),function(e){return e.push(t)})},e)},t.reduce(function(e,t){return e.set(t.get("name"),(0,u.List)())},(0,u.OrderedMap)()))}),C=(t.taggedOperations=function(e){return function(t){var n=(0,t.getConfigs)(),r=n.tagsSorter,o=n.operationsSorter;return S(e).sortBy(function(e,t){return t},function(e,t){var n="function"==typeof r?r:i.sorters.tagsSorter[r];return n?n(e,t):null}).map(function(t,n){var r="function"==typeof o?o:i.sorters.operationsSorter[o],a=r?t.sort(r):t;return(0,u.Map)({tagDetails:x(e,n),operations:a})})}},t.responses=(0,a.createSelector)(c,function(e){return e.get("responses",(0,u.Map)())})),k=t.requests=(0,a.createSelector)(c,function(e){return e.get("requests",(0,u.Map)())}),A=t.mutatedRequests=(0,a.createSelector)(c,function(e){return e.get("mutatedRequests",(0,u.Map)())}),O=(t.responseFor=function(e,t,n){return C(e).getIn([t,n],null)},t.requestFor=function(e,t,n){return k(e).getIn([t,n],null)},t.mutatedRequestFor=function(e,t,n){return A(e).getIn([t,n],null)},t.allowTryItOutFor=function(){return!0},t.parameterWithMetaByIdentity=function(e,t,n){var r=d(e).getIn(["paths"].concat((0,o.default)(t),["parameters"]),(0,u.OrderedMap)()),a=e.getIn(["meta","paths"].concat((0,o.default)(t),["parameters"]),(0,u.OrderedMap)());return r.map(function(e){var t=a.get(n.get("in")+"."+n.get("name")),r=a.get(n.get("in")+"."+n.get("name")+".hash-"+n.hashCode());return(0,u.OrderedMap)().merge(e,t,r)}).find(function(e){return e.get("in")===n.get("in")&&e.get("name")===n.get("name")},(0,u.OrderedMap)())}),P=(t.parameterInclusionSettingFor=function(e,t,n,r){var a=r+"."+n;return e.getIn(["meta","paths"].concat((0,o.default)(t),["parameter_inclusions",a]),!1)},t.parameterWithMeta=function(e,t,n,r){var a=d(e).getIn(["paths"].concat((0,o.default)(t),["parameters"]),(0,u.OrderedMap)()).find(function(e){return e.get("in")===r&&e.get("name")===n},(0,u.OrderedMap)());return O(e,t,a)},t.operationWithMeta=function(e,t,n){var r=d(e).getIn(["paths",t,n],(0,u.OrderedMap)()),o=e.getIn(["meta","paths",t,n],(0,u.OrderedMap)()),a=r.get("parameters",(0,u.List)()).map(function(r){return O(e,[t,n],r)});return(0,u.OrderedMap)().merge(r,o).set("parameters",a)});t.hasHost=(0,a.createSelector)(h,function(e){var t=e.get("host");return"string"==typeof t&&t.length>0&&"/"!==t[0]});function M(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(u.List.isList(e))return e.some(function(e){return u.Map.isMap(e)&&e.get("type")===t})}function T(e,t){t=t||[];var n=d(e).getIn(["paths"].concat((0,o.default)(t)),null);if(null!==n){var r=e.getIn(["meta","paths"].concat((0,o.default)(t),["produces_value"]),null),a=n.getIn(["produces",0],null);return r||a||"application/json"}}var I=t.operationScheme=function(e,t,n){var r=e.get("url").match(/^([a-z][a-z0-9+\-.]*):/),o=Array.isArray(r)?r[1]:null;return e.getIn(["scheme",t,n])||e.getIn(["scheme","_defaultScheme"])||o||""};t.canExecuteScheme=function(e,t,n){return["http","https"].indexOf(I(e,t,n))>-1},t.validateBeforeExecute=function(e,t){t=t||[];var n=!0;return e.getIn(["meta","paths"].concat((0,o.default)(t),["parameters"]),(0,u.fromJS)([])).forEach(function(e){var t=e.get("errors");t&&t.count()&&(n=!1)}),n};function j(e){return u.Map.isMap(e)?e:new u.Map}},function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},function(e,t,n){var r=n(50);e.exports=function(e,t,n){for(var o in t)n&&e[o]?e[o]=t[o]:r(e,o,t[o]);return e}},function(e,t,n){"use strict";var r=n(89);e.exports=r.DEFAULT=new r({include:[n(110)],explicit:[n(759),n(760),n(761)]})},function(e,t,n){var r=n(347),o=n(107),a=Object.prototype.hasOwnProperty;e.exports=function(e,t,n){var i=e[t];a.call(e,t)&&o(i,n)&&(void 0!==n||t in e)||r(e,t,n)}},function(e,t,n){"use strict";var r=n(12),o=(n(8),{}),a={reinitializeTransaction:function(){this.transactionWrappers=this.getTransactionWrappers(),this.wrapperInitData?this.wrapperInitData.length=0:this.wrapperInitData=[],this._isInTransaction=!1},_isInTransaction:!1,getTransactionWrappers:null,isInTransaction:function(){return!!this._isInTransaction},perform:function(e,t,n,o,a,i,u,s){var l,c;this.isInTransaction()&&r("27");try{this._isInTransaction=!0,l=!0,this.initializeAll(0),c=e.call(t,n,o,a,i,u,s),l=!1}finally{try{if(l)try{this.closeAll(0)}catch(e){}else this.closeAll(0)}finally{this._isInTransaction=!1}}return c},initializeAll:function(e){for(var t=this.transactionWrappers,n=e;n]/,s=n(221)(function(e,t){if(e.namespaceURI!==a.svg||"innerHTML"in e)e.innerHTML=t;else{(r=r||document.createElement("div")).innerHTML=""+t+"";for(var n=r.firstChild;n.firstChild;)e.appendChild(n.firstChild)}});if(o.canUseDOM){var l=document.createElement("div");l.innerHTML=" ",""===l.innerHTML&&(s=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),i.test(t)||"<"===t[0]&&u.test(t)){e.innerHTML=String.fromCharCode(65279)+t;var n=e.firstChild;1===n.data.length?e.removeChild(n):n.deleteData(0,1)}else e.innerHTML=t}),l=null}e.exports=s},function(e,t,n){"use strict";var r=/["'&<>]/;e.exports=function(e){return"boolean"==typeof e||"number"==typeof e?""+e:function(e){var t,n=""+e,o=r.exec(n);if(!o)return n;var a="",i=0,u=0;for(i=o.index;i0?r:n)(e)}},function(e,t,n){var r=n(169)("keys"),o=n(119);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t,n){var r=n(22),o=r["__core-js_shared__"]||(r["__core-js_shared__"]={});e.exports=function(e){return o[e]||(o[e]={})}},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var r=n(120),o=n(20)("iterator"),a=n(72);e.exports=n(14).getIteratorMethod=function(e){if(void 0!=e)return e[o]||e["@@iterator"]||a[r(e)]}},function(e,t,n){var r=n(100),o=n(17)("toStringTag"),a="Arguments"==r(function(){return arguments}());e.exports=function(e){var t,n,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:a?r(t):"Object"==(i=r(t))&&"function"==typeof t.callee?"Arguments":i}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t,n){var r=n(77),o=n(33).document,a=r(o)&&r(o.createElement);e.exports=function(e){return a?o.createElement(e):{}}},function(e,t,n){var r=n(245)("keys"),o=n(173);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t,n){var r=n(121).f,o=n(122),a=n(17)("toStringTag");e.exports=function(e,t,n){e&&!o(e=n?e:e.prototype,a)&&r(e,a,{configurable:!0,value:t})}},function(e,t,n){"use strict";var r=n(125);e.exports.f=function(e){return new function(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=r(t),this.reject=r(n)}(e)}},function(e,t,n){var r=n(259),o=n(53);e.exports=function(e,t,n){if(r(t))throw TypeError("String#"+n+" doesn't accept regex!");return String(o(e))}},function(e,t,n){var r=n(17)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,!"/./"[e](t)}catch(e){}}return!0}},function(e,t,n){t.f=n(20)},function(e,t,n){var r=n(22),o=n(14),a=n(116),i=n(180),u=n(35).f;e.exports=function(e){var t=o.Symbol||(o.Symbol=a?{}:r.Symbol||{});"_"==e.charAt(0)||e in t||u(t,e,{value:i.f(e)})}},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,n){"use strict";(function(t){ +/*! + * @description Recursive object extending + * @author Viacheslav Lotsmanov + * @license MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Viacheslav Lotsmanov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +function n(e){return e instanceof t||e instanceof Date||e instanceof RegExp}function r(e){if(e instanceof t){var n=t.alloc?t.alloc(e.length):new t(e.length);return e.copy(n),n}if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return new RegExp(e);throw new Error("Unexpected situation")}function o(e,t){return"__proto__"===t?void 0:e[t]}var a=e.exports=function(){if(arguments.length<1||"object"!=typeof arguments[0])return!1;if(arguments.length<2)return arguments[0];var e,t,i=arguments[0];return Array.prototype.slice.call(arguments,1).forEach(function(u){"object"!=typeof u||null===u||Array.isArray(u)||Object.keys(u).forEach(function(s){return t=o(i,s),(e=o(u,s))===i?void 0:"object"!=typeof e||null===e?void(i[s]=e):Array.isArray(e)?void(i[s]=function e(t){var o=[];return t.forEach(function(t,i){"object"==typeof t&&null!==t?Array.isArray(t)?o[i]=e(t):n(t)?o[i]=r(t):o[i]=a({},t):o[i]=t}),o}(e)):n(e)?void(i[s]=r(e)):"object"!=typeof t||null===t||Array.isArray(t)?void(i[s]=a({},e)):void(i[s]=a(t,e))})}),i}}).call(t,n(54).Buffer)},function(e,t,n){"use strict";e.exports=function(e){return"object"==typeof e?function e(t,n){var r;r=Array.isArray(t)?[]:{};n.push(t);Object.keys(t).forEach(function(o){var a=t[o];"function"!=typeof a&&(a&&"object"==typeof a?-1!==n.indexOf(t[o])?r[o]="[Circular]":r[o]=e(t[o],n.slice(0)):r[o]=a)});"string"==typeof t.name&&(r.name=t.name);"string"==typeof t.message&&(r.message=t.message);"string"==typeof t.stack&&(r.stack=t.stack);return r}(e,[]):"function"==typeof e?"[Function: "+(e.name||"anonymous")+"]":e}},function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function o(e){return null===e?"null":void 0===e?"undefined":"object"===(void 0===e?"undefined":r(e))?Array.isArray(e)?"array":"object":void 0===e?"undefined":r(e)}function a(e){return"object"===o(e)?u(e):"array"===o(e)?i(e):e}function i(e){return e.map(a)}function u(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[n]=a(e[n]));return t}function s(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n={arrayBehaviour:(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).arrayBehaviour||"replace"},r=t.map(function(e){return e||{}}),a=e||{},l=0;l1?t-1:0),r=1;r-1&&e%1==0&&e<=n}},function(e,t){e.exports=function(e){return function(t){return e(t)}}},function(e,t,n){(function(e){var r=n(281),o="object"==typeof t&&t&&!t.nodeType&&t,a=o&&"object"==typeof e&&e&&!e.nodeType&&e,i=a&&a.exports===o&&r.process,u=function(){try{var e=a&&a.require&&a.require("util").types;return e||i&&i.binding&&i.binding("util")}catch(e){}}();e.exports=u}).call(t,n(138)(e))},function(e,t,n){var r=n(24),o=n(132),a=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,i=/^\w*$/;e.exports=function(e,t){if(r(e))return!1;var n=typeof e;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!o(e))||i.test(e)||!a.test(e)||null!=t&&e in Object(t)}},function(e,t){e.exports=function(e){return e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.memoizedSampleFromSchema=t.memoizedCreateXMLExample=t.sampleXmlFromSchema=t.inferSchema=t.sampleFromSchema=void 0,t.createXMLExample=p;var r=n(9),o=u(n(659)),a=u(n(672)),i=u(n(185));function u(e){return e&&e.__esModule?e:{default:e}}var s={string:function(){return"string"},string_email:function(){return"user@example.com"},"string_date-time":function(){return(new Date).toISOString()},string_date:function(){return(new Date).toISOString().substring(0,10)},string_uuid:function(){return"3fa85f64-5717-4562-b3fc-2c963f66afa6"},string_hostname:function(){return"example.com"},string_ipv4:function(){return"198.51.100.42"},string_ipv6:function(){return"2001:0db8:5b96:0000:0000:426f:8e17:642a"},number:function(){return 0},number_float:function(){return 0},integer:function(){return 0},boolean:function(e){return"boolean"!=typeof e.default||e.default}},l=function(e){var t=e=(0,r.objectify)(e),n=t.type,o=t.format,a=s[n+"_"+o]||s[n];return(0,r.isFunc)(a)?a(e):"Unknown Type: "+e.type},c=t.sampleFromSchema=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=(0,r.objectify)(t),a=o.type,i=o.example,u=o.properties,s=o.additionalProperties,c=o.items,f=n.includeReadOnly,p=n.includeWriteOnly;if(void 0!==i)return(0,r.deeplyStripKey)(i,"$$ref",function(e){return"string"==typeof e&&e.indexOf("#")>-1});if(!a)if(u)a="object";else{if(!c)return;a="array"}if("object"===a){var d=(0,r.objectify)(u),h={};for(var v in d)d[v]&&d[v].deprecated||d[v]&&d[v].readOnly&&!f||d[v]&&d[v].writeOnly&&!p||(h[v]=e(d[v],n));if(!0===s)h.additionalProp1={};else if(s)for(var m=(0,r.objectify)(s),g=e(m,n),y=1;y<4;y++)h["additionalProp"+y]=g;return h}return"array"===a?Array.isArray(c.anyOf)?c.anyOf.map(function(t){return e(t,n)}):Array.isArray(c.oneOf)?c.oneOf.map(function(t){return e(t,n)}):[e(c,n)]:t.enum?t.default?t.default:(0,r.normalizeArray)(t.enum)[0]:"file"!==a?l(t):void 0},f=(t.inferSchema=function(e){return e.schema&&(e=e.schema),e.properties&&(e.type="object"),e},t.sampleXmlFromSchema=function e(t){var n,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=(0,i.default)({},(0,r.objectify)(t)),u=a.type,s=a.properties,c=a.additionalProperties,f=a.items,p=a.example,d=o.includeReadOnly,h=o.includeWriteOnly,v=a.default,m={},g={},y=t.xml,b=y.name,_=y.prefix,w=y.namespace,E=a.enum,x=void 0;if(!u)if(s||c)u="object";else{if(!f)return;u="array"}(b=b||"notagname",n=(_?_+":":"")+b,w)&&(g[_?"xmlns:"+_:"xmlns"]=w);if("array"===u&&f){if(f.xml=f.xml||y||{},f.xml.name=f.xml.name||y.name,y.wrapped)return m[n]=[],Array.isArray(p)?p.forEach(function(t){f.example=t,m[n].push(e(f,o))}):Array.isArray(v)?v.forEach(function(t){f.default=t,m[n].push(e(f,o))}):m[n]=[e(f,o)],g&&m[n].push({_attr:g}),m;var S=[];return Array.isArray(p)?(p.forEach(function(t){f.example=t,S.push(e(f,o))}),S):Array.isArray(v)?(v.forEach(function(t){f.default=t,S.push(e(f,o))}),S):e(f,o)}if("object"===u){var C=(0,r.objectify)(s);for(var k in m[n]=[],p=p||{},C)if(C.hasOwnProperty(k)&&(!C[k].readOnly||d)&&(!C[k].writeOnly||h))if(C[k].xml=C[k].xml||{},C[k].xml.attribute){var A=Array.isArray(C[k].enum)&&C[k].enum[0],O=C[k].example,P=C[k].default;g[C[k].xml.name||k]=void 0!==O&&O||void 0!==p[k]&&p[k]||void 0!==P&&P||A||l(C[k])}else{C[k].xml.name=C[k].xml.name||k,void 0===C[k].example&&void 0!==p[k]&&(C[k].example=p[k]);var M=e(C[k]);Array.isArray(M)?m[n]=m[n].concat(M):m[n].push(M)}return!0===c?m[n].push({additionalProp:"Anything can be here"}):c&&m[n].push({additionalProp:l(c)}),g&&m[n].push({_attr:g}),m}return x=void 0!==p?p:void 0!==v?v:Array.isArray(E)?E[0]:l(t),m[n]=g?[{_attr:g},x]:x,m});function p(e,t){var n=f(e,t);if(n)return(0,o.default)(n,{declaration:!0,indent:"\t"})}t.memoizedCreateXMLExample=(0,a.default)(p),t.memoizedSampleFromSchema=(0,a.default)(c)},function(e,t,n){"use strict";var r,o="object"==typeof Reflect?Reflect:null,a=o&&"function"==typeof o.apply?o.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=o&&"function"==typeof o.ownKeys?o.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var i=Number.isNaN||function(e){return e!=e};function u(){u.init.call(this)}e.exports=u,u.EventEmitter=u,u.prototype._events=void 0,u.prototype._eventsCount=0,u.prototype._maxListeners=void 0;var s=10;function l(e){return void 0===e._maxListeners?u.defaultMaxListeners:e._maxListeners}function c(e,t,n,r){var o,a,i,u;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(a=e._events)?(a=e._events=Object.create(null),e._eventsCount=0):(void 0!==a.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),a=e._events),i=a[t]),void 0===i)i=a[t]=n,++e._eventsCount;else if("function"==typeof i?i=a[t]=r?[n,i]:[i,n]:r?i.unshift(n):i.push(n),(o=l(e))>0&&i.length>o&&!i.warned){i.warned=!0;var s=new Error("Possible EventEmitter memory leak detected. "+i.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");s.name="MaxListenersExceededWarning",s.emitter=e,s.type=t,s.count=i.length,u=s,console&&console.warn&&console.warn(u)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(i=t[0]),i instanceof Error)throw i;var u=new Error("Unhandled error."+(i?" ("+i.message+")":""));throw u.context=i,u}var s=o[e];if(void 0===s)return!1;if("function"==typeof s)a(s,this,t);else{var l=s.length,c=h(s,l);for(n=0;n=0;a--)if(n[a]===t||n[a].listener===t){i=n[a].listener,o=a;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},u.prototype.listeners=function(e){return p(this,e,!0)},u.prototype.rawListeners=function(e){return p(this,e,!1)},u.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):d.call(e,t)},u.prototype.listenerCount=d,u.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){(t=e.exports=n(308)).Stream=t,t.Readable=t,t.Writable=n(201),t.Duplex=n(65),t.Transform=n(313),t.PassThrough=n(667)},function(e,t,n){"use strict";(function(t,r,o){var a=n(144);function i(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=y;var u,s=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:a.nextTick;y.WritableState=g;var l=n(108);l.inherits=n(84);var c={deprecate:n(666)},f=n(309),p=n(145).Buffer,d=o.Uint8Array||function(){};var h,v=n(310);function m(){}function g(e,t){u=u||n(65),e=e||{};var r=t instanceof u;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,l=e.writableHighWaterMark,c=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(l||0===l)?l:c,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(a.nextTick(o,r),a.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),S(e,t))}(e,n,r,t,o);else{var i=E(n);i||n.corked||n.bufferProcessing||!n.bufferedRequest||w(e,n),r?s(_,e,n,i,o):_(e,n,i,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new i(this)}function y(e){if(u=u||n(65),!(h.call(y,this)||this instanceof u))return new y(e);this._writableState=new g(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function b(e,t,n,r,o,a,i){t.writelen=r,t.writecb=i,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,a,t.onwrite),t.sync=!1}function _(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),S(e,t)}function w(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),a=t.corkedRequestsFree;a.entry=n;for(var u=0,s=!0;n;)o[u]=n,n.isBuf||(s=!1),n=n.next,u+=1;o.allBuffers=s,b(e,t,!0,t.length,o,"",a.finish),t.pendingcb++,t.lastBufferedRequest=null,a.next?(t.corkedRequestsFree=a.next,a.next=null):t.corkedRequestsFree=new i(t),t.bufferedRequestCount=0}else{for(;n;){var l=n.chunk,c=n.encoding,f=n.callback;if(b(e,t,!1,t.objectMode?1:l.length,l,c,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function E(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function x(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),S(e,t)})}function S(e,t){var n=E(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,a.nextTick(x,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}l.inherits(y,f),g.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(g.prototype,"buffer",{get:c.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(h=Function.prototype[Symbol.hasInstance],Object.defineProperty(y,Symbol.hasInstance,{value:function(e){return!!h.call(this,e)||this===y&&(e&&e._writableState instanceof g)}})):h=function(e){return e instanceof this},y.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},y.prototype.write=function(e,t,n){var r,o=this._writableState,i=!1,u=!o.objectMode&&(r=e,p.isBuffer(r)||r instanceof d);return u&&!p.isBuffer(e)&&(e=function(e){return p.from(e)}(e)),"function"==typeof t&&(n=t,t=null),u?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=m),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),a.nextTick(t,n)}(this,n):(u||function(e,t,n,r){var o=!0,i=!1;return null===n?i=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(i=new TypeError("Invalid non-string/buffer chunk")),i&&(e.emit("error",i),a.nextTick(r,i),o=!1),o}(this,o,e,n))&&(o.pendingcb++,i=function(e,t,n,r,o,a){if(!n){var i=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=p.from(t,n));return t}(t,r,o);r!==i&&(n=!0,o="buffer",r=i)}var u=t.objectMode?1:r.length;t.length+=u;var s=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(y.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),y.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},y.prototype._writev=null,y.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!==e&&void 0!==e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,S(e,t),n&&(t.finished?a.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),y.prototype.destroy=v.destroy,y.prototype._undestroy=v.undestroy,y.prototype._destroy=function(e,t){this.end(),t(e)}}).call(t,n(56),n(311).setImmediate,n(31))},function(e,t,n){"use strict";e.exports=function(e){return"function"==typeof e}},function(e,t,n){"use strict";e.exports=n(693)()?Array.from:n(694)},function(e,t,n){"use strict";var r=n(707),o=n(67),a=n(85),i=Array.prototype.indexOf,u=Object.prototype.hasOwnProperty,s=Math.abs,l=Math.floor;e.exports=function(e){var t,n,c,f;if(!r(e))return i.apply(this,arguments);for(n=o(a(this).length),c=arguments[1],t=c=isNaN(c)?0:c>=0?l(c):o(this.length)-l(s(c));t1&&void 0!==arguments[1])||arguments[1];return e=(0,r.normalizeArray)(e),{type:u,payload:{thing:e,shown:t}}},t.changeMode=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=(0,r.normalizeArray)(e),{type:i,payload:{thing:e,mode:t}}};var r=n(9),o=t.UPDATE_LAYOUT="layout_update_layout",a=t.UPDATE_FILTER="layout_update_filter",i=t.UPDATE_MODE="layout_update_mode",u=t.SHOW="layout_show"},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.execute=t.executeRequest=t.logRequest=t.setMutatedRequest=t.setRequest=t.setResponse=t.updateEmptyParamInclusion=t.validateParams=t.invalidateResolvedSubtreeCache=t.updateResolvedSubtree=t.requestResolvedSubtree=t.resolveSpec=t.parseToJson=t.SET_SCHEME=t.UPDATE_RESOLVED_SUBTREE=t.UPDATE_RESOLVED=t.UPDATE_OPERATION_META_VALUE=t.CLEAR_VALIDATE_PARAMS=t.CLEAR_REQUEST=t.CLEAR_RESPONSE=t.LOG_REQUEST=t.SET_MUTATED_REQUEST=t.SET_REQUEST=t.SET_RESPONSE=t.VALIDATE_PARAMS=t.UPDATE_EMPTY_PARAM_INCLUSION=t.UPDATE_PARAM=t.UPDATE_JSON=t.UPDATE_URL=t.UPDATE_SPEC=void 0;var r=b(n(25)),o=b(n(86)),a=b(n(23)),i=b(n(43)),u=b(n(208)),s=b(n(341)),l=b(n(342)),c=b(n(46));t.updateSpec=function(e){var t=L(e).replace(/\t/g," ");if("string"==typeof e)return{type:_,payload:t}},t.updateResolved=function(e){return{type:N,payload:e}},t.updateUrl=function(e){return{type:w,payload:e}},t.updateJsonSpec=function(e){return{type:E,payload:e}},t.changeParam=function(e,t,n,r,o){return{type:x,payload:{path:e,value:r,paramName:t,paramIn:n,isXml:o}}},t.changeParamByIdentity=function(e,t,n,r){return{type:x,payload:{path:e,param:t,value:n,isXml:r}}},t.clearValidateParams=function(e){return{type:I,payload:{pathMethod:e}}},t.changeConsumesValue=function(e,t){return{type:j,payload:{path:e,value:t,key:"consumes_value"}}},t.changeProducesValue=function(e,t){return{type:j,payload:{path:e,value:t,key:"produces_value"}}},t.clearResponse=function(e,t){return{type:M,payload:{path:e,method:t}}},t.clearRequest=function(e,t){return{type:T,payload:{path:e,method:t}}},t.setScheme=function(e,t,n){return{type:D,payload:{scheme:e,path:t,method:n}}};var f=b(n(210)),p=n(7),d=b(n(212)),h=b(n(184)),v=b(n(345)),m=b(n(765)),g=b(n(767)),y=n(9);function b(e){return e&&e.__esModule?e:{default:e}}var _=t.UPDATE_SPEC="spec_update_spec",w=t.UPDATE_URL="spec_update_url",E=t.UPDATE_JSON="spec_update_json",x=t.UPDATE_PARAM="spec_update_param",S=t.UPDATE_EMPTY_PARAM_INCLUSION="spec_update_empty_param_inclusion",C=t.VALIDATE_PARAMS="spec_validate_param",k=t.SET_RESPONSE="spec_set_response",A=t.SET_REQUEST="spec_set_request",O=t.SET_MUTATED_REQUEST="spec_set_mutated_request",P=t.LOG_REQUEST="spec_log_request",M=t.CLEAR_RESPONSE="spec_clear_response",T=t.CLEAR_REQUEST="spec_clear_request",I=t.CLEAR_VALIDATE_PARAMS="spec_clear_validate_param",j=t.UPDATE_OPERATION_META_VALUE="spec_update_operation_meta_value",N=t.UPDATE_RESOLVED="spec_update_resolved",R=t.UPDATE_RESOLVED_SUBTREE="spec_update_resolved_subtree",D=t.SET_SCHEME="set_scheme",L=function(e){return(0,v.default)(e)?e:""};t.parseToJson=function(e){return function(t){var n=t.specActions,r=t.specSelectors,o=t.errActions,a=r.specStr,i=null;try{e=e||a(),o.clear({source:"parser"}),i=f.default.safeLoad(e)}catch(e){return console.error(e),o.newSpecErr({source:"parser",level:"error",message:e.reason,line:e.mark&&e.mark.line?e.mark.line+1:void 0})}return i&&"object"===(void 0===i?"undefined":(0,c.default)(i))?n.updateJsonSpec(i):{}}};var U=!1,q=(t.resolveSpec=function(e,t){return function(n){var r=n.specActions,o=n.specSelectors,a=n.errActions,i=n.fn,u=i.fetch,s=i.resolve,l=i.AST,c=void 0===l?{}:l,f=n.getConfigs;U||(console.warn("specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use requestResolvedSubtree instead!"),U=!0);var p=f(),d=p.modelPropertyMacro,h=p.parameterMacro,v=p.requestInterceptor,m=p.responseInterceptor;void 0===e&&(e=o.specJson()),void 0===t&&(t=o.url());var g=c.getLineNumberForPath?c.getLineNumberForPath:function(){},y=o.specStr();return s({fetch:u,spec:e,baseDoc:t,modelPropertyMacro:d,parameterMacro:h,requestInterceptor:v,responseInterceptor:m}).then(function(e){var t=e.spec,n=e.errors;if(a.clear({type:"thrown"}),Array.isArray(n)&&n.length>0){var o=n.map(function(e){return console.error(e),e.line=e.fullPath?g(y,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",Object.defineProperty(e,"message",{enumerable:!0,value:e.message}),e});a.newThrownErrBatch(o)}return r.updateResolved(t)})}},[]),F=(0,m.default)((0,l.default)(s.default.mark(function e(){var t,n,r,o,a,i,c,f,d,h,v,m,y,b,_,w,E;return s.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t=q.system){e.next=4;break}return console.error("debResolveSubtrees: don't have a system to operate on, aborting."),e.abrupt("return");case 4:if(n=t.errActions,r=t.errSelectors,o=t.fn,a=o.resolveSubtree,i=o.AST,c=void 0===i?{}:i,f=t.specSelectors,d=t.specActions,a){e.next=8;break}return console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing."),e.abrupt("return");case 8:return h=c.getLineNumberForPath?c.getLineNumberForPath:function(){},v=f.specStr(),m=t.getConfigs(),y=m.modelPropertyMacro,b=m.parameterMacro,_=m.requestInterceptor,w=m.responseInterceptor,e.prev=11,e.next=14,q.reduce(function(){var e=(0,l.default)(s.default.mark(function e(t,o){var i,u,l,c,p,d,m;return s.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t;case 2:return i=e.sent,u=i.resultMap,l=i.specWithCurrentSubtrees,e.next=7,a(l,o,{baseDoc:f.url(),modelPropertyMacro:y,parameterMacro:b,requestInterceptor:_,responseInterceptor:w});case 7:return c=e.sent,p=c.errors,d=c.spec,r.allErrors().size&&n.clearBy(function(e){return"thrown"!==e.get("type")||"resolver"!==e.get("source")||!e.get("fullPath").every(function(e,t){return e===o[t]||void 0===o[t]})}),Array.isArray(p)&&p.length>0&&(m=p.map(function(e){return e.line=e.fullPath?h(v,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",Object.defineProperty(e,"message",{enumerable:!0,value:e.message}),e}),n.newThrownErrBatch(m)),(0,g.default)(u,o,d),(0,g.default)(l,o,d),e.abrupt("return",{resultMap:u,specWithCurrentSubtrees:l});case 15:case"end":return e.stop()}},e,void 0)}));return function(t,n){return e.apply(this,arguments)}}(),u.default.resolve({resultMap:(f.specResolvedSubtree([])||(0,p.Map)()).toJS(),specWithCurrentSubtrees:f.specJson().toJS()}));case 14:E=e.sent,delete q.system,q=[],e.next=22;break;case 19:e.prev=19,e.t0=e.catch(11),console.error(e.t0);case 22:d.updateResolvedSubtree([],E.resultMap);case 23:case"end":return e.stop()}},e,void 0,[[11,19]])})),35);t.requestResolvedSubtree=function(e){return function(t){q.map(function(e){return e.join("@@")}).indexOf(e.join("@@"))>-1||(q.push(e),q.system=t,F())}};t.updateResolvedSubtree=function(e,t){return{type:R,payload:{path:e,value:t}}},t.invalidateResolvedSubtreeCache=function(){return{type:R,payload:{path:[],value:(0,p.Map)()}}},t.validateParams=function(e,t){return{type:C,payload:{pathMethod:e,isOAS3:t}}},t.updateEmptyParamInclusion=function(e,t,n,r){return{type:S,payload:{pathMethod:e,paramName:t,paramIn:n,includeEmptyValue:r}}};t.setResponse=function(e,t,n){return{payload:{path:e,method:t,res:n},type:k}},t.setRequest=function(e,t,n){return{payload:{path:e,method:t,req:n},type:A}},t.setMutatedRequest=function(e,t,n){return{payload:{path:e,method:t,req:n},type:O}},t.logRequest=function(e){return{payload:e,type:P}},t.executeRequest=function(e){return function(t){var n=t.fn,r=t.specActions,o=t.specSelectors,u=t.getConfigs,s=t.oas3Selectors,l=e.pathName,c=e.method,f=e.operation,p=u(),v=p.requestInterceptor,m=p.responseInterceptor,g=f.toJS();if(f&&f.get("parameters")&&f.get("parameters").filter(function(e){return e&&!0===e.get("allowEmptyValue")}).forEach(function(t){if(o.parameterInclusionSettingFor([l,c],t.get("name"),t.get("in"))){e.parameters=e.parameters||{};var n=(0,y.paramToValue)(t,e.parameters);(!n||n&&0===n.size)&&(e.parameters[t.get("name")]="")}}),e.contextUrl=(0,d.default)(o.url()).toString(),g&&g.operationId?e.operationId=g.operationId:g&&l&&c&&(e.operationId=n.opId(g,l,c)),o.isOAS3()){var b=l+":"+c;e.server=s.selectedServer(b)||s.selectedServer();var _=s.serverVariables({server:e.server,namespace:b}).toJS(),w=s.serverVariables({server:e.server}).toJS();e.serverVariables=(0,i.default)(_).length?_:w,e.requestContentType=s.requestContentType(l,c),e.responseContentType=s.responseContentType(l,c)||"*/*";var E=s.requestBodyValue(l,c);(0,y.isJSONObject)(E)?e.requestBody=JSON.parse(E):E&&E.toJS?e.requestBody=E.toJS():e.requestBody=E}var x=(0,a.default)({},e);x=n.buildRequest(x),r.setRequest(e.pathName,e.method,x);e.requestInterceptor=function(t){var n=v.apply(this,[t]),o=(0,a.default)({},n);return r.setMutatedRequest(e.pathName,e.method,o),n},e.responseInterceptor=m;var S=Date.now();return n.execute(e).then(function(t){t.duration=Date.now()-S,r.setResponse(e.pathName,e.method,t)}).catch(function(t){return r.setResponse(e.pathName,e.method,{error:!0,err:(0,h.default)(t)})})}};t.execute=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.path,n=e.method,a=(0,o.default)(e,["path","method"]);return function(e){var o=e.fn.fetch,i=e.specSelectors,u=e.specActions,s=i.specJsonWithResolvedSubtrees().toJS(),l=i.operationScheme(t,n),c=i.contentTypeValues([t,n]).toJS(),f=c.requestContentType,p=c.responseContentType,d=/xml/i.test(f),h=i.parameterValues([t,n],d).toJS();return u.executeRequest((0,r.default)({},a,{fetch:o,spec:s,pathName:t,method:n,parameters:h,requestContentType:f,scheme:l,responseContentType:p}))}}},function(e,t,n){e.exports={default:n(735),__esModule:!0}},function(e,t,n){"use strict";var r=n(96);e.exports.f=function(e){return new function(e){var t,n;this.promise=new e(function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r}),this.resolve=r(t),this.reject=r(n)}(e)}},function(e,t,n){"use strict";var r=n(743);e.exports=r},function(e,t,n){"use strict";var r=n(89);e.exports=new r({explicit:[n(746),n(747),n(748)]})},function(e,t,n){"use strict";(function(t){var r=n(763),o=n(764),a=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,i=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,u=[["#","hash"],["?","query"],function(e){return e.replace("\\","/")},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],s={hash:1,query:1};function l(e){var n,r=t&&t.location||{},o={},a=typeof(e=e||r);if("blob:"===e.protocol)o=new f(unescape(e.pathname),{});else if("string"===a)for(n in o=new f(e,{}),s)delete o[n];else if("object"===a){for(n in e)n in s||(o[n]=e[n]);void 0===o.slashes&&(o.slashes=i.test(e.href))}return o}function c(e){var t=a.exec(e);return{protocol:t[1]?t[1].toLowerCase():"",slashes:!!t[2],rest:t[3]}}function f(e,t,n){if(!(this instanceof f))return new f(e,t,n);var a,i,s,p,d,h,v=u.slice(),m=typeof t,g=this,y=0;for("object"!==m&&"string"!==m&&(n=t,t=null),n&&"function"!=typeof n&&(n=o.parse),t=l(t),a=!(i=c(e||"")).protocol&&!i.slashes,g.slashes=i.slashes||a&&t.slashes,g.protocol=i.protocol||t.protocol||"",e=i.rest,i.slashes||(v[3]=[/(.*)/,"pathname"]);y-1||r("96",e),!l.plugins[n]){t.extractEvents||r("97",e),l.plugins[n]=t;var i=t.eventTypes;for(var s in i)u(i[s],t,s)||r("98",s,e)}}}function u(e,t,n){l.eventNameDispatchConfigs.hasOwnProperty(n)&&r("99",n),l.eventNameDispatchConfigs[n]=e;var o=e.phasedRegistrationNames;if(o){for(var a in o){if(o.hasOwnProperty(a))s(o[a],t,n)}return!0}return!!e.registrationName&&(s(e.registrationName,t,n),!0)}function s(e,t,n){l.registrationNameModules[e]&&r("100",e),l.registrationNameModules[e]=t,l.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var l={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},possibleRegistrationNames:null,injectEventPluginOrder:function(e){o&&r("101"),o=Array.prototype.slice.call(e),i()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];a.hasOwnProperty(n)&&a[n]===o||(a[n]&&r("102",n),a[n]=o,t=!0)}t&&i()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return l.registrationNameModules[t.registrationName]||null;if(void 0!==t.phasedRegistrationNames){var n=t.phasedRegistrationNames;for(var r in n)if(n.hasOwnProperty(r)){var o=l.registrationNameModules[n[r]];if(o)return o}}return null},_resetEventPlugins:function(){for(var e in o=null,a)a.hasOwnProperty(e)&&delete a[e];l.plugins.length=0;var t=l.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=l.registrationNameModules;for(var i in r)r.hasOwnProperty(i)&&delete r[i]}};e.exports=l},function(e,t,n){"use strict";var r,o,a=n(12),i=n(215);n(8),n(11);function u(e,t,n,r){var o=e.type||"unknown-event";e.currentTarget=s.getNodeFromInstance(r),t?i.invokeGuardedCallbackWithCatch(o,n,e):i.invokeGuardedCallback(o,n,e),e.currentTarget=null}var s={isEndish:function(e){return"topMouseUp"===e||"topTouchEnd"===e||"topTouchCancel"===e},isMoveish:function(e){return"topMouseMove"===e||"topTouchMove"===e},isStartish:function(e){return"topMouseDown"===e||"topTouchStart"===e},executeDirectDispatch:function(e){var t=e._dispatchListeners,n=e._dispatchInstances;Array.isArray(t)&&a("103"),e.currentTarget=t?s.getNodeFromInstance(n):null;var r=t?t(e):null;return e.currentTarget=null,e._dispatchListeners=null,e._dispatchInstances=null,r},executeDispatchesInOrder:function(e,t){var n=e._dispatchListeners,r=e._dispatchInstances;if(Array.isArray(n))for(var o=0;o0&&r.length<20?n+" (keys: "+r.join(", ")+")":n}function s(e,t){var n=o.get(e);return n||null}var l={isMounted:function(e){var t=o.get(e);return!!t&&!!t._renderedComponent},enqueueCallback:function(e,t,n){l.validateCallback(t,n);var r=s(e);if(!r)return null;r._pendingCallbacks?r._pendingCallbacks.push(t):r._pendingCallbacks=[t],i(r)},enqueueCallbackInternal:function(e,t){e._pendingCallbacks?e._pendingCallbacks.push(t):e._pendingCallbacks=[t],i(e)},enqueueForceUpdate:function(e){var t=s(e);t&&(t._pendingForceUpdate=!0,i(t))},enqueueReplaceState:function(e,t,n){var r=s(e);r&&(r._pendingStateQueue=[t],r._pendingReplaceState=!0,void 0!==n&&null!==n&&(l.validateCallback(n,"replaceState"),r._pendingCallbacks?r._pendingCallbacks.push(n):r._pendingCallbacks=[n]),i(r))},enqueueSetState:function(e,t){var n=s(e);n&&((n._pendingStateQueue||(n._pendingStateQueue=[])).push(t),i(n))},enqueueElementInternal:function(e,t,n){e._pendingElement=t,e._context=n,i(e)},validateCallback:function(e,t){e&&"function"!=typeof e&&r("122",t,u(e))}};e.exports=l},function(e,t,n){"use strict";n(13);var r=n(34),o=(n(11),r);e.exports=o},function(e,t,n){"use strict";e.exports=function(e){var t,n=e.keyCode;return"charCode"in e?0===(t=e.charCode)&&13===n&&(t=13):t=n,t>=32||13===t?t:0}},function(e,t,n){var r=n(62),o=n(231),a=n(48),i="[object Object]",u=Function.prototype,s=Object.prototype,l=u.toString,c=s.hasOwnProperty,f=l.call(Object);e.exports=function(e){if(!a(e)||r(e)!=i)return!1;var t=o(e);if(null===t)return!0;var n=c.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&l.call(n)==f}},function(e,t,n){var r=n(300)(Object.getPrototypeOf,Object);e.exports=r},function(e,t,n){var r=n(294);e.exports=function(e){var t=new e.constructor(e.byteLength);return new r(t).set(new r(e)),t}},function(e,t){ +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +var n=this&&this.__extends||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);function r(){this.constructor=e}e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)},r=Object.prototype.hasOwnProperty;function o(e,t){return r.call(e,t)}function a(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0},t.escapePathComponent=i,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var n=u(e,t);if(""===n)throw new Error("Object not found in root");return"/"+n},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,r=t.length;nw;w++)if((p||w in y)&&(m=b(v=y[w],w,g),e))if(n)E[w]=m;else if(m)switch(e){case 3:return!0;case 5:return v;case 6:return w;case 2:E.push(v)}else if(c)return!1;return f?-1:l||c?c:E}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.authorizeRequest=t.authorizeAccessCodeWithBasicAuthentication=t.authorizeAccessCodeWithFormParams=t.authorizeApplication=t.authorizePassword=t.preAuthorizeImplicit=t.CONFIGURE_AUTH=t.VALIDATE=t.AUTHORIZE_OAUTH2=t.PRE_AUTHORIZE_OAUTH2=t.LOGOUT=t.AUTHORIZE=t.SHOW_AUTH_POPUP=void 0;var r=l(n(46)),o=l(n(23)),a=l(n(42));t.showDefinitions=function(e){return{type:c,payload:e}},t.authorize=function(e){return{type:f,payload:e}},t.logout=function(e){return{type:p,payload:e}},t.authorizeOauth2=function(e){return{type:d,payload:e}},t.configureAuth=function(e){return{type:h,payload:e}};var i=l(n(212)),u=l(n(32)),s=n(9);function l(e){return e&&e.__esModule?e:{default:e}}var c=t.SHOW_AUTH_POPUP="show_popup",f=t.AUTHORIZE="authorize",p=t.LOGOUT="logout",d=(t.PRE_AUTHORIZE_OAUTH2="pre_authorize_oauth2",t.AUTHORIZE_OAUTH2="authorize_oauth2"),h=(t.VALIDATE="validate",t.CONFIGURE_AUTH="configure_auth");t.preAuthorizeImplicit=function(e){return function(t){var n=t.authActions,r=t.errActions,o=e.auth,i=e.token,s=e.isValid,l=o.schema,c=o.name,f=l.get("flow");delete u.default.swaggerUIRedirectOauth2,"accessCode"===f||s||r.newAuthErr({authId:c,source:"auth",level:"warning",message:"Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"}),i.error?r.newAuthErr({authId:c,source:"auth",level:"error",message:(0,a.default)(i)}):n.authorizeOauth2({auth:o,token:i})}};t.authorizePassword=function(e){return function(t){var n=t.authActions,r=e.schema,a=e.name,i=e.username,u=e.password,l=e.passwordType,c=e.clientId,f=e.clientSecret,p={grant_type:"password",scope:e.scopes.join(" "),username:i,password:u},d={};switch(l){case"request-body":!function(e,t,n){t&&(0,o.default)(e,{client_id:t});n&&(0,o.default)(e,{client_secret:n})}(p,c,f);break;case"basic":d.Authorization="Basic "+(0,s.btoa)(c+":"+f);break;default:console.warn("Warning: invalid passwordType "+l+" was passed, not including client id and secret")}return n.authorizeRequest({body:(0,s.buildFormData)(p),url:r.get("tokenUrl"),name:a,headers:d,query:{},auth:e})}};t.authorizeApplication=function(e){return function(t){var n=t.authActions,r=e.schema,o=e.scopes,a=e.name,i=e.clientId,u=e.clientSecret,l={Authorization:"Basic "+(0,s.btoa)(i+":"+u)},c={grant_type:"client_credentials",scope:o.join(" ")};return n.authorizeRequest({body:(0,s.buildFormData)(c),name:a,url:r.get("tokenUrl"),auth:e,headers:l})}},t.authorizeAccessCodeWithFormParams=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,a=t.name,i=t.clientId,u=t.clientSecret,l={grant_type:"authorization_code",code:t.code,client_id:i,client_secret:u,redirect_uri:n};return r.authorizeRequest({body:(0,s.buildFormData)(l),name:a,url:o.get("tokenUrl"),auth:t})}},t.authorizeAccessCodeWithBasicAuthentication=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,a=t.name,i=t.clientId,u=t.clientSecret,l={Authorization:"Basic "+(0,s.btoa)(i+":"+u)},c={grant_type:"authorization_code",code:t.code,client_id:i,redirect_uri:n};return r.authorizeRequest({body:(0,s.buildFormData)(c),name:a,url:o.get("tokenUrl"),auth:t,headers:l})}},t.authorizeRequest=function(e){return function(t){var n=t.fn,u=t.getConfigs,s=t.authActions,l=t.errActions,c=t.oas3Selectors,f=t.specSelectors,p=t.authSelectors,d=e.body,h=e.query,v=void 0===h?{}:h,m=e.headers,g=void 0===m?{}:m,y=e.name,b=e.url,_=e.auth,w=(p.getConfigs()||{}).additionalQueryStringParams,E=void 0;E=f.isOAS3()?(0,i.default)(b,c.selectedServer(),!0):(0,i.default)(b,f.url(),!0),"object"===(void 0===w?"undefined":(0,r.default)(w))&&(E.query=(0,o.default)({},E.query,w));var x=E.toString(),S=(0,o.default)({Accept:"application/json, text/plain, */*","Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"},g);n.fetch({url:x,method:"post",headers:S,query:v,body:d,requestInterceptor:u().requestInterceptor,responseInterceptor:u().responseInterceptor}).then(function(e){var t=JSON.parse(e.data),n=t&&(t.error||""),r=t&&(t.parseError||"");e.ok?n||r?l.newAuthErr({authId:y,level:"error",source:"auth",message:(0,a.default)(t)}):s.authorizeOauth2({auth:_,token:t}):l.newAuthErr({authId:y,level:"error",source:"auth",message:e.statusText})}).catch(function(e){var t=new Error(e).message;if(e.response&&e.response.data){var n=e.response.data;try{var r="string"==typeof n?JSON.parse(n):n;r.error&&(t+=", error: "+r.error),r.error_description&&(t+=", description: "+r.error_description)}catch(e){}}l.newAuthErr({authId:y,level:"error",source:"auth",message:t})})}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.parseYamlConfig=void 0;var r,o=n(210),a=(r=o)&&r.__esModule?r:{default:r};t.parseYamlConfig=function(e,t){try{return a.default.safeLoad(e)}catch(e){return t&&t.errActions.newThrownErr(new Error(e)),{}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.loaded=t.TOGGLE_CONFIGS=t.UPDATE_CONFIGS=void 0;var r,o=n(21),a=(r=o)&&r.__esModule?r:{default:r};t.update=function(e,t){return{type:i,payload:(0,a.default)({},e,t)}},t.toggle=function(e){return{type:u,payload:e}};var i=t.UPDATE_CONFIGS="configs_update",u=t.TOGGLE_CONFIGS="configs_toggle";t.loaded=function(){return function(){}}},function(e,t,n){"use strict";function r(e,t,n,r,o){this.src=e,this.env=r,this.options=n,this.parser=t,this.tokens=o,this.pos=0,this.posMax=this.src.length,this.level=0,this.pending="",this.pendingLevel=0,this.cache=[],this.isInLabel=!1,this.linkLevel=0,this.linkContent="",this.labelUnmatchedScopes=0}r.prototype.pushPending=function(){this.tokens.push({type:"text",content:this.pending,level:this.pendingLevel}),this.pending=""},r.prototype.push=function(e){this.pending&&this.pushPending(),this.tokens.push(e),this.pendingLevel=this.level},r.prototype.cacheSet=function(e,t){for(var n=this.cache.length;n<=e;n++)this.cache.push(0);this.cache[e]=t},r.prototype.cacheGet=function(e){return es;)r(u,n=t[s++])&&(~a(l,n)||l.push(n));return l}},function(e,t,n){var r=n(22).document;e.exports=r&&r.documentElement},function(e,t,n){var r=n(52),o=n(74),a=n(168)("IE_PROTO"),i=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=o(e),r(e,a)?e[a]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?i:null}},function(e,t,n){var r=n(33),o=r["__core-js_shared__"]||(r["__core-js_shared__"]={});e.exports=function(e){return o[e]||(o[e]={})}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){"use strict";var r=n(248)(!0);n(249)(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var r=n(123),o=n(53);e.exports=function(e){return function(t,n){var a,i,u=String(o(t)),s=r(n),l=u.length;return s<0||s>=l?e?"":void 0:(a=u.charCodeAt(s))<55296||a>56319||s+1===l||(i=u.charCodeAt(s+1))<56320||i>57343?e?u.charAt(s):a:e?u.slice(s,s+2):i-56320+(a-55296<<10)+65536}}},function(e,t,n){"use strict";var r=n(250),o=n(29),a=n(76),i=n(59),u=n(103),s=n(464),l=n(176),c=n(470),f=n(17)("iterator"),p=!([].keys&&"next"in[].keys()),d=function(){return this};e.exports=function(e,t,n,h,v,m,g){s(n,t,h);var y,b,_,w=function(e){if(!p&&e in C)return C[e];switch(e){case"keys":case"values":return function(){return new n(this,e)}}return function(){return new n(this,e)}},E=t+" Iterator",x="values"==v,S=!1,C=e.prototype,k=C[f]||C["@@iterator"]||v&&C[v],A=k||w(v),O=v?x?w("entries"):A:void 0,P="Array"==t&&C.entries||k;if(P&&(_=c(P.call(new e)))!==Object.prototype&&_.next&&(l(_,E,!0),r||"function"==typeof _[f]||i(_,f,d)),x&&k&&"values"!==k.name&&(S=!0,A=function(){return k.call(this)}),r&&!g||!p&&!S&&C[f]||i(C,f,A),u[t]=A,u[E]=d,v)if(y={values:x?A:w("values"),keys:m?A:w("keys"),entries:O},g)for(b in y)b in C||a(C,b,y[b]);else o(o.P+o.F*(p||S),t,y);return y}},function(e,t){e.exports=!1},function(e,t,n){var r=n(467),o=n(253);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t,n){var r=n(123),o=Math.max,a=Math.min;e.exports=function(e,t){return(e=r(e))<0?o(e+t,0):a(e,t)}},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var r=n(33).document;e.exports=r&&r.documentElement},function(e,t,n){var r=n(60),o=n(125),a=n(17)("species");e.exports=function(e,t){var n,i=r(e).constructor;return void 0===i||void 0==(n=r(i)[a])?t:o(n)}},function(e,t,n){var r,o,a,i=n(124),u=n(482),s=n(254),l=n(174),c=n(33),f=c.process,p=c.setImmediate,d=c.clearImmediate,h=c.MessageChannel,v=c.Dispatch,m=0,g={},y=function(){var e=+this;if(g.hasOwnProperty(e)){var t=g[e];delete g[e],t()}},b=function(e){y.call(e.data)};p&&d||(p=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return g[++m]=function(){u("function"==typeof e?e:Function(e),t)},r(m),m},d=function(e){delete g[e]},"process"==n(100)(f)?r=function(e){f.nextTick(i(y,e,1))}:v&&v.now?r=function(e){v.now(i(y,e,1))}:h?(a=(o=new h).port2,o.port1.onmessage=b,r=i(a.postMessage,a,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(r=function(e){c.postMessage(e+"","*")},c.addEventListener("message",b,!1)):r="onreadystatechange"in l("script")?function(e){s.appendChild(l("script")).onreadystatechange=function(){s.removeChild(this),y.call(e)}}:function(e){setTimeout(i(y,e,1),0)}),e.exports={set:p,clear:d}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,n){var r=n(60),o=n(77),a=n(177);e.exports=function(e,t){if(r(e),o(t)&&t.constructor===e)return t;var n=a.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){var r=n(77),o=n(100),a=n(17)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[a])?!!t:"RegExp"==o(e))}},function(e,t,n){var r=n(19),o=n(14),a=n(51);e.exports=function(e,t){var n=(o.Object||{})[e]||Object[e],i={};i[e]=t(n),r(r.S+r.F*a(function(){n(1)}),"Object",i)}},function(e,t,n){var r=n(95);e.exports=Array.isArray||function(e){return"Array"==r(e)}},function(e,t,n){var r=n(242),o=n(170).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,o)}},function(e,t,n){var r=n(128),o=n(97),a=n(73),i=n(165),u=n(52),s=n(241),l=Object.getOwnPropertyDescriptor;t.f=n(41)?l:function(e,t){if(e=a(e),t=i(t,!0),s)try{return l(e,t)}catch(e){}if(u(e,t))return o(!r.f.call(e,t),e[t])}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){e.exports={default:n(534),__esModule:!0}},function(e,t,n){"use strict";var r=n(98),o=n(182),a=n(128),i=n(74),u=n(161),s=Object.assign;e.exports=!s||n(51)(function(){var e={},t={},n=Symbol(),r="abcdefghijklmnopqrst";return e[n]=7,r.split("").forEach(function(e){t[e]=e}),7!=s({},e)[n]||Object.keys(s({},t)).join("")!=r})?function(e,t){for(var n=i(e),s=arguments.length,l=1,c=o.f,f=a.f;s>l;)for(var p,d=u(arguments[l++]),h=c?r(d).concat(c(d)):r(d),v=h.length,m=0;v>m;)f.call(d,p=h[m++])&&(n[p]=d[p]);return n}:s},function(e,t,n){"use strict";var r=n(106),o=n(13),a=n(268),i=(n(269),n(130));n(8),n(538);function u(e,t,n){this.props=e,this.context=t,this.refs=i,this.updater=n||a}function s(e,t,n){this.props=e,this.context=t,this.refs=i,this.updater=n||a}function l(){}u.prototype.isReactComponent={},u.prototype.setState=function(e,t){"object"!=typeof e&&"function"!=typeof e&&null!=e&&r("85"),this.updater.enqueueSetState(this,e),t&&this.updater.enqueueCallback(this,t,"setState")},u.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this),e&&this.updater.enqueueCallback(this,e,"forceUpdate")},l.prototype=u.prototype,s.prototype=new l,s.prototype.constructor=s,o(s.prototype,u.prototype),s.prototype.isPureReactComponent=!0,e.exports={Component:u,PureComponent:s}},function(e,t,n){"use strict";n(11);var r={isMounted:function(e){return!1},enqueueCallback:function(e,t){},enqueueForceUpdate:function(e){},enqueueReplaceState:function(e,t){},enqueueSetState:function(e,t){}};e.exports=r},function(e,t,n){"use strict";var r=!1;e.exports=r},function(e,t,n){"use strict";var r="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103;e.exports=r},function(e,t,n){"use strict";var r=n(546);e.exports=function(e){return r(e,!1)}},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(274),o=n(563),a=n(564),i=n(565),u=n(278);n(277);n.d(t,"createStore",function(){return r.b}),n.d(t,"combineReducers",function(){return o.a}),n.d(t,"bindActionCreators",function(){return a.a}),n.d(t,"applyMiddleware",function(){return i.a}),n.d(t,"compose",function(){return u.a})},function(e,t,n){"use strict";n.d(t,"a",function(){return a}),t.b=function e(t,n,i){var u;"function"==typeof n&&void 0===i&&(i=n,n=void 0);if(void 0!==i){if("function"!=typeof i)throw new Error("Expected the enhancer to be a function.");return i(e)(t,n)}if("function"!=typeof t)throw new Error("Expected the reducer to be a function.");var s=t;var l=n;var c=[];var f=c;var p=!1;function d(){f===c&&(f=c.slice())}function h(){return l}function v(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var t=!0;return d(),f.push(e),function(){if(t){t=!1,d();var n=f.indexOf(e);f.splice(n,1)}}}function m(e){if(!Object(r.a)(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(p)throw new Error("Reducers may not dispatch actions.");try{p=!0,l=s(l,e)}finally{p=!1}for(var t=c=f,n=0;no?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var a=Array(o);++rp))return!1;var h=c.get(e);if(h&&c.get(t))return h==t;var v=-1,m=!0,g=n&u?new r:void 0;for(c.set(e,t),c.set(t,e);++v0?("string"==typeof t||i.objectMode||Object.getPrototypeOf(t)===l.prototype||(t=function(e){return l.from(e)}(t)),r?i.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):w(e,i,t,!0):i.ended?e.emit("error",new Error("stream.push() after EOF")):(i.reading=!1,i.decoder&&!n?(t=i.decoder.write(t),i.objectMode||0!==t.length?w(e,i,t,!1):k(e,i)):w(e,i,t,!1))):r||(i.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=E?e=E:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function S(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(d("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(C,e):C(e))}function C(e){d("emit readable"),e.emit("readable"),M(e)}function k(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(A,e,t))}function A(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ea.length?a.length:e;if(i===a.length?o+=a:o+=a.slice(0,e),0===(e-=i)){i===a.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=a.slice(i));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=l.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var a=r.data,i=e>a.length?a.length:e;if(a.copy(n,n.length-e,0,i),0===(e-=i)){i===a.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=a.slice(i));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function I(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(j,t,e))}function j(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function N(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return d("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?I(this):S(this),null;if(0===(e=x(e,t))&&t.ended)return 0===t.length&&I(this),null;var r,o=t.needReadable;return d("need readable",o),(0===t.length||t.length-e0?T(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&I(this)),null!==r&&this.emit("data",r),r},b.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},b.prototype.pipe=function(e,t){var n=this,a=this._readableState;switch(a.pipesCount){case 0:a.pipes=e;break;case 1:a.pipes=[a.pipes,e];break;default:a.pipes.push(e)}a.pipesCount+=1,d("pipe count=%d opts=%j",a.pipesCount,t);var s=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?c:b;function l(t,r){d("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,d("cleanup"),e.removeListener("close",g),e.removeListener("finish",y),e.removeListener("drain",f),e.removeListener("error",m),e.removeListener("unpipe",l),n.removeListener("end",c),n.removeListener("end",b),n.removeListener("data",v),p=!0,!a.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function c(){d("onend"),e.end()}a.endEmitted?o.nextTick(s):n.once("end",s),e.on("unpipe",l);var f=function(e){return function(){var t=e._readableState;d("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&u(e,"data")&&(t.flowing=!0,M(e))}}(n);e.on("drain",f);var p=!1;var h=!1;function v(t){d("ondata"),h=!1,!1!==e.write(t)||h||((1===a.pipesCount&&a.pipes===e||a.pipesCount>1&&-1!==N(a.pipes,e))&&!p&&(d("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,h=!0),n.pause())}function m(t){d("onerror",t),b(),e.removeListener("error",m),0===u(e,"error")&&e.emit("error",t)}function g(){e.removeListener("finish",y),b()}function y(){d("onfinish"),e.removeListener("close",g),b()}function b(){d("unpipe"),n.unpipe(e)}return n.on("data",v),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?i(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",m),e.once("close",g),e.once("finish",y),e.emit("pipe",n),a.flowing||(d("pipe resume"),n.resume()),e},b.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var a=0;a=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(665),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(t,n(31))},function(e,t,n){"use strict";var r=n(145).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function a(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=s,this.end=l,t=4;break;case"utf8":this.fillLast=u,t=4;break;case"base64":this.text=c,this.end=f,t=3;break;default:return this.write=p,void(this.end=d)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function i(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function u(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function s(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function l(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function c(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function p(e){return e.toString(this.encoding)}function d(e){return e&&e.length?this.write(e):""}t.StringDecoder=a,a.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},a.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";e.exports=a;var r=n(65),o=n(108);function a(e){if(!(this instanceof a))return new a(e);r.call(this,e),this._transformState={afterTransform:function(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length=0?n&&o?o-1:o:1:!1!==e&&r(e)}},function(e,t,n){"use strict";e.exports=n(681)()?Object.assign:n(682)},function(e,t,n){"use strict";var r,o,a,i,u,s=n(67),l=function(e,t){return t};try{Object.defineProperty(l,"length",{configurable:!0,writable:!1,enumerable:!1,value:1})}catch(e){}1===l.length?(r={configurable:!0,writable:!1,enumerable:!1},o=Object.defineProperty,e.exports=function(e,t){return t=s(t),e.length===t?e:(r.value=t,o(e,"length",r))}):(i=n(319),u=[],a=function(e){var t,n=0;if(u[e])return u[e];for(t=[];e--;)t.push("a"+(++n).toString(36));return new Function("fn","return function ("+t.join(", ")+") { return fn.apply(this, arguments); };")},e.exports=function(e,t){var n;if(t=s(t),e.length===t)return e;n=a(t)(e);try{i(n,e)}catch(e){}return n})},function(e,t,n){"use strict";var r=n(85),o=Object.defineProperty,a=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,u=Object.getOwnPropertySymbols;e.exports=function(e,t){var n,s=Object(r(t));if(e=Object(r(e)),i(s).forEach(function(r){try{o(e,r,a(t,r))}catch(e){n=e}}),"function"==typeof u&&u(s).forEach(function(r){try{o(e,r,a(t,r))}catch(e){n=e}}),void 0!==n)throw n;return e}},function(e,t,n){"use strict";var r=n(57),o=n(146),a=Function.prototype.call;e.exports=function(e,t){var n={},i=arguments[2];return r(t),o(e,function(e,r,o,u){n[r]=a.call(t,i,e,r,o,u)}),n}},function(e,t){e.exports=function(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return{statePlugins:{err:{reducers:(0,a.default)(e),actions:i,selectors:u}}}};var r,o=n(323),a=(r=o)&&r.__esModule?r:{default:r},i=s(n(131)),u=s(n(327));function s(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=s(n(21)),o=s(n(23));t.default=function(e){var t;return t={},(0,r.default)(t,a.NEW_THROWN_ERR,function(t,n){var r=n.payload,a=(0,o.default)(l,r,{type:"thrown"});return t.update("errors",function(e){return(e||(0,i.List)()).push((0,i.fromJS)(a))}).update("errors",function(t){return(0,u.default)(t,e.getSystem())})}),(0,r.default)(t,a.NEW_THROWN_ERR_BATCH,function(t,n){var r=n.payload;return r=r.map(function(e){return(0,i.fromJS)((0,o.default)(l,e,{type:"thrown"}))}),t.update("errors",function(e){return(e||(0,i.List)()).concat((0,i.fromJS)(r))}).update("errors",function(t){return(0,u.default)(t,e.getSystem())})}),(0,r.default)(t,a.NEW_SPEC_ERR,function(t,n){var r=n.payload,o=(0,i.fromJS)(r);return o=o.set("type","spec"),t.update("errors",function(e){return(e||(0,i.List)()).push((0,i.fromJS)(o)).sortBy(function(e){return e.get("line")})}).update("errors",function(t){return(0,u.default)(t,e.getSystem())})}),(0,r.default)(t,a.NEW_SPEC_ERR_BATCH,function(t,n){var r=n.payload;return r=r.map(function(e){return(0,i.fromJS)((0,o.default)(l,e,{type:"spec"}))}),t.update("errors",function(e){return(e||(0,i.List)()).concat((0,i.fromJS)(r))}).update("errors",function(t){return(0,u.default)(t,e.getSystem())})}),(0,r.default)(t,a.NEW_AUTH_ERR,function(t,n){var r=n.payload,a=(0,i.fromJS)((0,o.default)({},r));return a=a.set("type","auth"),t.update("errors",function(e){return(e||(0,i.List)()).push((0,i.fromJS)(a))}).update("errors",function(t){return(0,u.default)(t,e.getSystem())})}),(0,r.default)(t,a.CLEAR,function(e,t){var n=t.payload;if(!n||!e.get("errors"))return e;var r=e.get("errors").filter(function(e){return e.keySeq().every(function(t){var r=e.get(t),o=n[t];return!o||r!==o})});return e.merge({errors:r})}),(0,r.default)(t,a.CLEAR_BY,function(e,t){var n=t.payload;if(!n||"function"!=typeof n)return e;var r=e.get("errors").filter(function(e){return n(e)});return e.merge({errors:r})}),t};var a=n(131),i=n(7),u=s(n(324));function s(e){return e&&e.__esModule?e:{default:e}}var l={line:0,level:"error",message:"Unknown error"}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){var n={jsSpec:t.specSelectors.specJson().toJS()};return(0,a.default)(u,function(e,t){try{var r=t.transform(e,n);return r.filter(function(e){return!!e})}catch(t){return console.error("Transformer error:",t),e}},e).filter(function(e){return!!e}).map(function(e){return!e.get("line")&&e.get("path"),e})};var r,o=n(729),a=(r=o)&&r.__esModule?r:{default:r};function i(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var u=[i(n(325)),i(n(326))]},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.transform=function(e){return e.map(function(e){var t=e.get("message").indexOf("is not of a type(s)");if(t>-1){var n=e.get("message").slice(t+"is not of a type(s)".length).split(",");return e.set("message",e.get("message").slice(0,t)+function(e){return e.reduce(function(e,t,n,r){return n===r.length-1&&r.length>1?e+"or "+t:r[n+1]&&r.length>2?e+t+", ":r[n+1]?e+t+" ":e+t},"should be a")}(n))}return e})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.transform=function(e,t){t.jsSpec;return e};var r,o=n(142);(r=o)&&r.__esModule,n(7)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.lastError=t.allErrors=void 0;var r=n(7),o=n(58),a=t.allErrors=(0,o.createSelector)(function(e){return e},function(e){return e.get("errors",(0,r.List)())});t.lastError=(0,o.createSelector)(a,function(e){return e.last()})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{statePlugins:{layout:{reducers:a.default,actions:i,selectors:u}}}};var r,o=n(329),a=(r=o)&&r.__esModule?r:{default:r},i=s(n(206)),u=s(n(330));function s(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o,a=n(21),i=(r=a)&&r.__esModule?r:{default:r},u=n(7),s=n(206);t.default=(o={},(0,i.default)(o,s.UPDATE_LAYOUT,function(e,t){return e.set("layout",t.payload)}),(0,i.default)(o,s.UPDATE_FILTER,function(e,t){return e.set("filter",t.payload)}),(0,i.default)(o,s.SHOW,function(e,t){var n=t.payload.shown,r=(0,u.fromJS)(t.payload.thing);return e.update("shown",(0,u.fromJS)({}),function(e){return e.set(r,n)})}),(0,i.default)(o,s.UPDATE_MODE,function(e,t){var n=t.payload.thing,r=t.payload.mode;return e.setIn(["modes"].concat(n),(r||"")+"")}),o)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.showSummary=t.whatMode=t.isShown=t.currentFilter=t.current=void 0;var r,o=n(69),a=(r=o)&&r.__esModule?r:{default:r},i=n(58),u=n(9),s=n(7);t.current=function(e){return e.get("layout")},t.currentFilter=function(e){return e.get("filter")};var l=t.isShown=function(e,t,n){return t=(0,u.normalizeArray)(t),e.get("shown",(0,s.fromJS)({})).get((0,s.fromJS)(t),n)};t.whatMode=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return t=(0,u.normalizeArray)(t),e.getIn(["modes"].concat((0,a.default)(t)),n)},t.showSummary=(0,i.createSelector)(function(e){return e},function(e){return!l(e,"editor")})},function(e,t,n){var r=n(36);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){var a=e.return;throw void 0!==a&&r(a.call(e)),t}}},function(e,t,n){var r=n(72),o=n(20)("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(r.Array===e||a[o]===e)}},function(e,t,n){var r=n(20)("iterator"),o=!1;try{var a=[7][r]();a.return=function(){o=!0},Array.from(a,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var a=[7],i=a[r]();i.next=function(){return{done:n=!0}},a[r]=function(){return i},e(a)}catch(e){}return n}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{statePlugins:{spec:{wrapActions:s,reducers:a.default,actions:i,selectors:u}}}};var r,o=n(335),a=(r=o)&&r.__esModule?r:{default:r},i=l(n(207)),u=l(n(148)),s=l(n(349));function l(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o=p(n(21)),a=p(n(23)),i=p(n(69)),u=n(7),s=n(9),l=p(n(32)),c=n(148),f=n(207);function p(e){return e&&e.__esModule?e:{default:e}}t.default=(r={},(0,o.default)(r,f.UPDATE_SPEC,function(e,t){return"string"==typeof t.payload?e.set("spec",t.payload):e}),(0,o.default)(r,f.UPDATE_URL,function(e,t){return e.set("url",t.payload+"")}),(0,o.default)(r,f.UPDATE_JSON,function(e,t){return e.set("json",(0,s.fromJSOrdered)(t.payload))}),(0,o.default)(r,f.UPDATE_RESOLVED,function(e,t){return e.setIn(["resolved"],(0,s.fromJSOrdered)(t.payload))}),(0,o.default)(r,f.UPDATE_RESOLVED_SUBTREE,function(e,t){var n=t.payload,r=n.value,o=n.path;return e.setIn(["resolvedSubtrees"].concat((0,i.default)(o)),(0,s.fromJSOrdered)(r))}),(0,o.default)(r,f.UPDATE_PARAM,function(e,t){var n=t.payload,r=n.path,o=n.paramName,a=n.paramIn,u=n.param,l=n.value,c=n.isXml,f=u?(0,s.paramToIdentifier)(u):a+"."+o,p=c?"value_xml":"value";return e.setIn(["meta","paths"].concat((0,i.default)(r),["parameters",f,p]),l)}),(0,o.default)(r,f.UPDATE_EMPTY_PARAM_INCLUSION,function(e,t){var n=t.payload,r=n.pathMethod,o=n.paramName,a=n.paramIn,u=n.includeEmptyValue;if(!o||!a)return console.warn("Warning: UPDATE_EMPTY_PARAM_INCLUSION could not generate a paramKey."),e;var s=a+"."+o;return e.setIn(["meta","paths"].concat((0,i.default)(r),["parameter_inclusions",s]),u)}),(0,o.default)(r,f.VALIDATE_PARAMS,function(e,t){var n=t.payload,r=n.pathMethod,o=n.isOAS3,a=(0,c.specJsonWithResolvedSubtrees)(e).getIn(["paths"].concat((0,i.default)(r))),l=(0,c.parameterValues)(e,r).toJS();return e.updateIn(["meta","paths"].concat((0,i.default)(r),["parameters"]),(0,u.fromJS)({}),function(t){return a.get("parameters",(0,u.List)()).reduce(function(t,n){var a=(0,s.paramToValue)(n,l),i=(0,c.parameterInclusionSettingFor)(e,r,n.get("name"),n.get("in")),f=(0,s.validateParam)(n,a,{bypassRequiredCheck:i,isOAS3:o});return t.setIn([(0,s.paramToIdentifier)(n),"errors"],(0,u.fromJS)(f))},t)})}),(0,o.default)(r,f.CLEAR_VALIDATE_PARAMS,function(e,t){var n=t.payload.pathMethod;return e.updateIn(["meta","paths"].concat((0,i.default)(n),["parameters"]),(0,u.fromJS)([]),function(e){return e.map(function(e){return e.set("errors",(0,u.fromJS)([]))})})}),(0,o.default)(r,f.SET_RESPONSE,function(e,t){var n=t.payload,r=n.res,o=n.path,i=n.method,u=void 0;(u=r.error?(0,a.default)({error:!0,name:r.err.name,message:r.err.message,statusCode:r.err.statusCode},r.err.response):r).headers=u.headers||{};var c=e.setIn(["responses",o,i],(0,s.fromJSOrdered)(u));return l.default.Blob&&r.data instanceof l.default.Blob&&(c=c.setIn(["responses",o,i,"text"],r.data)),c}),(0,o.default)(r,f.SET_REQUEST,function(e,t){var n=t.payload,r=n.req,o=n.path,a=n.method;return e.setIn(["requests",o,a],(0,s.fromJSOrdered)(r))}),(0,o.default)(r,f.SET_MUTATED_REQUEST,function(e,t){var n=t.payload,r=n.req,o=n.path,a=n.method;return e.setIn(["mutatedRequests",o,a],(0,s.fromJSOrdered)(r))}),(0,o.default)(r,f.UPDATE_OPERATION_META_VALUE,function(e,t){var n=t.payload,r=n.path,o=n.value,a=n.key,s=["paths"].concat((0,i.default)(r)),l=["meta","paths"].concat((0,i.default)(r));return e.getIn(["json"].concat((0,i.default)(s)))||e.getIn(["resolved"].concat((0,i.default)(s)))||e.getIn(["resolvedSubtrees"].concat((0,i.default)(s)))?e.setIn([].concat((0,i.default)(l),[a]),(0,u.fromJS)(o)):e}),(0,o.default)(r,f.CLEAR_RESPONSE,function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["responses",r,o])}),(0,o.default)(r,f.CLEAR_REQUEST,function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["requests",r,o])}),(0,o.default)(r,f.SET_SCHEME,function(e,t){var n=t.payload,r=n.scheme,o=n.path,a=n.method;return o&&a?e.setIn(["scheme",o,a],r):o||a?void 0:e.setIn(["scheme","_defaultScheme"],r)}),r)},function(e,t,n){var r=n(36),o=n(96),a=n(20)("species");e.exports=function(e,t){var n,i=r(e).constructor;return void 0===i||void 0==(n=r(i)[a])?t:o(n)}},function(e,t,n){var r,o,a,i=n(45),u=n(737),s=n(243),l=n(164),c=n(22),f=c.process,p=c.setImmediate,d=c.clearImmediate,h=c.MessageChannel,v=c.Dispatch,m=0,g={},y=function(){var e=+this;if(g.hasOwnProperty(e)){var t=g[e];delete g[e],t()}},b=function(e){y.call(e.data)};p&&d||(p=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return g[++m]=function(){u("function"==typeof e?e:Function(e),t)},r(m),m},d=function(e){delete g[e]},"process"==n(95)(f)?r=function(e){f.nextTick(i(y,e,1))}:v&&v.now?r=function(e){v.now(i(y,e,1))}:h?(a=(o=new h).port2,o.port1.onmessage=b,r=i(a.postMessage,a,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(r=function(e){c.postMessage(e+"","*")},c.addEventListener("message",b,!1)):r="onreadystatechange"in l("script")?function(e){s.appendChild(l("script")).onreadystatechange=function(){s.removeChild(this),y.call(e)}}:function(e){setTimeout(i(y,e,1),0)}),e.exports={set:p,clear:d}},function(e,t){e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,n){var r=n(36),o=n(28),a=n(209);e.exports=function(e,t){if(r(e),o(t)&&t.constructor===e)return t;var n=a.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){"use strict";var r=n(22),o=n(14),a=n(35),i=n(41),u=n(20)("species");e.exports=function(e){var t="function"==typeof o[e]?o[e]:r[e];i&&t&&!t[u]&&a.f(t,u,{configurable:!0,get:function(){return this}})}},function(e,t,n){e.exports=n(741)},function(e,t,n){"use strict";t.__esModule=!0;var r,o=n(208),a=(r=o)&&r.__esModule?r:{default:r};t.default=function(e){return function(){var t=e.apply(this,arguments);return new a.default(function(e,n){return function r(o,i){try{var u=t[o](i),s=u.value}catch(e){return void n(e)}if(!u.done)return a.default.resolve(s).then(function(e){r("next",e)},function(e){r("throw",e)});e(s)}("next")})}}},function(e,t,n){"use strict";var r=n(89);e.exports=new r({include:[n(344)]})},function(e,t,n){"use strict";var r=n(89);e.exports=new r({include:[n(211)],implicit:[n(749),n(750),n(751),n(752)]})},function(e,t,n){var r=n(62),o=n(24),a=n(48),i="[object String]";e.exports=function(e){return"string"==typeof e||!o(e)&&a(e)&&r(e)==i}},function(e,t,n){var r=n(152),o=n(82),a=n(139),i=n(38),u=n(83);e.exports=function(e,t,n,s){if(!i(e))return e;for(var l=-1,c=(t=o(t,e)).length,f=c-1,p=e;null!=p&&++l.":"function"==typeof t?" Instead of passing a class like Foo, pass React.createElement(Foo) or .":null!=t&&void 0!==t.props?" This may be caused by unintentionally loading two independent copies of React.":"");var a,u=i.createElement(D,{child:t});if(e){var s=p.get(e);a=s._processChildContext(s._context)}else a=g;var l=N(n);if(l){var c=l._currentElement.props.child;if(_(c,t)){var f=l._renderedComponent.getPublicInstance(),d=o&&function(){o.call(f)};return L._updateRootComponent(l,u,a,n,d),f}L.unmountComponentAtNode(n)}var h=A(n),m=h&&!!O(h),y=I(n),b=m&&!l&&!y,w=L._renderNewRootComponent(u,n,b,a)._renderedComponent.getPublicInstance();return o&&o.call(w),w},render:function(e,t,n){return L._renderSubtreeIntoContainer(null,e,t,n)},unmountComponentAtNode:function(e){j(e)||r("40");var t=N(e);if(!t){I(e),1===e.nodeType&&e.hasAttribute(E);return!1}return delete k[t._instance.rootID],m.batchedUpdates(T,t,e,!1),!0},_mountImageIntoNode:function(e,t,n,a,i){if(j(t)||r("41"),a){var u=A(t);if(d.canReuseMarkup(e,u))return void s.precacheNode(n,u);var l=u.getAttribute(d.CHECKSUM_ATTR_NAME);u.removeAttribute(d.CHECKSUM_ATTR_NAME);var c=u.outerHTML;u.setAttribute(d.CHECKSUM_ATTR_NAME,l);var f=e,p=function(e,t){for(var n=Math.min(e.length,t.length),r=0;r1?r-1:0),i=1;i=o&&(t=console)[e].apply(t,a)}return a.warn=a.bind(null,"warn"),a.error=a.bind(null,"error"),a.info=a.bind(null,"info"),a.debug=a.bind(null,"debug"),{rootInjects:{log:a}}}},function(e,t,n){"use strict";var r,o=n(390),a=(r=o)&&r.__esModule?r:{default:r},i=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(n(397));e.exports=function(e){var t=e.configs,n=e.getConfigs;return{fn:{fetch:a.default.makeHttp(t.preFetch,t.postFetch),buildRequest:a.default.buildRequest,execute:a.default.execute,resolve:a.default.resolve,resolveSubtree:function(e,t,r){for(var o=arguments.length,i=Array(o>3?o-3:0),u=3;u2&&void 0!==arguments[2]?arguments[2]:"",r=(arguments.length>3&&void 0!==arguments[3]?arguments[3]:{}).v2OperationIdCompatibilityMode;return e&&"object"===(void 0===e?"undefined":(0,c.default)(e))?(e.operationId||"").replace(/\s/g,"").length?h(e.operationId):a(t,n,{v2OperationIdCompatibilityMode:r}):null}function a(e,t){if((arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).v2OperationIdCompatibilityMode){var n=(t.toLowerCase()+"_"+e).replace(/[\s!@#$%^&*()_+=[{\]};:<>|.\/?,\\'""-]/g,"_");return(n=n||e.substring(1)+"_"+t).replace(/((_){2,})/g,"_").replace(/^(_)*/g,"").replace(/([_])*$/g,"")}return""+d(t)+h(e)}function i(e,t){return d(t)+"-"+e}function u(e,t){return s(e,t,!0)||null}function s(e,t,n){if(!e||"object"!==(void 0===e?"undefined":(0,c.default)(e))||!e.paths||"object"!==(0,c.default)(e.paths))return null;var r=e.paths;for(var o in r)for(var a in r[o])if("PARAMETERS"!==a.toUpperCase()){var i=r[o][a];if(i&&"object"===(void 0===i?"undefined":(0,c.default)(i))){var u={spec:e,pathName:o,method:a.toUpperCase(),operation:i},s=t(u);if(n&&s)return u}}}Object.defineProperty(t,"__esModule",{value:!0});var l=r(n(20)),c=r(n(1));t.isOAS3=function(e){var t=e.openapi;return!!t&&(0,p.default)(t,"3")},t.isSwagger2=function(e){var t=e.swagger;return!!t&&(0,p.default)(t,"2")},t.opId=o,t.idFromPathMethod=a,t.legacyIdFromPathMethod=i,t.getOperationRaw=function(e,t){return e&&e.paths?u(e,function(e){var n=e.pathName,r=e.method,a=e.operation;if(!a||"object"!==(void 0===a?"undefined":(0,c.default)(a)))return!1;var u=a.operationId;return[o(a,n,r),i(n,r),u].some(function(e){return e&&e===t})}):null},t.findOperation=u,t.eachOperation=s,t.normalizeSwagger=function(e){var t=e.spec,n=t.paths,r={};if(!n||t.$$normalized)return e;for(var a in n){var i=n[a];if((0,f.default)(i)){var u=i.parameters;for(var s in i)!function(e){var n=i[e];if(!(0,f.default)(n))return"continue";var s=o(n,a,e);if(s){r[s]?r[s].push(n):r[s]=[n];var c=r[s];if(c.length>1)c.forEach(function(e,t){e.__originalOperationId=e.__originalOperationId||e.operationId,e.operationId=""+s+(t+1)});else if(void 0!==n.operationId){var p=c[0];p.__originalOperationId=p.__originalOperationId||n.operationId,p.operationId=s}}if("parameters"!==e){var d=[],h={};for(var v in t)"produces"!==v&&"consumes"!==v&&"security"!==v||(h[v]=t[v],d.push(h));if(u&&(h.parameters=u,d.push(h)),d.length){var m=!0,g=!1,y=void 0;try{for(var b,_=(0,l.default)(d);!(m=(b=_.next()).done);m=!0){var w=b.value;for(var E in w)if(n[E]){if("parameters"===E){var x=!0,S=!1,C=void 0;try{for(var k,A=(0,l.default)(w[E]);!(x=(k=A.next()).done);x=!0)!function(){var e=k.value;n[E].some(function(t){return t.name&&t.name===e.name||t.$ref&&t.$ref===e.$ref||t.$$ref&&t.$$ref===e.$$ref||t===e})||n[E].push(e)}()}catch(e){S=!0,C=e}finally{try{!x&&A.return&&A.return()}finally{if(S)throw C}}}}else n[E]=w[E]}}catch(e){g=!0,y=e}finally{try{!m&&_.return&&_.return()}finally{if(g)throw y}}}}}(s)}}return t.$$normalized=!0,e};var f=r(n(48)),p=r(n(15)),d=function(e){return String.prototype.toLowerCase.call(e)},h=function(e){return e.replace(/[^\w]/gi,"_")}},function(e,t){e.exports=n(894)},function(e,t){e.exports=n(897)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).loadSpec,r=void 0!==n&&n,o={ok:e.ok,url:e.url||t,status:e.status,statusText:e.statusText,headers:a(e.headers)},i=o.headers["content-type"],u=r||_(i);return(u?e.text:e.blob||e.buffer).call(e).then(function(e){if(o.text=e,o.data=e,u)try{var t=function(e,t){return t&&(0===t.indexOf("application/json")||t.indexOf("+json")>0)?JSON.parse(e):g.default.safeLoad(e)}(e,i);o.body=t,o.obj=t}catch(e){o.parseError=e}return o})}function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t={};return"function"==typeof e.forEach?(e.forEach(function(e,n){void 0!==t[n]?(t[n]=Array.isArray(t[n])?t[n]:[t[n]],t[n].push(e)):t[n]=e}),t):t}function i(e,t){return t||"undefined"==typeof navigator||(t=navigator),t&&"ReactNative"===t.product?!(!e||"object"!==(void 0===e?"undefined":(0,h.default)(e))||"string"!=typeof e.uri):"undefined"!=typeof File?e instanceof File:null!==e&&"object"===(void 0===e?"undefined":(0,h.default)(e))&&"function"==typeof e.pipe}function u(e,t){var n=e.collectionFormat,r=e.allowEmptyValue,o="object"===(void 0===e?"undefined":(0,h.default)(e))?e.value:e;if(void 0===o&&r)return"";if(i(o)||"boolean"==typeof o)return o;var a=encodeURIComponent;return t&&(a=(0,y.default)(o)?function(e){return e}:function(e){return(0,p.default)(e)}),"object"!==(void 0===o?"undefined":(0,h.default)(o))||Array.isArray(o)?Array.isArray(o)?Array.isArray(o)&&!n?o.map(a).join(","):"multi"===n?o.map(a):o.map(a).join({csv:",",ssv:"%20",tsv:"%09",pipes:"|"}[n]):a(o):""}function s(e){var t=(0,f.default)(e).reduce(function(t,n){var r=e[n],o=!!r.skipEncoding,a=o?n:encodeURIComponent(n),i=function(e){return e&&"object"===(void 0===e?"undefined":(0,h.default)(e))}(r)&&!Array.isArray(r);return t[a]=u(i?r:{value:r},o),t},{});return m.default.stringify(t,{encode:!1,indices:!1})||""}function l(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,r=void 0===t?"":t,o=e.query,a=e.form;if(a){var l=(0,f.default)(a).some(function(e){return i(a[e].value)}),p=e.headers["content-type"]||e.headers["Content-Type"];if(l||/multipart\/form-data/i.test(p)){var d=n(31);e.body=new d,(0,f.default)(a).forEach(function(t){e.body.append(t,u(a[t],!0))})}else e.body=s(a);delete e.form}if(o){var h=r.split("?"),v=(0,c.default)(h,2),g=v[0],y=v[1],b="";if(y){var _=m.default.parse(y);(0,f.default)(o).forEach(function(e){return delete _[e]}),b=m.default.stringify(_,{encode:!0})}var w=function(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:{};return d.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if("object"===(void 0===t?"undefined":(0,h.default)(t))&&(t=(i=t).url),i.headers=i.headers||{},b.mergeInQueryOrForm(i),!i.requestInterceptor){e.next=10;break}return e.next=6,i.requestInterceptor(i);case 6:if(e.t0=e.sent,e.t0){e.next=9;break}e.t0=i;case 9:i=e.t0;case 10:return n=i.headers["content-type"]||i.headers["Content-Type"],/multipart\/form-data/i.test(n)&&(delete i.headers["content-type"],delete i.headers["Content-Type"]),r=void 0,e.prev=13,e.next=16,(i.userFetch||fetch)(i.url,i);case 16:return r=e.sent,e.next=19,b.serializeRes(r,t,i);case 19:if(r=e.sent,!i.responseInterceptor){e.next=27;break}return e.next=23,i.responseInterceptor(r);case 23:if(e.t1=e.sent,e.t1){e.next=26;break}e.t1=r;case 26:r=e.t1;case 27:e.next=37;break;case 29:if(e.prev=29,e.t2=e.catch(13),r){e.next=33;break}throw e.t2;case 33:throw(o=new Error(r.statusText)).statusCode=o.status=r.status,o.responseError=e.t2,o;case 37:if(r.ok){e.next=42;break}throw(a=new Error(r.statusText)).statusCode=a.status=r.status,a.response=r,a;case 42:return e.abrupt("return",r);case 43:case"end":return e.stop()}},e,this,[[13,29]])}));return function(t){return e.apply(this,arguments)}}();var _=t.shouldDownloadAsText=function(){return/(json|xml|yaml|text)\b/.test(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"")}},function(e,t){e.exports=n(42)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){return Array.isArray(e)?e.length<1?"":"/"+e.map(function(e){return(e+"").replace(/~/g,"~0").replace(/\//g,"~1")}).join("/"):e}function a(e,t,n){return{op:"replace",path:e,value:t,meta:n}}function i(e,t,n){return f(c(e.filter(m).map(function(e){return t(e.value,n,e.path)})||[]))}function u(e,t,n){return n=n||[],Array.isArray(e)?e.map(function(e,r){return u(e,t,n.concat(r))}):p(e)?(0,w.default)(e).map(function(r){return u(e[r],t,n.concat(r))}):t(e,n[n.length-1],n)}function s(e,t,n){var r=[];if((n=n||[]).length>0){var o=t(e,n[n.length-1],n);o&&(r=r.concat(o))}if(Array.isArray(e)){var a=e.map(function(e,r){return s(e,t,n.concat(r))});a&&(r=r.concat(a))}else if(p(e)){var i=(0,w.default)(e).map(function(r){return s(e[r],t,n.concat(r))});i&&(r=r.concat(i))}return c(r)}function l(e){return Array.isArray(e)?e:[e]}function c(e){var t;return(t=[]).concat.apply(t,(0,_.default)(e.map(function(e){return Array.isArray(e)?c(e):e})))}function f(e){return e.filter(function(e){return void 0!==e})}function p(e){return e&&"object"===(void 0===e?"undefined":(0,b.default)(e))}function d(e){return e&&"function"==typeof e}function h(e){if(g(e)){var t=e.op;return"add"===t||"remove"===t||"replace"===t}return!1}function v(e){return h(e)||g(e)&&"mutation"===e.type}function m(e){return v(e)&&("add"===e.op||"replace"===e.op||"merge"===e.op||"mergeDeep"===e.op)}function g(e){return e&&"object"===(void 0===e?"undefined":(0,b.default)(e))}function y(e,t){try{return S.default.getValueByPointer(e,t)}catch(e){return console.error(e),{}}}Object.defineProperty(t,"__esModule",{value:!0});var b=r(n(1)),_=r(n(12)),w=r(n(0)),E=r(n(35)),x=r(n(2)),S=r(n(36)),C=r(n(4)),k=r(n(37)),A=r(n(38));t.default={add:function(e,t){return{op:"add",path:e,value:t}},replace:a,remove:function(e,t){return{op:"remove",path:e}},merge:function(e,t){return{type:"mutation",op:"merge",path:e,value:t}},mergeDeep:function(e,t){return{type:"mutation",op:"mergeDeep",path:e,value:t}},context:function(e,t){return{type:"context",path:e,value:t}},getIn:function(e,t){return t.reduce(function(e,t){return void 0!==t&&e?e[t]:e},e)},applyPatch:function(e,t,n){if(n=n||{},"merge"===(t=(0,x.default)({},t,{path:t.path&&o(t.path)})).op){var r=y(e,t.path);(0,x.default)(r,t.value),S.default.applyPatch(e,[a(t.path,r)])}else if("mergeDeep"===t.op){var i=y(e,t.path);for(var u in t.value){var s=t.value[u],l=Array.isArray(s);if(l){var c=i[u]||[];i[u]=c.concat(s)}else if(p(s)&&!l){var f=(0,x.default)({},i[u]);for(var d in s){if(Object.prototype.hasOwnProperty.call(f,d)){f=(0,k.default)((0,A.default)({},f),s);break}(0,x.default)(f,(0,E.default)({},d,s[d]))}i[u]=f}else i[u]=s}}else if("add"===t.op&&""===t.path&&p(t.value)){var h=(0,w.default)(t.value).reduce(function(e,n){return e.push({op:"add",path:"/"+o(n),value:t.value[n]}),e},[]);S.default.applyPatch(e,h)}else if("replace"===t.op&&""===t.path){var v=t.value;n.allowMetaPatches&&t.meta&&m(t)&&(Array.isArray(t.value)||p(t.value))&&(v=(0,x.default)({},v,t.meta)),e=v}else if(S.default.applyPatch(e,[t]),n.allowMetaPatches&&t.meta&&m(t)&&(Array.isArray(t.value)||p(t.value))){var g=y(e,t.path),b=(0,x.default)({},g,t.meta);S.default.applyPatch(e,[a(t.path,b)])}return e},parentPathMatch:function(e,t){if(!Array.isArray(t))return!1;for(var n=0,r=t.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=t.requestInterceptor,r=t.responseInterceptor,o=e.withCredentials?"include":"same-origin";return function(t){return e({url:t,loadSpec:!0,requestInterceptor:n,responseInterceptor:r,headers:{Accept:"application/json"},credentials:o}).then(function(e){return e.body})}}Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(4)),i=r(n(11));t.makeFetchJSON=o,t.clearCache=function(){s.plugins.refs.clearCache()},t.default=function(e){function t(e){var t=this;x&&(s.plugins.refs.docCache[x]=e),s.plugins.refs.fetchJSON=o(E,{requestInterceptor:y,responseInterceptor:b});var n=[s.plugins.refs];return"function"==typeof g&&n.push(s.plugins.parameters),"function"==typeof m&&n.push(s.plugins.properties),"strict"!==p&&n.push(s.plugins.allOf),(0,l.default)({spec:e,context:{baseDoc:x},plugins:n,allowMetaPatches:h,pathDiscriminator:v,parameterMacro:g,modelPropertyMacro:m,useCircularStructures:w}).then(_?function(){var e=(0,i.default)(a.default.mark(function e(n){return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",n);case 1:case"end":return e.stop()}},e,t)}));return function(t){return e.apply(this,arguments)}}():c.normalizeSwagger)}var n=e.fetch,r=e.spec,f=e.url,p=e.mode,d=e.allowMetaPatches,h=void 0===d||d,v=e.pathDiscriminator,m=e.modelPropertyMacro,g=e.parameterMacro,y=e.requestInterceptor,b=e.responseInterceptor,_=e.skipNormalization,w=e.useCircularStructures,E=e.http,x=e.baseDoc;return x=x||f,E=n||E||u.default,r?t(r):o(E,{requestInterceptor:y,responseInterceptor:b})(x).then(t)};var u=r(n(8)),s=n(32),l=r(s),c=n(5)},function(e,t){e.exports=n(208)},function(e,t){e.exports=n(94)},function(e,t){e.exports=n(2)},function(e,t){e.exports=n(3)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){function n(){Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack;for(var e=arguments.length,n=Array(e),r=0;r-1&&-1===c.indexOf(n)||f.indexOf(r)>-1||p.some(function(e){return r.indexOf(e)>-1})},t.generateAbsoluteRefPatches=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.specmap,a=n.getBaseUrlForNodePath,s=void 0===a?function(e){return r.getContext([].concat((0,i.default)(t),(0,i.default)(e))).baseDoc}:a,l=n.targetKeys,c=void 0===l?["$ref","$$ref"]:l,f=[];return(0,u.default)(e).forEach(function(){if(c.indexOf(this.key)>-1){var e=this.path,n=t.concat(this.path),a=o(this.node,s(e));f.push(r.replace(n,a))}}),f},t.absolutifyPointer=o;var u=r(n(43)),s=r(n(7)),l=["properties"],c=["properties"],f=["definitions","parameters","responses","securityDefinitions","components/schemas","components/responses","components/parameters","components/securitySchemes"],p=["schema/example","items/example"]},function(e,t,n){e.exports=n(26)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if("string"==typeof e?n.url=e:n=e,!(this instanceof o))return new o(n);(0,i.default)(this,n);var r=this.resolve().then(function(){return t.disableInterfaces||(0,i.default)(t,o.makeApisTagOperation(t)),t});return r.client=this,r}Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(3)),i=r((r(n(27)),n(6))),u=r(n(15)),s=r(n(7)),l=n(8),c=r(l),f=n(18),p=r(f),d=r(n(49)),h=n(50),v=n(52),m=n(5);o.http=c.default,o.makeHttp=l.makeHttp.bind(null,o.http),o.resolve=p.default,o.resolveSubtree=d.default,o.execute=v.execute,o.serializeRes=l.serializeRes,o.serializeHeaders=l.serializeHeaders,o.clearCache=f.clearCache,o.parameterBuilders=v.PARAMETER_BUILDERS,o.makeApisTagOperation=h.makeApisTagOperation,o.buildRequest=v.buildRequest,o.helpers={opId:m.opId},o.prototype={http:c.default,execute:function(e){return this.applyDefaults(),o.execute((0,a.default)({spec:this.spec,http:this.http,securities:{authorized:this.authorizations},contextUrl:"string"==typeof this.url?this.url:void 0},e))},resolve:function(){var e=this;return o.resolve({spec:this.spec,url:this.url,allowMetaPatches:this.allowMetaPatches,useCircularStructures:this.useCircularStructures,requestInterceptor:this.requestInterceptor||null,responseInterceptor:this.responseInterceptor||null}).then(function(t){return e.originalSpec=e.spec,e.spec=t.spec,e.errors=t.errors,e})}},o.prototype.applyDefaults=function(){var e=this.spec,t=this.url;if(t&&(0,u.default)(t,"http")){var n=s.default.parse(t);e.host||(e.host=n.host),e.schemes||(e.schemes=[n.protocol.replace(":","")]),e.basePath||(e.basePath="/")}},t.default=o,e.exports=t.default},function(e,t){e.exports=n(906)},function(e,t){e.exports=n(907)},function(e,t){e.exports=n(908)},function(e,t){e.exports=n(345)},function(e,t){e.exports=n(911)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.plugins=t.SpecMap=void 0;var o=r(n(9)),a=r(n(1)),i=r(n(19)),u=r(n(4)),s=r(n(0)),l=r(n(20)),c=r(n(33)),f=r(n(2)),p=r(n(21)),d=r(n(22));t.default=function(e){return new w(e).dispatch()};var h=r(n(34)),v=r(n(10)),m=r(n(39)),g=r(n(44)),y=r(n(45)),b=r(n(46)),_=r(n(47)),w=function(){function e(t){var n=this;(0,p.default)(this,e),(0,f.default)(this,{spec:"",debugLevel:"info",plugins:[],pluginHistory:{},errors:[],mutations:[],promisedPatches:[],state:{},patches:[],context:{},contextTree:new _.default,showDebug:!1,allPatches:[],pluginProp:"specMap",libMethods:(0,f.default)((0,c.default)(this),v.default,{getInstance:function(){return n}}),allowMetaPatches:!1},t),this.get=this._get.bind(this),this.getContext=this._getContext.bind(this),this.hasRun=this._hasRun.bind(this),this.wrappedPlugins=this.plugins.map(this.wrapPlugin.bind(this)).filter(v.default.isFunction),this.patches.push(v.default.add([],this.spec)),this.patches.push(v.default.context([],this.context)),this.updatePatches(this.patches)}return(0,d.default)(e,[{key:"debug",value:function(e){if(this.debugLevel===e){for(var t,n=arguments.length,r=Array(n>1?n-1:0),o=1;o1?n-1:0),o=1;o0})}},{key:"nextPromisedPatch",value:function(){if(this.promisedPatches.length>0)return i.default.race(this.promisedPatches.map(function(e){return e.value}))}},{key:"getPluginHistory",value:function(e){var t=this.getPluginName(e);return this.pluginHistory[t]||[]}},{key:"getPluginRunCount",value:function(e){return this.getPluginHistory(e).length}},{key:"getPluginHistoryTip",value:function(e){var t=this.getPluginHistory(e);return t&&t[t.length-1]||{}}},{key:"getPluginMutationIndex",value:function(e){var t=this.getPluginHistoryTip(e).mutationIndex;return"number"!=typeof t?-1:t}},{key:"getPluginName",value:function(e){return e.pluginName}},{key:"updatePluginHistory",value:function(e,t){var n=this.getPluginName(e);(this.pluginHistory[n]=this.pluginHistory[n]||[]).push(t)}},{key:"updatePatches",value:function(e,t){var n=this;v.default.normalizeArray(e).forEach(function(e){if(e instanceof Error)n.errors.push(e);else try{if(!v.default.isObject(e))return void n.debug("updatePatches","Got a non-object patch",e);if(n.showDebug&&n.allPatches.push(e),v.default.isPromise(e.value))return n.promisedPatches.push(e),void n.promisedPatchThen(e);if(v.default.isContextPatch(e))return void n.setContext(e.path,e.value);if(v.default.isMutation(e))return void n.updateMutations(e)}catch(e){console.error(e),n.errors.push(e)}})}},{key:"updateMutations",value:function(e){"object"===(0,a.default)(e.value)&&!Array.isArray(e.value)&&this.allowMetaPatches&&(e.value=(0,f.default)({},e.value));var t=v.default.applyPatch(this.state,e,{allowMetaPatches:this.allowMetaPatches});t&&(this.mutations.push(e),this.state=t)}},{key:"removePromisedPatch",value:function(e){var t=this.promisedPatches.indexOf(e);t<0?this.debug("Tried to remove a promisedPatch that isn't there!"):this.promisedPatches.splice(t,1)}},{key:"promisedPatchThen",value:function(e){var t=this;return e.value=e.value.then(function(n){var r=(0,f.default)({},e,{value:n});t.removePromisedPatch(e),t.updatePatches(r)}).catch(function(n){t.removePromisedPatch(e),t.updatePatches(n)})}},{key:"getMutations",value:function(e,t){return e=e||0,"number"!=typeof t&&(t=this.mutations.length),this.mutations.slice(e,t)}},{key:"getCurrentMutations",value:function(){return this.getMutationsForPlugin(this.getCurrentPlugin())}},{key:"getMutationsForPlugin",value:function(e){var t=this.getPluginMutationIndex(e);return this.getMutations(t+1)}},{key:"getCurrentPlugin",value:function(){return this.currentPlugin}},{key:"getPatchesOfType",value:function(e,t){return e.filter(t)}},{key:"getLib",value:function(){return this.libMethods}},{key:"_get",value:function(e){return v.default.getIn(this.state,e)}},{key:"_getContext",value:function(e){return this.contextTree.get(e)}},{key:"setContext",value:function(e,t){return this.contextTree.set(e,t)}},{key:"_hasRun",value:function(e){return this.getPluginRunCount(this.getCurrentPlugin())>(e||0)}},{key:"_clone",value:function(e){return JSON.parse((0,o.default)(e))}},{key:"dispatch",value:function(){function e(e){e&&(e=v.default.fullyNormalizeArray(e),n.updatePatches(e,r))}var t=this,n=this,r=this.nextPlugin();if(!r){var o=this.nextPromisedPatch();if(o)return o.then(function(){return t.dispatch()}).catch(function(){return t.dispatch()});var a={spec:this.state,errors:this.errors};return this.showDebug&&(a.patches=this.allPatches),i.default.resolve(a)}if(n.pluginCount=n.pluginCount||{},n.pluginCount[r]=(n.pluginCount[r]||0)+1,n.pluginCount[r]>100)return i.default.resolve({spec:n.state,errors:n.errors.concat(new Error("We've reached a hard limit of 100 plugin runs"))});if(r!==this.currentPlugin&&this.promisedPatches.length){var u=this.promisedPatches.map(function(e){return e.value});return i.default.all(u.map(function(e){return e.then(Function,Function)})).then(function(){return t.dispatch()})}return function(){n.currentPlugin=r;var t=n.getCurrentMutations(),o=n.mutations.length-1;try{if(r.isGenerator){var a=!0,i=!1,u=void 0;try{for(var s,p=(0,l.default)(r(t,n.getLib()));!(a=(s=p.next()).done);a=!0)e(s.value)}catch(e){i=!0,u=e}finally{try{!a&&p.return&&p.return()}finally{if(i)throw u}}}else e(r(t,n.getLib()))}catch(t){console.error(t),e([(0,f.default)((0,c.default)(t),{plugin:r})])}finally{n.updatePluginHistory(r,{mutationIndex:o})}return n.dispatch()}()}}]),e}(),E={refs:m.default,allOf:g.default,parameters:y.default,properties:b.default};t.SpecMap=w,t.plugins=E},function(e,t){e.exports=n(352)},function(e,t){e.exports=n(290)},function(e,t){e.exports=n(21)},function(e,t){e.exports=n(912)},function(e,t){e.exports=n(183)},function(e,t){e.exports=n(185)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!O.test(e)){if(!t)throw new P("Tried to resolve a relative URL, without having a basePath. path: '"+e+"' basePath: '"+t+"'");return S.default.resolve(t,e)}return e}function a(e,t){var n;return n=e&&e.response&&e.response.body?e.response.body.code+" "+e.response.body.message:e.message,new P("Could not resolve reference: "+n,t,e)}function i(e){return(e+"").split("#")}function u(e,t){var n=M[e];if(n&&!C.default.isPromise(n))try{var r=l(t,n);return(0,_.default)(y.default.resolve(r),{__value:r})}catch(e){return y.default.reject(e)}return s(e).then(function(e){return l(t,e)})}function s(e){var t=M[e];return t?C.default.isPromise(t)?t:y.default.resolve(t):(M[e]=j.fetchJSON(e).then(function(t){return M[e]=t,t}),M[e])}function l(e,t){var n=c(e);if(n.length<1)return t;var r=C.default.getIn(t,n);if(void 0===r)throw new P("Could not resolve pointer: "+e+" does not exist in document",{pointer:e});return r}function c(e){if("string"!=typeof e)throw new TypeError("Expected a string, got a "+(void 0===e?"undefined":(0,m.default)(e)));return"/"===e[0]&&(e=e.substr(1)),""===e?[]:e.split("/").map(f)}function f(e){return"string"!=typeof e?e:x.default.unescape(e.replace(/~1/g,"/").replace(/~0/g,"~"))}function p(e){return x.default.escape(e.replace(/~/g,"~0").replace(/\//g,"~1"))}function d(e,t){if(N(t))return!0;var n=e.charAt(t.length),r=t.slice(-1);return 0===e.indexOf(t)&&(!n||"/"===n||"#"===n)&&"#"!==r}function h(e,t,n,r){var o=T.get(r);o||(o={},T.set(r,o));var a=function(e){return 0===e.length?"":"/"+e.map(p).join("/")}(n),i=(t||"")+"#"+e,u=a.replace(/allOf\/\d+\/?/g,"");if(t==r.contextTree.get([]).baseDoc&&d(u,e))return!0;var s="";if(n.some(function(e){return s=s+"/"+p(e),o[s]&&o[s].some(function(e){return d(e,i)||d(i,e)})}))return!0;o[u]=(o[u]||[]).concat(i)}function v(e,t){var n=[e];return t.path.reduce(function(e,t){return n.push(e[t]),e[t]},e),function e(t){return C.default.isObject(t)&&(n.indexOf(t)>=0||(0,g.default)(t).some(function(n){return e(t[n])}))}(t.value)}Object.defineProperty(t,"__esModule",{value:!0});var m=r(n(1)),g=r(n(0)),y=r(n(19)),b=r(n(40)),_=r(n(2)),w=n(41),E=r(n(17)),x=r(n(42)),S=r(n(7)),C=r(n(10)),k=r(n(23)),A=n(24),O=new RegExp("^([a-z]+://|//)","i"),P=(0,k.default)("JSONRefError",function(e,t,n){this.originalError=n,(0,_.default)(this,t||{})}),M={},T=new b.default,I={key:"$ref",plugin:function(e,t,n,r){var s=r.getInstance(),l=n.slice(0,-1);if(!(0,A.isFreelyNamed)(l)){var f=r.getContext(n).baseDoc;if("string"!=typeof e)return new P("$ref: must be a string (JSON-Ref)",{$ref:e,baseDoc:f,fullPath:n});var p=i(e),d=p[0],m=p[1]||"",g=void 0;try{g=f||d?o(d,f):null}catch(t){return a(t,{pointer:m,$ref:e,basePath:g,fullPath:n})}var y=void 0,b=void 0;if(h(m,g,l,r)&&!s.useCircularStructures){var _=(0,A.absolutifyPointer)(e,g);return e===_?null:C.default.replace(n,_)}if(null==g?(b=c(m),void 0===(y=r.get(b))&&(y=new P("Could not resolve reference: "+e,{pointer:m,$ref:e,baseDoc:f,fullPath:n}))):y=null!=(y=u(g,m)).__value?y.__value:y.catch(function(t){throw a(t,{pointer:m,$ref:e,baseDoc:f,fullPath:n})}),y instanceof Error)return[C.default.remove(n),y];var w=(0,A.absolutifyPointer)(e,g),E=C.default.replace(l,y,{$$ref:w});if(g&&g!==f)return[E,C.default.context(l,{baseDoc:g})];try{if(!v(r.state,E)||s.useCircularStructures)return E}catch(e){return null}}}},j=(0,_.default)(I,{docCache:M,absoluteify:o,clearCache:function(e){void 0!==e?delete M[e]:(0,g.default)(M).forEach(function(e){delete M[e]})},JSONRefError:P,wrapError:a,getDoc:s,split:i,extractFromDoc:u,fetchJSON:function(e){return(0,w.fetch)(e,{headers:{Accept:"application/json, application/yaml"},loadSpec:!0}).then(function(e){return e.text()}).then(function(e){return E.default.safeLoad(e)})},extract:l,jsonPointerToArray:c,unescapeJsonPointerToken:f});t.default=j;var N=function(e){return!e||"/"===e||"#"===e};e.exports=t.default},function(e,t){e.exports=n(916)},function(e,t){e.exports=n(924)},function(e,t){e.exports=n(925)},function(e,t){e.exports=n(926)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(12)),a=r(n(2)),i=n(24);t.default={key:"allOf",plugin:function(e,t,n,r,u){if(!u.meta||!u.meta.$$ref){var s=n.slice(0,-1);if(!(0,i.isFreelyNamed)(s)){if(!Array.isArray(e)){var l=new TypeError("allOf must be an array");return l.fullPath=n,l}var c=!1,f=u.value;s.forEach(function(e){f&&(f=f[e])}),delete(f=(0,a.default)({},f)).allOf;var p=[];return p.push(r.replace(s,{})),e.forEach(function(e,t){if(!r.isObject(e)){if(c)return null;c=!0;var a=new TypeError("Elements in allOf must be objects");return a.fullPath=n,p.push(a)}p.push(r.mergeDeep(s,e));var u=n.slice(0,-1),l=(0,i.generateAbsoluteRefPatches)(e,u,{getBaseUrlForNodePath:function(e){return r.getContext([].concat((0,o.default)(n),[t],(0,o.default)(e))).baseDoc},specmap:r});p.push.apply(p,(0,o.default)(l))}),p.push(r.mergeDeep(s,f)),f.$$ref||p.push(r.remove([].concat(s,"$$ref"))),p}}}},e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(2)),a=r(n(10));t.default={key:"parameters",plugin:function(e,t,n,r,i){if(Array.isArray(e)&&e.length){var u=(0,o.default)([],e),s=n.slice(0,-1),l=(0,o.default)({},a.default.getIn(r.spec,s));return e.forEach(function(e,t){try{u[t].default=r.parameterMacro(l,e)}catch(e){var o=new Error(e);return o.fullPath=n,o}}),a.default.replace(n,u)}return a.default.replace(n,e)}},e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(2)),a=r(n(10));t.default={key:"properties",plugin:function(e,t,n,r){var i=(0,o.default)({},e);for(var u in e)try{i[u].default=r.modelPropertyMacro(i[u])}catch(e){var s=new Error(e);return s.fullPath=n,s}return a.default.replace(n,i)}},e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){return a({children:{}},e,t)}function a(e,t,n){return e.value=t||{},e.protoValue=n?(0,u.default)({},n.protoValue,e.value):e.value,(0,i.default)(e.children).forEach(function(t){var n=e.children[t];e.children[t]=a(n,n.value,e)}),e}Object.defineProperty(t,"__esModule",{value:!0});var i=r(n(0)),u=r(n(3)),s=r(n(21)),l=r(n(22)),c=function(){function e(t){(0,s.default)(this,e),this.root=o(t||{})}return(0,l.default)(e,[{key:"set",value:function(e,t){var n=this.getParent(e,!0);if(n){var r=e[e.length-1],i=n.children;i[r]?a(i[r],t,n):i[r]=o(t,n)}else a(this.root,t,null)}},{key:"get",value:function(e){if((e=e||[]).length<1)return this.root.value;for(var t=this.root,n=void 0,r=void 0,o=0;o2&&void 0!==arguments[2]?arguments[2]:{};return o.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return r=b.returnEntireTree,i=b.baseDoc,c=b.requestInterceptor,f=b.responseInterceptor,p=b.parameterMacro,d=b.modelPropertyMacro,h=b.useCircularStructures,v={pathDiscriminator:n,baseDoc:i,requestInterceptor:c,responseInterceptor:f,parameterMacro:p,modelPropertyMacro:d,useCircularStructures:h},m=(0,l.normalizeSwagger)({spec:t}),g=m.spec,e.next=5,(0,s.default)((0,a.default)({},v,{spec:g,allowMetaPatches:!0,skipNormalization:!0}));case 5:return y=e.sent,!r&&Array.isArray(n)&&n.length&&(y.spec=(0,u.default)(y.spec,n)||null),e.abrupt("return",y);case 8:case"end":return e.stop()}},e,this)}));return function(t,n){return e.apply(this,arguments)}}(),e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function(t){var n=t.pathName,r=t.method,o=t.operationId;return function(t){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.execute((0,i.default)({spec:e.spec},(0,u.default)(e,"requestInterceptor","responseInterceptor","userFetch"),{pathName:n,method:r,parameters:t,operationId:o},a))}}}function a(e){var t=e.spec,n=e.cb,r=void 0===n?l:n,o=e.defaultTag,a=void 0===o?"default":o,i=e.v2OperationIdCompatibilityMode,u={},f={};return(0,s.eachOperation)(t,function(e){var n=e.pathName,o=e.method,l=e.operation;(l.tags?c(l.tags):[a]).forEach(function(e){if("string"==typeof e){var a=f[e]=f[e]||{},c=(0,s.opId)(l,n,o,{v2OperationIdCompatibilityMode:i}),p=r({spec:t,pathName:n,method:o,operation:l,operationId:c});if(u[c])u[c]++,a[""+c+u[c]]=p;else if(void 0!==a[c]){var d=u[c]||1;u[c]=d+1,a[""+c+u[c]]=p;var h=a[c];delete a[c],a[""+c+d]=h}else a[c]=p}})}),f}Object.defineProperty(t,"__esModule",{value:!0}),t.self=void 0;var i=r(n(3));t.makeExecute=o,t.makeApisTagOperationsOperationExecute=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=f.makeExecute(e),n=f.mapTagOperations({v2OperationIdCompatibilityMode:e.v2OperationIdCompatibilityMode,spec:e.spec,cb:t}),r={};for(var o in n)for(var a in r[o]={operations:{}},n[o])r[o].operations[a]={execute:n[o][a]};return{apis:r}},t.makeApisTagOperation=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=f.makeExecute(e);return{apis:f.mapTagOperations({v2OperationIdCompatibilityMode:e.v2OperationIdCompatibilityMode,spec:e.spec,cb:t})}},t.mapTagOperations=a;var u=r(n(51)),s=n(5),l=function(){return null},c=function(e){return Array.isArray(e)?e:[e]},f=t.self={mapTagOperations:a,makeExecute:o}},function(e,t){e.exports=n(927)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){var t=e.spec,n=e.operationId,r=(e.securities,e.requestContentType,e.responseContentType),o=e.scheme,i=e.requestInterceptor,s=e.responseInterceptor,c=e.contextUrl,f=e.userFetch,p=(e.requestBody,e.server),d=e.serverVariables,h=e.http,g=e.parameters,y=e.parameterBuilders,O=(0,x.isOAS3)(t);y||(y=O?_.default:b.default);var P={url:"",credentials:h&&h.withCredentials?"include":"same-origin",headers:{},cookies:{}};i&&(P.requestInterceptor=i),s&&(P.responseInterceptor=s),f&&(P.userFetch=f);var M=(0,x.getOperationRaw)(t,n);if(!M)throw new C("Operation "+n+" not found");var T=M.operation,I=void 0===T?{}:T,j=M.method,N=M.pathName;if(P.url+=a({spec:t,scheme:o,contextUrl:c,server:p,serverVariables:d,pathName:N,method:j}),!n)return delete P.cookies,P;P.url+=N,P.method=(""+j).toUpperCase(),g=g||{};var R=t.paths[N]||{};r&&(P.headers.accept=r);var D=A([].concat(S(I.parameters)).concat(S(R.parameters)));D.forEach(function(e){var n=y[e.in],r=void 0;if("body"===e.in&&e.schema&&e.schema.properties&&(r=g),void 0===(r=e&&e.name&&g[e.name])?r=e&&e.name&&g[e.in+"."+e.name]:k(e.name,D).length>1&&console.warn("Parameter '"+e.name+"' is ambiguous because the defined spec has more than one parameter with the name: '"+e.name+"' and the passed-in parameter values did not define an 'in' value."),null!==r){if(void 0!==e.default&&void 0===r&&(r=e.default),void 0===r&&e.required&&!e.allowEmptyValue)throw new Error("Required parameter "+e.name+" is not provided");if(O&&e.schema&&"object"===e.schema.type&&"string"==typeof r)try{r=JSON.parse(r)}catch(e){throw new Error("Could not parse object parameter value string as JSON")}n&&n({req:P,parameter:e,value:r,operation:I,spec:t})}});var L=(0,u.default)({},e,{operation:I});if((P=O?(0,w.default)(L,P):(0,E.default)(L,P)).cookies&&(0,l.default)(P.cookies).length){var U=(0,l.default)(P.cookies).reduce(function(e,t){var n=P.cookies[t];return e+(e?"&":"")+v.default.serialize(t,n)},"");P.headers.Cookie=U}return P.cookies&&delete P.cookies,(0,m.mergeInQueryOrForm)(P),P}function a(e){return(0,x.isOAS3)(e.spec)?function(e){var t=e.spec,n=e.pathName,r=e.method,o=e.server,a=e.contextUrl,i=e.serverVariables,u=void 0===i?{}:i,s=(0,f.default)(t,["paths",n,(r||"").toLowerCase(),"servers"])||(0,f.default)(t,["paths",n,"servers"])||(0,f.default)(t,["servers"]),l="",c=null;if(o&&s&&s.length){var p=s.map(function(e){return e.url});p.indexOf(o)>-1&&(l=o,c=s[p.indexOf(o)])}!l&&s&&s.length&&(l=s[0].url,c=s[0]),l.indexOf("{")>-1&&function(e){for(var t=[],n=/{([^}]+)}/g,r=void 0;r=n.exec(e);)t.push(r[1]);return t}(l).forEach(function(e){if(c.variables&&c.variables[e]){var t=c.variables[e],n=u[e]||t.default,r=new RegExp("{"+e+"}","g");l=l.replace(r,n)}});return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=h.default.parse(e),r=h.default.parse(t),o=P(n.protocol)||P(r.protocol)||"",a=n.host||r.host,i=n.pathname||"",u=void 0;return"/"===(u=o&&a?o+"://"+(a+i):i)[u.length-1]?u.slice(0,-1):u}(l,a)}(e):function(e){var t=e.spec,n=e.scheme,r=e.contextUrl,o=void 0===r?"":r,a=h.default.parse(o),i=Array.isArray(t.schemes)?t.schemes[0]:null,u=n||i||P(a.protocol)||"http",s=t.host||a.host||"",l=t.basePath||"",c=void 0;return"/"===(c=u&&s?u+"://"+(s+l):l)[c.length-1]?c.slice(0,-1):c}(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.self=void 0;var i=r(n(9)),u=r(n(3)),s=r(n(53)),l=r(n(0)),c=r(n(2));t.execute=function(e){var t=e.http,n=e.fetch,r=e.spec,o=e.operationId,a=e.pathName,l=e.method,c=e.parameters,f=e.securities,h=(0,s.default)(e,["http","fetch","spec","operationId","pathName","method","parameters","securities"]),v=t||n||g.default;a&&l&&!o&&(o=(0,x.legacyIdFromPathMethod)(a,l));var m=O.buildRequest((0,u.default)({spec:r,operationId:o,parameters:c,securities:f,http:v},h));return m.body&&((0,p.default)(m.body)||(0,d.default)(m.body))&&(m.body=(0,i.default)(m.body)),v(m)},t.buildRequest=o,t.baseUrl=a;var f=r((r(n(6)),n(13))),p=r(n(54)),d=r(n(55)),h=r((r(n(14)),n(7))),v=r(n(56)),m=n(8),g=r(m),y=r(n(23)),b=r(n(57)),_=r(n(58)),w=r(n(63)),E=r(n(65)),x=n(5),S=function(e){return Array.isArray(e)?e:[]},C=(0,y.default)("OperationNotFoundError",function(e,t,n){this.originalError=n,(0,c.default)(this,t||{})}),k=function(e,t){return t.filter(function(t){return t.name===e})},A=function(e){var t={};e.forEach(function(e){t[e.in]||(t[e.in]={}),t[e.in][e.name]=e});var n=[];return(0,l.default)(t).forEach(function(e){(0,l.default)(t[e]).forEach(function(r){n.push(t[e][r])})}),n},O=t.self={buildRequest:o},P=function(e){return e?e.replace(/\W/g,""):null}},function(e,t){e.exports=n(86)},function(e,t){e.exports=n(230)},function(e,t){e.exports=n(24)},function(e,t){e.exports=n(930)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={body:function(e){var t=e.req,n=e.value;t.body=n},header:function(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{},void 0!==r&&(t.headers[n.name]=r)},query:function(e){var t=e.req,n=e.value,r=e.parameter;if(t.query=t.query||{},!1===n&&"boolean"===r.type&&(n="false"),0===n&&["number","integer"].indexOf(r.type)>-1&&(n="0"),n)t.query[r.name]={collectionFormat:r.collectionFormat,value:n};else if(r.allowEmptyValue&&void 0!==n){var o=r.name;t.query[o]=t.query[o]||{},t.query[o].allowEmptyValue=!0}},path:function(e){var t=e.req,n=e.value,r=e.parameter;t.url=t.url.split("{"+r.name+"}").join(encodeURIComponent(n))},formData:function(e){var t=e.req,n=e.value,r=e.parameter;(n||r.allowEmptyValue)&&(t.form=t.form||{},t.form[r.name]={value:n,allowEmptyValue:r.allowEmptyValue,collectionFormat:r.collectionFormat})}},e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(0)),a=r(n(1)),i=r(n(59));t.default={path:function(e){var t=e.req,n=e.value,r=e.parameter,o=r.name,a=r.style,u=r.explode,s=(0,i.default)({key:r.name,value:n,style:a||"simple",explode:u||!1,escape:!0});t.url=t.url.split("{"+o+"}").join(s)},query:function(e){var t=e.req,n=e.value,r=e.parameter;if(t.query=t.query||{},!1===n&&(n="false"),0===n&&(n="0"),n){var u=void 0===n?"undefined":(0,a.default)(n);"deepObject"===r.style?(0,o.default)(n).forEach(function(e){var o=n[e];t.query[r.name+"["+e+"]"]={value:(0,i.default)({key:e,value:o,style:"deepObject",escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0}}):"object"!==u||Array.isArray(n)||"form"!==r.style&&r.style||!r.explode&&void 0!==r.explode?t.query[r.name]={value:(0,i.default)({key:r.name,value:n,style:r.style||"form",explode:void 0===r.explode||r.explode,escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0}:(0,o.default)(n).forEach(function(e){var o=n[e];t.query[e]={value:(0,i.default)({key:e,value:o,style:r.style||"form",escape:r.allowReserved?"unsafe":"reserved"}),skipEncoding:!0}})}else if(r.allowEmptyValue&&void 0!==n){var s=r.name;t.query[s]=t.query[s]||{},t.query[s].allowEmptyValue=!0}},header:function(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{},u.indexOf(n.name.toLowerCase())>-1||void 0!==r&&(t.headers[n.name]=(0,i.default)({key:n.name,value:r,style:n.style||"simple",explode:void 0!==n.explode&&n.explode,escape:!1}))},cookie:function(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{};var o=void 0===r?"undefined":(0,a.default)(r);if("undefined"!==o){var u="object"===o&&!Array.isArray(r)&&n.explode?"":n.name+"=";t.headers.Cookie=u+(0,i.default)({key:n.name,value:r,escape:!1,style:n.style||"form",explode:void 0!==n.explode&&n.explode})}}};var u=["accept","authorization","content-type"];e.exports=t.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).escape,n=arguments[2];return"number"==typeof e&&(e=e.toString()),"string"==typeof e&&e.length&&t?n?JSON.parse(e):(0,s.stringToCharArray)(e).map(function(e){return c(e)?e:l(e)&&"unsafe"===t?e:((0,u.default)(e)||[]).map(function(e){return("0"+e.toString(16).toUpperCase()).slice(-2)}).map(function(e){return"%"+e}).join("")}).join(""):e}Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(0)),i=r(n(1));t.encodeDisallowedCharacters=o,t.default=function(e){var t=e.value;return Array.isArray(t)?function(e){var t=e.key,n=e.value,r=e.style,a=e.explode,i=e.escape,u=function(e){return o(e,{escape:i})};if("simple"===r)return n.map(function(e){return u(e)}).join(",");if("label"===r)return"."+n.map(function(e){return u(e)}).join(".");if("matrix"===r)return n.map(function(e){return u(e)}).reduce(function(e,n){return!e||a?(e||"")+";"+t+"="+n:e+","+n},"");if("form"===r){var s=a?"&"+t+"=":",";return n.map(function(e){return u(e)}).join(s)}if("spaceDelimited"===r){var l=a?t+"=":"";return n.map(function(e){return u(e)}).join(" "+l)}if("pipeDelimited"===r){var c=a?t+"=":"";return n.map(function(e){return u(e)}).join("|"+c)}}(e):"object"===(void 0===t?"undefined":(0,i.default)(t))?function(e){var t=e.key,n=e.value,r=e.style,i=e.explode,u=e.escape,s=function(e){return o(e,{escape:u})},l=(0,a.default)(n);return"simple"===r?l.reduce(function(e,t){var r=s(n[t]);return(e?e+",":"")+t+(i?"=":",")+r},""):"label"===r?l.reduce(function(e,t){var r=s(n[t]);return(e?e+".":".")+t+(i?"=":".")+r},""):"matrix"===r&&i?l.reduce(function(e,t){var r=s(n[t]);return(e?e+";":";")+t+"="+r},""):"matrix"===r?l.reduce(function(e,r){var o=s(n[r]);return(e?e+",":";"+t+"=")+r+","+o},""):"form"===r?l.reduce(function(e,t){var r=s(n[t]);return(e?e+(i?"&":","):"")+t+(i?"=":",")+r},""):void 0}(e):function(e){var t=e.key,n=e.value,r=e.style,a=e.escape,i=function(e){return o(e,{escape:a})};return"simple"===r?i(n):"label"===r?"."+i(n):"matrix"===r?";"+t+"="+i(n):"form"===r?i(n):"deepObject"===r?i(n):void 0}(e)};var u=r((r(n(60)),n(61))),s=n(62),l=function(e){return":/?#[]@!$&'()*+,;=".indexOf(e)>-1},c=function(e){return/^[a-z0-9\-._~]+$/i.test(e)}},function(e,t){e.exports=n(931)},function(e,t){e.exports=n(932)},function(e,t){e.exports=n(933)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,a=void 0===o?{}:o,i=e.spec,f=(0,s.default)({},t),p=r.authorized,d=void 0===p?{}:p,h=a.security||i.security||[],v=d&&!!(0,u.default)(d).length,m=(0,l.default)(i,["components","securitySchemes"])||{};return f.headers=f.headers||{},f.query=f.query||{},(0,u.default)(r).length&&v&&h&&(!Array.isArray(a.security)||a.security.length)?(h.forEach(function(e,t){for(var n in e){var r=d[n],o=m[n];if(r){var a=r.value||r,i=o.type;if(r)if("apiKey"===i)"query"===o.in&&(f.query[o.name]=a),"header"===o.in&&(f.headers[o.name]=a),"cookie"===o.in&&(f.cookies[o.name]=a);else if("http"===i){if("basic"===o.scheme){var u=a.username,s=a.password,l=(0,c.default)(u+":"+s);f.headers.Authorization="Basic "+l}"bearer"===o.scheme&&(f.headers.Authorization="Bearer "+a)}else if("oauth2"===i){var p=r.token||{},h=p.access_token,v=p.token_type;v&&"bearer"!==v.toLowerCase()||(v="Bearer"),f.headers.Authorization=v+" "+h}}}}),f):t}Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(9)),i=r(n(1)),u=r(n(0));t.default=function(e,t){var n=e.operation,r=e.requestBody,s=e.securities,l=e.spec,c=e.attachContentTypeForEmptyPayload,p=e.requestContentType;t=o({request:t,securities:s,operation:n,spec:l});var d=n.requestBody||{},h=(0,u.default)(d.content||{}),v=p&&h.indexOf(p)>-1;if(r||c){if(p&&v)t.headers["Content-Type"]=p;else if(!p){var m=h[0];m&&(t.headers["Content-Type"]=m,p=m)}}else p&&v&&(t.headers["Content-Type"]=p);return r&&(p?h.indexOf(p)>-1&&("application/x-www-form-urlencoded"===p||0===p.indexOf("multipart/")?"object"===(void 0===r?"undefined":(0,i.default)(r))?(t.form={},(0,u.default)(r).forEach(function(e){var n,o=r[e],u=void 0;"undefined"!=typeof File&&(u=o instanceof File),"undefined"!=typeof Blob&&(u=u||o instanceof Blob),void 0!==f.Buffer&&(u=u||f.Buffer.isBuffer(o)),n="object"!==(void 0===o?"undefined":(0,i.default)(o))||u?o:Array.isArray(o)?o.toString():(0,a.default)(o),t.form[e]={value:n}})):t.form=r:t.body=r):t.body=r),t},t.applySecurities=o;var s=r(n(6)),l=r(n(13)),c=r(n(14)),f=n(64)},function(e,t){e.exports=n(54)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,s=void 0===o?{}:o,l=e.spec,c=(0,u.default)({},t),f=r.authorized,p=void 0===f?{}:f,d=r.specSecurity,h=void 0===d?[]:d,v=s.security||h,m=p&&!!(0,a.default)(p).length,g=l.securityDefinitions;return c.headers=c.headers||{},c.query=c.query||{},(0,a.default)(r).length&&m&&v&&(!Array.isArray(s.security)||s.security.length)?(v.forEach(function(e,t){for(var n in e){var r=p[n];if(r){var o=r.token,a=r.value||r,u=g[n],s=u.type,l=u["x-tokenName"]||"access_token",f=o&&o[l],d=o&&o.token_type;if(r)if("apiKey"===s){var h="query"===u.in?"query":"headers";c[h]=c[h]||{},c[h][u.name]=a}else"basic"===s?a.header?c.headers.authorization=a.header:(a.base64=(0,i.default)(a.username+":"+a.password),c.headers.authorization="Basic "+a.base64):"oauth2"===s&&f&&(d=d&&"bearer"!==d.toLowerCase()?d:"Bearer",c.headers.authorization=d+" "+f)}}}),c):t}Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(0));t.default=function(e,t){var n=e.spec,r=e.operation,a=e.securities,i=e.requestContentType,u=e.attachContentTypeForEmptyPayload;if((t=o({request:t,securities:a,operation:r,spec:n})).body||t.form||u)i?t.headers["Content-Type"]=i:Array.isArray(r.consumes)?t.headers["Content-Type"]=r.consumes[0]:Array.isArray(n.consumes)?t.headers["Content-Type"]=n.consumes[0]:r.parameters&&r.parameters.filter(function(e){return"file"===e.type}).length?t.headers["Content-Type"]="multipart/form-data":r.parameters&&r.parameters.filter(function(e){return"formData"===e.in}).length&&(t.headers["Content-Type"]="application/x-www-form-urlencoded");else if(i){var s=r.parameters&&r.parameters.filter(function(e){return"body"===e.in}).length>0,l=r.parameters&&r.parameters.filter(function(e){return"formData"===e.in}).length>0;(s||l)&&(t.headers["Content-Type"]=i)}return t},t.applySecurities=o;var i=r(n(14)),u=r(n(6));r(n(8))}])},function(e,t,n){"use strict";var r=Object.prototype.hasOwnProperty,o=function(){for(var e=[],t=0;t<256;++t)e.push("%"+((t<16?"0":"")+t.toString(16)).toUpperCase());return e}();t.arrayToObject=function(e,t){for(var n=t&&t.plainObjects?Object.create(null):{},r=0;r=48&&a<=57||a>=65&&a<=90||a>=97&&a<=122?n+=t.charAt(r):a<128?n+=o[a]:a<2048?n+=o[192|a>>6]+o[128|63&a]:a<55296||a>=57344?n+=o[224|a>>12]+o[128|a>>6&63]+o[128|63&a]:(r+=1,a=65536+((1023&a)<<10|1023&t.charCodeAt(r)),n+=o[240|a>>18]+o[128|a>>12&63]+o[128|a>>6&63]+o[128|63&a])}return n},t.compact=function(e){for(var t=[{obj:{o:e},prop:"o"}],n=[],r=0;r=g){if(r&&"add"===n.op&&b>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",f,n,e);if(!1===(d=s[n.op].call(n,v,b,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",f,n,e);return d}}else if(b&&-1!=b.indexOf("~")&&(b=i.unescapePathComponent(b)),m>=g){if(!1===(d=u[n.op].call(n,v,b,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",f,n,e);return d}v=v[b]}}function f(e,n,r,o,a){if(void 0===o&&(o=!0),void 0===a&&(a=!0),r&&!Array.isArray(n))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=i._deepClone(e));for(var u=new Array(n.length),s=0,l=n.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",n,e,r);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",n,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",n,e,r);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&i.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",n,e,r);if(r)if("add"==e.op){var a=e.path.split("/").length,s=o.split("/").length;if(a!==s+1&&a!==s)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",n,e,r)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==o)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",n,e,r)}else if("move"===e.op||"copy"===e.op){var l=d([{op:"_get",path:e.from,value:void 0}],r);if(l&&"OPERATION_PATH_UNRESOLVABLE"===l.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",n,e,r)}}function d(e,n,r){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(n)f(i._deepClone(n),i._deepClone(e),r||!0);else{r=r||p;for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:(0,i.List)();return function(e){return(e.authSelectors.definitionsToAuthorize()||(0,i.List)()).filter(function(e){return t.some(function(t){return t.get(e.keySeq().first())})})}},t.authorized=(0,a.createSelector)(s,function(e){return e.get("authorized")||(0,i.Map)()}),t.isAuthorized=function(e,t){return function(e){var n=e.authSelectors.authorized();return i.List.isList(t)?!!t.toJS().filter(function(e){return-1===(0,r.default)(e).map(function(e){return!!n.get(e)}).indexOf(!1)}).length:null}},t.getConfigs=(0,a.createSelector)(s,function(e){return e.get("configs")})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.execute=void 0;var r,o=n(25),a=(r=o)&&r.__esModule?r:{default:r};t.execute=function(e,t){var n=t.authSelectors,r=t.specSelectors;return function(t){var o=t.path,i=t.method,u=t.operation,s=t.extras,l={authorized:n.authorized()&&n.authorized().toJS(),definitions:r.securityDefinitions()&&r.securityDefinitions().toJS(),specSecurity:r.security()&&r.security().toJS()};return e((0,a.default)({path:o,method:i,operation:u,securities:l},s))}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{fn:{shallowEqualKeys:r.shallowEqualKeys}}};var r=n(9)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=s(n(42)),o=s(n(23));t.default=function(e){var t=e.fn,n={download:function(e){return function(n){var r=n.errActions,a=n.specSelectors,i=n.specActions,s=n.getConfigs,l=t.fetch,c=s();function f(t){if(t instanceof Error||t.status>=400)return i.updateLoadingStatus("failed"),r.newThrownErr((0,o.default)(new Error((t.message||t.statusText)+" "+e),{source:"fetch"})),void(!t.status&&t instanceof Error&&function(){try{var t=void 0;if("URL"in u.default?t=new URL(e):(t=document.createElement("a")).href=e,"https:"!==t.protocol&&"https:"===u.default.location.protocol){var n=(0,o.default)(new Error("Possible mixed-content issue? The page was loaded over https:// but a "+t.protocol+"// URL was specified. Check that you are not attempting to load mixed content."),{source:"fetch"});return void r.newThrownErr(n)}if(t.origin!==u.default.location.origin){var a=(0,o.default)(new Error("Possible cross-origin (CORS) issue? The URL origin ("+t.origin+") does not match the page ("+u.default.location.origin+"). Check the server returns the correct 'Access-Control-Allow-*' headers."),{source:"fetch"});r.newThrownErr(a)}}catch(e){return}}());i.updateLoadingStatus("success"),i.updateSpec(t.text),a.url()!==e&&i.updateUrl(e)}e=e||a.url(),i.updateLoadingStatus("loading"),r.clear({source:"fetch"}),l({url:e,loadSpec:!0,requestInterceptor:c.requestInterceptor||function(e){return e},responseInterceptor:c.responseInterceptor||function(e){return e},credentials:"same-origin",headers:{Accept:"application/json,*/*"}}).then(f,f)}},updateLoadingStatus:function(e){var t=[null,"loading","failed","success","failedConfig"];return-1===t.indexOf(e)&&console.error("Error: "+e+" is not one of "+(0,r.default)(t)),{type:"spec_update_loading_status",payload:e}}},s={loadingStatus:(0,a.createSelector)(function(e){return e||(0,i.Map)()},function(e){return e.get("loadingStatus")||null})};return{statePlugins:{spec:{actions:n,reducers:{spec_update_loading_status:function(e,t){return"string"==typeof t.payload?e.set("loadingStatus",t.payload):e}},selectors:s}}}};var a=n(58),i=n(7),u=s(n(32));function s(e){return e&&e.__esModule?e:{default:e}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{statePlugins:{spec:{actions:i,selectors:f},configs:{reducers:s.default,actions:a,selectors:u}}}};var r=c(n(934)),o=n(236),a=l(n(237)),i=l(n(405)),u=l(n(406)),s=c(n(407));function l(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function c(e){return e&&e.__esModule?e:{default:e}}var f={getLocalConfig:function(){return(0,o.parseYamlConfig)(r.default)}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getConfigByUrl=t.downloadConfig=void 0;var r=n(236);t.downloadConfig=function(e){return function(t){return(0,t.fn.fetch)(e)}},t.getConfigByUrl=function(e,t){return function(n){var o=n.specActions;if(e)return o.downloadConfig(e).then(a,a);function a(n){n instanceof Error||n.status>=400?(o.updateLoadingStatus("failedConfig"),o.updateLoadingStatus("failedConfig"),o.updateUrl(""),console.error(n.statusText+" "+e.url),t(null)):t((0,r.parseYamlConfig)(n.text))}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.get=function(e,t){return e.getIn(Array.isArray(t)?t:[t])}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o,a=n(21),i=(r=a)&&r.__esModule?r:{default:r},u=n(7),s=n(237);t.default=(o={},(0,i.default)(o,s.UPDATE_CONFIGS,function(e,t){return e.merge((0,u.fromJS)(t.payload))}),(0,i.default)(o,s.TOGGLE_CONFIGS,function(e,t){var n=t.payload,r=e.get(n);return e.set(n,!r)}),o)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return[r.default,{statePlugins:{configs:{wrapActions:{loaded:function(e,t){return function(){e.apply(void 0,arguments);var n=decodeURIComponent(window.location.hash);t.layoutActions.parseDeepLinkHash(n)}}}}},wrapComponents:{operation:o.default,OperationTag:a.default}}]};var r=i(n(409)),o=i(n(411)),a=i(n(412));function i(e){return e&&e.__esModule?e:{default:e}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.clearScrollTo=t.scrollToElement=t.readyToScroll=t.parseDeepLinkHash=t.scrollTo=t.show=void 0;var r,o=f(n(21)),a=f(n(18)),i=n(410),u=f(n(935)),s=n(9),l=n(7),c=f(l);function f(e){return e&&e.__esModule?e:{default:e}}var p=t.show=function(e,t){var n=t.getConfigs,r=t.layoutSelectors;return function(){for(var t=arguments.length,o=Array(t),u=0;u-1&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(h.map(function(e){return e.replace(/_/g," ")}),!0)),n.show(h,!0)}(f.indexOf("_")>-1||d.indexOf("_")>-1)&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(u.map(function(e){return e.replace(/_/g," ")}),!0)),n.show(u,!0),n.scrollTo(u)}}},v=t.readyToScroll=function(e,t){return function(n){var r=n.layoutSelectors.getScrollToKey();c.default.is(r,(0,l.fromJS)(e))&&(n.layoutActions.scrollToElement(t),n.layoutActions.clearScrollTo())}},m=t.scrollToElement=function(e,t){return function(n){try{t=t||n.fn.getScrollParent(e),u.default.createScroller(t).to(e)}catch(e){console.error(e)}}},g=t.clearScrollTo=function(){return{type:"layout_clear_scroll"}};t.default={fn:{getScrollParent:function(e,t){var n=document.documentElement,r=getComputedStyle(e),o="absolute"===r.position,a=t?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===r.position)return n;for(var i=e;i=i.parentElement;)if(r=getComputedStyle(i),(!o||"static"!==r.position)&&a.test(r.overflow+r.overflowY+r.overflowX))return i;return n}},statePlugins:{layout:{actions:{scrollToElement:m,scrollTo:d,clearScrollTo:g,readyToScroll:v,parseDeepLinkHash:h},selectors:{getScrollToKey:function(e){return e.get("scrollToKey")},isShownKeyFromUrlHashArray:function(e,t){var n=(0,a.default)(t,2),r=n[0],o=n[1];return o?["operations",r,o]:r?["operations-tag",r]:[]},urlHashArrayFromIsShownKey:function(e,t){var n=(0,a.default)(t,3),r=n[0],o=n[1],i=n[2];return"operations"==r?[o,i]:"operations-tag"==r?[o]:[]}},reducers:(r={},(0,o.default)(r,"layout_scroll_to",function(e,t){return e.set("scrollToKey",c.default.fromJS(t.payload))}),(0,o.default)(r,"layout_clear_scroll",function(e){return e.delete("scrollToKey")}),r),wrapActions:{show:p}}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.setHash=function(e){return e?history.pushState(null,null,"#"+e):window.location.hash=""}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=l(n(4)),o=l(n(2)),a=l(n(3)),i=l(n(5)),u=l(n(6)),s=l(n(0));l(n(10));function l(e){return e&&e.__esModule?e:{default:e}}t.default=function(e,t){return function(n){function l(){var e,n,a,u;(0,o.default)(this,l);for(var s=arguments.length,c=Array(s),f=0;f",Gt:"≫",gt:">",gtcc:"⪧",gtcir:"⩺",gtdot:"⋗",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"⋗",gtreqless:"⋛",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"ℋ",HARDcy:"Ъ",hardcy:"ъ",hArr:"⇔",harr:"↔",harrcir:"⥈",harrw:"↭",Hat:"^",hbar:"ℏ",Hcirc:"Ĥ",hcirc:"ĥ",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",Hfr:"ℌ",hfr:"𝔥",HilbertSpace:"ℋ",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",Hopf:"ℍ",hopf:"𝕙",horbar:"―",HorizontalLine:"─",Hscr:"ℋ",hscr:"𝒽",hslash:"ℏ",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"≏",hybull:"⁃",hyphen:"‐",Iacute:"Í",iacute:"í",ic:"⁣",Icirc:"Î",icirc:"î",Icy:"И",icy:"и",Idot:"İ",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",Ifr:"ℑ",ifr:"𝔦",Igrave:"Ì",igrave:"ì",ii:"ⅈ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"℩",IJlig:"IJ",ijlig:"ij",Im:"ℑ",Imacr:"Ī",imacr:"ī",image:"ℑ",ImaginaryI:"ⅈ",imagline:"ℐ",imagpart:"ℑ",imath:"ı",imof:"⊷",imped:"Ƶ",Implies:"⇒",in:"∈",incare:"℅",infin:"∞",infintie:"⧝",inodot:"ı",Int:"∬",int:"∫",intcal:"⊺",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"⋂",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"⁣",InvisibleTimes:"⁢",IOcy:"Ё",iocy:"ё",Iogon:"Į",iogon:"į",Iopf:"𝕀",iopf:"𝕚",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",Iscr:"ℐ",iscr:"𝒾",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"⋴",isinsv:"⋳",isinv:"∈",it:"⁢",Itilde:"Ĩ",itilde:"ĩ",Iukcy:"І",iukcy:"і",Iuml:"Ï",iuml:"ï",Jcirc:"Ĵ",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"𝔍",jfr:"𝔧",jmath:"ȷ",Jopf:"𝕁",jopf:"𝕛",Jscr:"𝒥",jscr:"𝒿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"є",Kappa:"Κ",kappa:"κ",kappav:"ϰ",Kcedil:"Ķ",kcedil:"ķ",Kcy:"К",kcy:"к",Kfr:"𝔎",kfr:"𝔨",kgreen:"ĸ",KHcy:"Х",khcy:"х",KJcy:"Ќ",kjcy:"ќ",Kopf:"𝕂",kopf:"𝕜",Kscr:"𝒦",kscr:"𝓀",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"ℒ",Lambda:"Λ",lambda:"λ",Lang:"⟪",lang:"⟨",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"ℒ",laquo:"«",Larr:"↞",lArr:"⇐",larr:"←",larrb:"⇤",larrbfs:"⤟",larrfs:"⤝",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",lat:"⪫",lAtail:"⤛",latail:"⤙",late:"⪭",lates:"⪭︀",lBarr:"⤎",lbarr:"⤌",lbbrk:"❲",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"⦏",lbrkslu:"⦍",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ļ",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",lE:"≦",le:"≤",LeftAngleBracket:"⟨",LeftArrow:"←",Leftarrow:"⇐",leftarrow:"←",LeftArrowBar:"⇤",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVector:"⇃",LeftDownVectorBar:"⥙",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrow:"↔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTee:"⊣",LeftTeeArrow:"↤",LeftTeeVector:"⥚",leftthreetimes:"⋋",LeftTriangle:"⊲",LeftTriangleBar:"⧏",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVector:"↿",LeftUpVectorBar:"⥘",LeftVector:"↼",LeftVectorBar:"⥒",lEg:"⪋",leg:"⋚",leq:"≤",leqq:"≦",leqslant:"⩽",les:"⩽",lescc:"⪨",lesdot:"⩿",lesdoto:"⪁",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"⋖",lesseqgtr:"⋚",lesseqqgtr:"⪋",LessEqualGreater:"⋚",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"𝔏",lfr:"𝔩",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"▄",LJcy:"Љ",ljcy:"љ",Ll:"⋘",ll:"≪",llarr:"⇇",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"◺",Lmidot:"Ŀ",lmidot:"ŀ",lmoust:"⎰",lmoustache:"⎰",lnap:"⪉",lnapprox:"⪉",lnE:"≨",lne:"⪇",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftarrow:"⟵",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longleftrightarrow:"⟷",longmapsto:"⟼",LongRightArrow:"⟶",Longrightarrow:"⟹",longrightarrow:"⟶",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"𝕃",lopf:"𝕝",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"◊",lozenge:"◊",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"‎",lrtri:"⊿",lsaquo:"‹",Lscr:"ℒ",lscr:"𝓁",Lsh:"↰",lsh:"↰",lsim:"≲",lsime:"⪍",lsimg:"⪏",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Ł",lstrok:"ł",LT:"<",Lt:"≪",lt:"<",ltcc:"⪦",ltcir:"⩹",ltdot:"⋖",lthree:"⋋",ltimes:"⋉",ltlarr:"⥶",ltquest:"⩻",ltri:"◃",ltrie:"⊴",ltrif:"◂",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"▮",mcomma:"⨩",Mcy:"М",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:" ",Mellintrf:"ℳ",Mfr:"𝔐",mfr:"𝔪",mho:"℧",micro:"µ",mid:"∣",midast:"*",midcir:"⫰",middot:"·",minus:"−",minusb:"⊟",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"⫛",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"𝕄",mopf:"𝕞",mp:"∓",Mscr:"ℳ",mscr:"𝓂",mstpos:"∾",Mu:"Μ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"ń",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natur:"♮",natural:"♮",naturals:"ℕ",nbsp:" ",nbump:"≎̸",nbumpe:"≏̸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Ņ",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"⩂",Ncy:"Н",ncy:"н",ndash:"–",ne:"≠",nearhk:"⤤",neArr:"⇗",nearr:"↗",nearrow:"↗",nedot:"≐̸",NegativeMediumSpace:"​",NegativeThickSpace:"​",NegativeThinSpace:"​",NegativeVeryThinSpace:"​",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"𝔑",nfr:"𝔫",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nhArr:"⇎",nharr:"↮",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"њ",nlArr:"⇍",nlarr:"↚",nldr:"‥",nlE:"≦̸",nle:"≰",nLeftarrow:"⇍",nleftarrow:"↚",nLeftrightarrow:"⇎",nleftrightarrow:"↮",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"⁠",NonBreakingSpace:" ",Nopf:"ℕ",nopf:"𝕟",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"≏̸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"⋷",notinvc:"⋶",NotLeftTriangle:"⋪",NotLeftTriangleBar:"⧏̸",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"⋠",NotReverseElement:"∌",NotRightTriangle:"⋫",NotRightTriangleBar:"⧐̸",NotRightTriangleEqual:"⋭",NotSquareSubset:"⊏̸",NotSquareSubsetEqual:"⋢",NotSquareSuperset:"⊐̸",NotSquareSupersetEqual:"⋣",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"⊁",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"⋡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"≁",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",npar:"∦",nparallel:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"⋠",npre:"⪯̸",nprec:"⊀",npreceq:"⪯̸",nrArr:"⇏",nrarr:"↛",nrarrc:"⤳̸",nrarrw:"↝̸",nRightarrow:"⇏",nrightarrow:"↛",nrtri:"⋫",nrtrie:"⋭",nsc:"⊁",nsccue:"⋡",nsce:"⪰̸",Nscr:"𝒩",nscr:"𝓃",nshortmid:"∤",nshortparallel:"∦",nsim:"≁",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"⋢",nsqsupe:"⋣",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"⊁",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"⋫",ntrianglerighteq:"⋭",Nu:"Ν",nu:"ν",num:"#",numero:"№",numsp:" ",nvap:"≍⃒",nVDash:"⊯",nVdash:"⊮",nvDash:"⊭",nvdash:"⊬",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwArr:"⇖",nwarr:"↖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",ocir:"⊚",Ocirc:"Ô",ocirc:"ô",Ocy:"О",ocy:"о",odash:"⊝",Odblac:"Ő",odblac:"ő",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Œ",oelig:"œ",ofcir:"⦿",Ofr:"𝔒",ofr:"𝔬",ogon:"˛",Ograve:"Ò",ograve:"ò",ogt:"⧁",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"Ō",omacr:"ō",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"𝕆",oopf:"𝕠",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",Or:"⩔",or:"∨",orarr:"↻",ord:"⩝",order:"ℴ",orderof:"ℴ",ordf:"ª",ordm:"º",origof:"⊶",oror:"⩖",orslope:"⩗",orv:"⩛",oS:"Ⓢ",Oscr:"𝒪",oscr:"ℴ",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",Otimes:"⨷",otimes:"⊗",otimesas:"⨶",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"⏞",OverBracket:"⎴",OverParenthesis:"⏜",par:"∥",para:"¶",parallel:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"𝔓",pfr:"𝔭",Phi:"Φ",phi:"φ",phiv:"ϕ",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"π",pitchfork:"⋔",piv:"ϖ",planck:"ℏ",planckh:"ℎ",plankv:"ℏ",plus:"+",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"ℌ",pointint:"⨕",Popf:"ℙ",popf:"𝕡",pound:"£",Pr:"⪻",pr:"≺",prap:"⪷",prcue:"≼",prE:"⪳",pre:"⪯",prec:"≺",precapprox:"⪷",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",precsim:"≾",Prime:"″",prime:"′",primes:"ℙ",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"∏",Product:"∏",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"∝",Proportion:"∷",Proportional:"∝",propto:"∝",prsim:"≾",prurel:"⊰",Pscr:"𝒫",pscr:"𝓅",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"𝔔",qfr:"𝔮",qint:"⨌",Qopf:"ℚ",qopf:"𝕢",qprime:"⁗",Qscr:"𝒬",qscr:"𝓆",quaternions:"ℍ",quatint:"⨖",quest:"?",questeq:"≟",QUOT:'"',quot:'"',rAarr:"⇛",race:"∽̱",Racute:"Ŕ",racute:"ŕ",radic:"√",raemptyv:"⦳",Rang:"⟫",rang:"⟩",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",Rarr:"↠",rArr:"⇒",rarr:"→",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"↝",rAtail:"⤜",ratail:"⤚",ratio:"∶",rationals:"ℚ",RBarr:"⤐",rBarr:"⤏",rbarr:"⤍",rbbrk:"❳",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"⦐",Rcaron:"Ř",rcaron:"ř",Rcedil:"Ŗ",rcedil:"ŗ",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"р",rdca:"⤷",rdldhar:"⥩",rdquo:"”",rdquor:"”",rdsh:"↳",Re:"ℜ",real:"ℜ",realine:"ℛ",realpart:"ℜ",reals:"ℝ",rect:"▭",REG:"®",reg:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",Rfr:"ℜ",rfr:"𝔯",rHar:"⥤",rhard:"⇁",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"ρ",rhov:"ϱ",RightAngleBracket:"⟩",RightArrow:"→",Rightarrow:"⇒",rightarrow:"→",RightArrowBar:"⇥",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"⥝",RightDownVector:"⇂",RightDownVectorBar:"⥕",RightFloor:"⌋",rightharpoondown:"⇁",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"↝",RightTee:"⊢",RightTeeArrow:"↦",RightTeeVector:"⥛",rightthreetimes:"⋌",RightTriangle:"⊳",RightTriangleBar:"⧐",RightTriangleEqual:"⊵",RightUpDownVector:"⥏",RightUpTeeVector:"⥜",RightUpVector:"↾",RightUpVectorBar:"⥔",RightVector:"⇀",RightVectorBar:"⥓",ring:"˚",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"‏",rmoust:"⎱",rmoustache:"⎱",rnmid:"⫮",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",Ropf:"ℝ",ropf:"𝕣",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",Rscr:"ℛ",rscr:"𝓇",Rsh:"↱",rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"⋌",rtimes:"⋊",rtri:"▹",rtrie:"⊵",rtrif:"▸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"℞",Sacute:"Ś",sacute:"ś",sbquo:"‚",Sc:"⪼",sc:"≻",scap:"⪸",Scaron:"Š",scaron:"š",sccue:"≽",scE:"⪴",sce:"⪰",Scedil:"Ş",scedil:"ş",Scirc:"Ŝ",scirc:"ŝ",scnap:"⪺",scnE:"⪶",scnsim:"⋩",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"с",sdot:"⋅",sdotb:"⊡",sdote:"⩦",searhk:"⤥",seArr:"⇘",searr:"↘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"𝔖",sfr:"𝔰",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"←",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"­",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sigmav:"ς",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"⪝",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"←",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ь",sol:"/",solb:"⧄",solbar:"⌿",Sopf:"𝕊",sopf:"𝕤",spades:"♠",spadesuit:"♠",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"⊏",sqsube:"⊑",sqsubset:"⊏",sqsubseteq:"⊑",sqsup:"⊐",sqsupe:"⊒",sqsupset:"⊐",sqsupseteq:"⊒",squ:"□",Square:"□",square:"□",SquareIntersection:"⊓",SquareSubset:"⊏",SquareSubsetEqual:"⊑",SquareSuperset:"⊐",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"▪",squf:"▪",srarr:"→",Sscr:"𝒮",sscr:"𝓈",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"ϕ",strns:"¯",Sub:"⋐",sub:"⊂",subdot:"⪽",subE:"⫅",sube:"⊆",subedot:"⫃",submult:"⫁",subnE:"⫋",subne:"⊊",subplus:"⪿",subrarr:"⥹",Subset:"⋐",subset:"⊂",subseteq:"⊆",subseteqq:"⫅",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"⫋",subsim:"⫇",subsub:"⫕",subsup:"⫓",succ:"≻",succapprox:"⪸",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"⋩",succsim:"≿",SuchThat:"∋",Sum:"∑",sum:"∑",sung:"♪",Sup:"⋑",sup:"⊃",sup1:"¹",sup2:"²",sup3:"³",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"⫄",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"⫗",suplarr:"⥻",supmult:"⫂",supnE:"⫌",supne:"⊋",supplus:"⫀",Supset:"⋑",supset:"⊃",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"⫌",supsim:"⫈",supsub:"⫔",supsup:"⫖",swarhk:"⤦",swArr:"⇙",swarr:"↙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:"\t",target:"⌖",Tau:"Τ",tau:"τ",tbrk:"⎴",Tcaron:"Ť",tcaron:"ť",Tcedil:"Ţ",tcedil:"ţ",Tcy:"Т",tcy:"т",tdot:"⃛",telrec:"⌕",Tfr:"𝔗",tfr:"𝔱",there4:"∴",Therefore:"∴",therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thetav:"ϑ",thickapprox:"≈",thicksim:"∼",ThickSpace:"  ",thinsp:" ",ThinSpace:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",Tilde:"∼",tilde:"˜",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",times:"×",timesb:"⊠",timesbar:"⨱",timesd:"⨰",tint:"∭",toea:"⤨",top:"⊤",topbot:"⌶",topcir:"⫱",Topf:"𝕋",topf:"𝕥",topfork:"⫚",tosa:"⤩",tprime:"‴",TRADE:"™",trade:"™",triangle:"▵",triangledown:"▿",triangleleft:"◃",trianglelefteq:"⊴",triangleq:"≜",triangleright:"▹",trianglerighteq:"⊵",tridot:"◬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"⧍",tritime:"⨻",trpezium:"⏢",Tscr:"𝒯",tscr:"𝓉",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"ћ",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",Uarr:"↟",uArr:"⇑",uarr:"↑",Uarrocir:"⥉",Ubrcy:"Ў",ubrcy:"ў",Ubreve:"Ŭ",ubreve:"ŭ",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Ű",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"𝔘",ufr:"𝔲",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"▀",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"⌏",ultri:"◸",Umacr:"Ū",umacr:"ū",uml:"¨",UnderBar:"_",UnderBrace:"⏟",UnderBracket:"⎵",UnderParenthesis:"⏝",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"𝕌",uopf:"𝕦",UpArrow:"↑",Uparrow:"⇑",uparrow:"↑",UpArrowBar:"⤒",UpArrowDownArrow:"⇅",UpDownArrow:"↕",Updownarrow:"⇕",updownarrow:"↕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",Upsi:"ϒ",upsi:"υ",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",UpTee:"⊥",UpTeeArrow:"↥",upuparrows:"⇈",urcorn:"⌝",urcorner:"⌝",urcrop:"⌎",Uring:"Ů",uring:"ů",urtri:"◹",Uscr:"𝒰",uscr:"𝓊",utdot:"⋰",Utilde:"Ũ",utilde:"ũ",utri:"▵",utrif:"▴",uuarr:"⇈",Uuml:"Ü",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"ϰ",varnothing:"∅",varphi:"ϕ",varpi:"ϖ",varpropto:"∝",vArr:"⇕",varr:"↕",varrho:"ϱ",varsigma:"ς",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"ϑ",vartriangleleft:"⊲",vartriangleright:"⊳",Vbar:"⫫",vBar:"⫨",vBarv:"⫩",Vcy:"В",vcy:"в",VDash:"⊫",Vdash:"⊩",vDash:"⊨",vdash:"⊢",Vdashl:"⫦",Vee:"⋁",vee:"∨",veebar:"⊻",veeeq:"≚",vellip:"⋮",Verbar:"‖",verbar:"|",Vert:"‖",vert:"|",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"❘",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"𝔙",vfr:"𝔳",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"𝕍",vopf:"𝕧",vprop:"∝",vrtri:"⊳",Vscr:"𝒱",vscr:"𝓋",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Ŵ",wcirc:"ŵ",wedbar:"⩟",Wedge:"⋀",wedge:"∧",wedgeq:"≙",weierp:"℘",Wfr:"𝔚",wfr:"𝔴",Wopf:"𝕎",wopf:"𝕨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"𝒲",wscr:"𝓌",xcap:"⋂",xcirc:"◯",xcup:"⋃",xdtri:"▽",Xfr:"𝔛",xfr:"𝔵",xhArr:"⟺",xharr:"⟷",Xi:"Ξ",xi:"ξ",xlArr:"⟸",xlarr:"⟵",xmap:"⟼",xnis:"⋻",xodot:"⨀",Xopf:"𝕏",xopf:"𝕩",xoplus:"⨁",xotime:"⨂",xrArr:"⟹",xrarr:"⟶",Xscr:"𝒳",xscr:"𝓍",xsqcup:"⨆",xuplus:"⨄",xutri:"△",xvee:"⋁",xwedge:"⋀",Yacute:"Ý",yacute:"ý",YAcy:"Я",yacy:"я",Ycirc:"Ŷ",ycirc:"ŷ",Ycy:"Ы",ycy:"ы",yen:"¥",Yfr:"𝔜",yfr:"𝔶",YIcy:"Ї",yicy:"ї",Yopf:"𝕐",yopf:"𝕪",Yscr:"𝒴",yscr:"𝓎",YUcy:"Ю",yucy:"ю",Yuml:"Ÿ",yuml:"ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Ż",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"​",Zeta:"Ζ",zeta:"ζ",Zfr:"ℨ",zfr:"𝔷",ZHcy:"Ж",zhcy:"ж",zigrarr:"⇝",Zopf:"ℤ",zopf:"𝕫",Zscr:"𝒵",zscr:"𝓏",zwj:"‍",zwnj:"‌"}},function(e,t,n){"use strict";var r=n(423),o=n(27).unescapeMd;e.exports=function(e,t){var n,a,i,u=t,s=e.posMax;if(60===e.src.charCodeAt(t)){for(t++;t8&&n<14);)if(92===n&&t+11)break;if(41===n&&--a<0)break;t++}return u!==t&&(i=o(e.src.slice(u,t)),!!e.parser.validateLink(i)&&(e.linkContent=i,e.pos=t,!0))}},function(e,t,n){"use strict";var r=n(27).replaceEntities;e.exports=function(e){var t=r(e);try{t=decodeURI(t)}catch(e){}return encodeURI(t)}},function(e,t,n){"use strict";var r=n(27).unescapeMd;e.exports=function(e,t){var n,o=t,a=e.posMax,i=e.src.charCodeAt(t);if(34!==i&&39!==i&&40!==i)return!1;for(t++,40===i&&(i=41);t1?r-1:0),a=1;a1?t-1:0),r=1;r0){var T=i("JsonSchemaForm"),I=i("ParameterExt"),j=A.get("properties",(0,o.OrderedMap)());return n=o.Map.isMap(n)?n:(0,o.OrderedMap)(),r.default.createElement("div",{className:"table-container"},S&&r.default.createElement(g,{source:S}),r.default.createElement("table",null,r.default.createElement("tbody",null,j.map(function(e,t){var u=x?(0,a.getCommonExtensions)(e):null,s=A.get("required",(0,o.List)()).includes(t),l=e.get("type"),f=e.get("format"),d=e.get("description"),v=n.get(t),m=e.get("default")||e.get("example")||"";""===m&&"object"===l&&(m=(0,a.getSampleSchema)(e,!1,{includeWriteOnly:!0})),"string"!=typeof m&&"object"===l&&(m=(0,a.stringify)(m));var y="string"===l&&("binary"===f||"base64"===f);return r.default.createElement("tr",{key:t,className:"parameters","data-property-name":t},r.default.createElement("td",{className:"col parameters-col_name"},r.default.createElement("div",{className:s?"parameter__name required":"parameter__name"},t,s?r.default.createElement("span",{style:{color:"red"}}," *"):null),r.default.createElement("div",{className:"parameter__type"},l,f&&r.default.createElement("span",{className:"prop-format"},"($",f,")"),x&&u.size?u.map(function(e,t){return r.default.createElement(I,{key:t+"-"+e,xKey:t,xVal:e})}):null),r.default.createElement("div",{className:"parameter__deprecated"},e.get("deprecated")?"deprecated":null)),r.default.createElement("td",{className:"col parameters-col_description"},r.default.createElement(g,{source:d}),p?r.default.createElement("div",null,r.default.createElement(T,{fn:c,dispatchInitialValue:!y,schema:e,description:t,getComponent:i,value:void 0===v?m:v,onChange:function(e){h(e,[t])}})):null))}))))}return r.default.createElement("div",null,S&&r.default.createElement(g,{source:S}),O?r.default.createElement(w,{examples:O,currentKey:v,currentUserInputValue:n,onSelect:function(e){m(e)},updateValue:h,defaultToFirstExample:!0,getComponent:i}):null,p?r.default.createElement("div",null,r.default.createElement(b,{value:n,defaultValue:u(t,f,v),onChange:h,getComponent:i})):r.default.createElement(y,{getComponent:i,getConfigs:s,specSelectors:l,expandDepth:1,isExecute:p,schema:k.get("schema"),specPath:d.push("content",f),example:r.default.createElement(_,{className:"body-param__example",value:(0,a.stringify)(n)||u(t,f,v)})}),O?r.default.createElement(E,{example:O.get(v),getComponent:i}):null)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=f(n(42)),o=f(n(4)),a=f(n(2)),i=f(n(3)),u=f(n(5)),s=f(n(6)),l=n(0),c=f(l);f(n(1)),f(n(10));function f(e){return e&&e.__esModule?e:{default:e}}var p=function(e){function t(){return(0,a.default)(this,t),(0,u.default)(this,(t.__proto__||(0,o.default)(t)).apply(this,arguments))}return(0,s.default)(t,e),(0,i.default)(t,[{key:"render",value:function(){var e=this.props,t=e.link,n=e.name,o=(0,e.getComponent)("Markdown"),a=t.get("operationId")||t.get("operationRef"),i=t.get("parameters")&&t.get("parameters").toJS(),u=t.get("description");return c.default.createElement("div",{style:{marginBottom:"1.5em"}},c.default.createElement("div",{style:{marginBottom:".5em"}},c.default.createElement("b",null,c.default.createElement("code",null,n)),u?c.default.createElement(o,{source:u}):null),c.default.createElement("pre",null,"Operation `",a,"`",c.default.createElement("br",null),c.default.createElement("br",null),"Parameters ",function(e,t){if("string"!=typeof t)return"";return t.split("\n").map(function(t,n){return n>0?Array(e+1).join(" ")+t:t}).join("\n")}(0,(0,r.default)(i,null,2))||"{}",c.default.createElement("br",null)))}}]),t}(l.Component);t.default=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=c(n(4)),o=c(n(2)),a=c(n(3)),i=c(n(5)),u=c(n(6)),s=c(n(0)),l=n(7);c(n(1)),c(n(10));function c(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(){var e,n,a,u;(0,o.default)(this,t);for(var s=arguments.length,l=Array(s),c=0;c=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values"),a.Arguments=a.Array,r("keys"),r("values"),r("entries")},function(e,t){e.exports=function(){}},function(e,t,n){"use strict";var r=n(117),o=n(97),a=n(99),i={};n(50)(i,n(20)("iterator"),function(){return this}),e.exports=function(e,t,n){e.prototype=r(i,{next:o(1,n)}),a(e,t+" Iterator")}},function(e,t,n){var r=n(35),o=n(36),a=n(98);e.exports=n(41)?Object.defineProperties:function(e,t){o(e);for(var n,i=a(t),u=i.length,s=0;u>s;)r.f(e,n=i[s++],t[n]);return e}},function(e,t,n){var r=n(73),o=n(118),a=n(457);e.exports=function(e){return function(t,n,i){var u,s=r(t),l=o(s.length),c=a(i,l);if(e&&n!=n){for(;l>c;)if((u=s[c++])!=u)return!0}else for(;l>c;c++)if((e||c in s)&&s[c]===n)return e||c||0;return!e&&-1}}},function(e,t,n){var r=n(167),o=Math.max,a=Math.min;e.exports=function(e,t){return(e=r(e))<0?o(e+t,0):a(e,t)}},function(e,t,n){var r=n(167),o=n(162);e.exports=function(e){return function(t,n){var a,i,u=String(o(t)),s=r(n),l=u.length;return s<0||s>=l?e?"":void 0:(a=u.charCodeAt(s))<55296||a>56319||s+1===l||(i=u.charCodeAt(s+1))<56320||i>57343?e?u.charAt(s):a:e?u.slice(s,s+2):i-56320+(a-55296<<10)+65536}}},function(e,t,n){var r=n(36),o=n(171);e.exports=n(14).getIterator=function(e){var t=o(e);if("function"!=typeof t)throw TypeError(e+" is not iterable!");return r(t.call(e))}},function(e,t,n){n(461),n(247),n(472),n(476),n(487),n(488),e.exports=n(61).Promise},function(e,t,n){"use strict";var r=n(172),o={};o[n(17)("toStringTag")]="z",o+""!="[object z]"&&n(76)(Object.prototype,"toString",function(){return"[object "+r(this)+"]"},!0)},function(e,t,n){e.exports=!n(101)&&!n(102)(function(){return 7!=Object.defineProperty(n(174)("div"),"a",{get:function(){return 7}}).a})},function(e,t,n){var r=n(77);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){"use strict";var r=n(465),o=n(246),a=n(176),i={};n(59)(i,n(17)("iterator"),function(){return this}),e.exports=function(e,t,n){e.prototype=r(i,{next:o(1,n)}),a(e,t+" Iterator")}},function(e,t,n){var r=n(60),o=n(466),a=n(253),i=n(175)("IE_PROTO"),u=function(){},s=function(){var e,t=n(174)("iframe"),r=a.length;for(t.style.display="none",n(254).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("