diff --git a/.github/actions/build-push-container/action.yaml b/.github/actions/build-push-container/action.yaml index c1e589f2b..7fe44f576 100644 --- a/.github/actions/build-push-container/action.yaml +++ b/.github/actions/build-push-container/action.yaml @@ -51,15 +51,11 @@ inputs: app_chefs_geo_address_apiurl: description: Proxy URL to BC Geo Address API URL required: true - default: "../api/v1/bcgeoaddress/address" - app_chefs_advance_geo_address_apiurl: - description: Proxy URL to BC Geo Address API URL for advance search - required: true default: "../api/v1/bcgeoaddress/advance/address" ref: description: The checkout ref id required: false - default: '' + default: "" pr_number: description: Pull request number required: false @@ -98,7 +94,6 @@ runs: VITE_CHEFSTOURURL: ${{ inputs.app_chefstoururl }} VITE_FRONTEND_BASEPATH: ${{ inputs.route_path }} VITE_CHEFS_GEO_ADDRESS_APIURL: ${{ inputs.app_chefs_geo_address_apiurl }} - VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL: ${{ inputs.app_chefs_advance_geo_address_apiurl }} VITE_BC_GEO_ADDRESS_APIURL: ${{ inputs.app_bc_geo_address_apiurl }} ENV_PATH: ./app/frontend/.env shell: bash @@ -109,7 +104,6 @@ runs: echo VITE_HOWTOURL=$VITE_HOWTOURL >> $ENV_PATH echo VITE_CHEFSTOURURL=$VITE_CHEFSTOURURL >> $ENV_PATH echo VITE_CHEFS_GEO_ADDRESS_APIURL=$VITE_CHEFS_GEO_ADDRESS_APIURL >> $ENV_PATH - echo VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL=$VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL >> $ENV_PATH echo VITE_BC_GEO_ADDRESS_APIURL=$VITE_BC_GEO_ADDRESS_APIURL >> $ENV_PATH echo VITE_FRONTEND_BASEPATH=$VITE_FRONTEND_BASEPATH >> $ENV_PATH diff --git a/.vscode/launch.json b/.vscode/launch.json index 72c7a54d6..c5d7ac6e2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,11 +21,12 @@ { "cwd": "${workspaceFolder}/app/frontend", "env": { - "VITE_TITLE": "Common Hosted Forms - Local", + "VITE_CHEFS_GEO_ADDRESS_APIURL": "http://localhost:8080/app/api/v1/bcgeoaddress/advance/address", + "VITE_CHEFSTOURURL": "https://www.youtube.com/embed/obOhyYusMjM", "VITE_CONTACT": "submit.digital@gov.bc.ca", "VITE_FRONTEND_BASEPATH": "/app", - "VITE_CHEFSTOURURL": "https://www.youtube.com/embed/obOhyYusMjM", - "VITE_HOWTOURL": "https://www.youtube.com/playlist?list=PL9CV_8JBQHirsQAShw45PZeU1CkU88Q53" + "VITE_HOWTOURL": "https://www.youtube.com/playlist?list=PL9CV_8JBQHirsQAShw45PZeU1CkU88Q53", + "VITE_TITLE": "Common Hosted Forms - Local" }, "name": "CHEFS Frontend", "outputCapture": "std", diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json index ca78b437b..e3d4efeb1 100644 --- a/app/frontend/package-lock.json +++ b/app/frontend/package-lock.json @@ -1609,12 +1609,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "devOptional": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2611,9 +2611,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -6552,9 +6552,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/app/src/components/errorToProblem.js b/app/src/components/errorToProblem.js index c6264bec8..bd01f91b0 100755 --- a/app/src/components/errorToProblem.js +++ b/app/src/components/errorToProblem.js @@ -2,28 +2,46 @@ const Problem = require('api-problem'); const log = require('./log')(module.filename); -module.exports = function (service, e) { - if (e.response) { - // Handle raw data - let data; - if (typeof e.response.data === 'string' || e.response.data instanceof String) { - data = JSON.parse(e.response.data); - } else { - data = e.response.data; - } +/** + * Try to convert response data to JSON, but failing that just return it as-is. + * + * @param {*} data the data to attempt to parse into JSON. + * @returns an object if data is JSON, otherwise data itself + */ +const _parseResponseData = (data) => { + let parsedData; + + try { + parsedData = JSON.parse(data); + } catch (error) { + // Syntax Error: It's not valid JSON. + parsedData = data; + } + + return parsedData; +}; + +module.exports = function (service, error) { + if (error.response) { + const data = _parseResponseData(error.response.data); + + log.error(`Error from ${service}: status = ${error.response.status}, data: ${JSON.stringify(data)}`, error); - log.error(`Error from ${service}: status = ${e.response.status}, data : ${JSON.stringify(data)}`, e); // Validation Error - if (e.response.status === 422) { - throw new Problem(e.response.status, { + if (error.response.status === 422) { + throw new Problem(error.response.status, { detail: data.detail, errors: data.errors, }); } + // Something else happened but there's a response - throw new Problem(e.response.status, { detail: e.response.data.toString() }); + throw new Problem(error.response.status, { detail: error.response.data.toString() }); } else { - log.error(`Unknown error calling ${service}: ${e.message}`, e); - throw new Problem(502, `Unknown ${service} Error`, { detail: e.message }); + log.error(`Unknown error calling ${service}: ${error.message}`, error); + + throw new Problem(502, `Unknown ${service} Error`, { + detail: error.message, + }); } }; diff --git a/app/src/forms/proxy/controller.js b/app/src/forms/proxy/controller.js index a2b8865ce..a0a0f2103 100644 --- a/app/src/forms/proxy/controller.js +++ b/app/src/forms/proxy/controller.js @@ -3,6 +3,9 @@ const jwtService = require('../../components/jwtService'); const axios = require('axios'); const { ExternalAPIStatuses } = require('../common/constants'); const Problem = require('api-problem'); +const ProxyServiceError = require('./error'); +const { NotFoundError } = require('objection'); +const log = require('../../components/log')(module.filename); module.exports = { generateProxyHeaders: async (req, res, next) => { @@ -19,22 +22,53 @@ module.exports = { const proxyHeaderInfo = await service.readProxyHeaders(req.headers); // find the specified external api configuration... const extAPI = await service.getExternalAPI(req.headers, proxyHeaderInfo); - if (extAPI.code != ExternalAPIStatuses.APPROVED) { - throw new Problem(407, 'External API has not been approved by CHEFS.'); - } // add path to endpoint url if included in headers... const extUrl = service.createExternalAPIUrl(req.headers, extAPI.endpointUrl); // build list of request headers based on configuration... const extHeaders = await service.createExternalAPIHeaders(extAPI, proxyHeaderInfo); + // check for approval before we call it.. + if (extAPI.code != ExternalAPIStatuses.APPROVED) { + throw new Problem(407, 'External API has not been approved by CHEFS.'); + } let axiosInstance = axios.create({ headers: extHeaders, }); // call the external api - const { data } = await axiosInstance.get(extUrl); + const { data, status } = await axiosInstance.get(extUrl).catch(function (err) { + let message = err.message; + if (err.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + log.warn(`Error returned from the external API': ${message}`); + } else if (err.request) { + message = 'External API call made, no response received.'; + log.warn(message); + } else { + // Something happened in setting up the request that triggered an Error + log.warn(`Error setting up the external API request: ${message}`); + } + // send a bad gateway, the message should contain the real status + throw new Problem(502, message); + }); // if all good return data - res.status(200).json(data); + res.status(status).json(data); } catch (error) { - next(error); + if (error instanceof ProxyServiceError) { + // making an assumption that the form component making this call + // has not been setup correctly yet. + // formio components will call as soon as the URL is entered while designing. + // calls will fire before the designer has added the headers. + log.warn(error.message); + // send back status 400 Bad Request + res.sendStatus(400); + } else if (error instanceof NotFoundError) { + // may have created formio component before adding the External API config. + log.warn('External API configuration does not exist.'); + // send back status 400 Bad Request + res.sendStatus(400); + } else { + next(error); + } } }, }; diff --git a/app/src/forms/proxy/error.js b/app/src/forms/proxy/error.js new file mode 100644 index 000000000..f096a4f50 --- /dev/null +++ b/app/src/forms/proxy/error.js @@ -0,0 +1,8 @@ +class ProxyServiceError extends Error { + constructor(message) { + super(message); + this.name = 'ProxyServiceError'; + } +} + +module.exports = ProxyServiceError; diff --git a/app/src/forms/proxy/service.js b/app/src/forms/proxy/service.js index 845119648..f6cd334a1 100644 --- a/app/src/forms/proxy/service.js +++ b/app/src/forms/proxy/service.js @@ -1,6 +1,6 @@ const { encryptionService } = require('../../components/encryptionService'); const jwtService = require('../../components/jwtService'); - +const ProxyServiceError = require('./error'); const { ExternalAPI } = require('../../forms/common/models'); const headerValue = (headers, key) => { @@ -21,7 +21,7 @@ const trimTrailingSlashes = (str) => str.replace(/\/+$/g, ''); const service = { generateProxyHeaders: async (payload, currentUser, token) => { if (!payload || !currentUser || !currentUser.idp) { - throw new Error('Cannot generate proxy headers with missing or incomplete parameters'); + throw new ProxyServiceError('Cannot generate proxy headers with missing or incomplete parameters'); } const headerData = { @@ -51,16 +51,20 @@ const service = { const data = JSON.parse(decryptedHeaderData); return data; } catch (error) { - throw new Error(`Could not decrypt proxy headers: ${error.message}`); + throw new ProxyServiceError(`Could not decrypt proxy headers: ${error.message}`); } } else { - throw new Error('Proxy headers not found'); + throw new ProxyServiceError('X-CHEFS-PROXY-DATA headers not found or empty.'); } }, getExternalAPI: async (headers, proxyHeaderInfo) => { const externalApiName = headerValue(headers, 'X-CHEFS-EXTERNAL-API-NAME'); - const externalAPI = await ExternalAPI.query().modify('findByFormIdAndName', proxyHeaderInfo['formId'], externalApiName).first().throwIfNotFound(); - return externalAPI; + if (externalApiName) { + const externalAPI = await ExternalAPI.query().modify('findByFormIdAndName', proxyHeaderInfo['formId'], externalApiName).first().throwIfNotFound(); + return externalAPI; + } else { + throw new ProxyServiceError('X-CHEFS-EXTERNAL-API-NAME header not found or empty.'); + } }, createExternalAPIUrl: (headers, endpointUrl) => { //check incoming request headers for path to add to the endpoint url @@ -78,7 +82,7 @@ const service = { if (externalAPI.sendUserToken) { if (!proxyHeaderInfo || !proxyHeaderInfo.token) { // just assume that if there is no idpUserId than it isn't a userInfo object - throw new Error('Cannot create user token headers for External API without populated proxy header info token.'); + throw new ProxyServiceError('Cannot create user token headers for External API without populated proxy header info token.'); } const val = externalAPI.userTokenBearer ? `Bearer ${proxyHeaderInfo['token']}` : proxyHeaderInfo['token']; result[externalAPI.userTokenHeader] = val; @@ -86,7 +90,7 @@ const service = { if (externalAPI.sendUserInfo) { if (!proxyHeaderInfo || !proxyHeaderInfo.idp) { // just assume that if there is no idp than it isn't a userInfo object - throw new Error('Cannot create user headers for External API without populated proxy header info object.'); + throw new ProxyServiceError('Cannot create user headers for External API without populated proxy header info object.'); } // user information (no token) diff --git a/app/tests/unit/components/errorToProblem.spec.js b/app/tests/unit/components/errorToProblem.spec.js index 7efcdaadb..58cc9d8b5 100644 --- a/app/tests/unit/components/errorToProblem.spec.js +++ b/app/tests/unit/components/errorToProblem.spec.js @@ -3,20 +3,33 @@ const errorToProblem = require('../../../src/components/errorToProblem'); const SERVICE = 'TESTSERVICE'; describe('errorToProblem', () => { + it('should throw a 404', () => { + const error = { + response: { + data: { detail: 'detail' }, + status: 404, + }, + }; + + expect(() => errorToProblem(SERVICE, error)).toThrow('404'); + }); + it('should throw a 422', () => { - const e = { + const error = { response: { data: { detail: 'detail' }, status: 422, }, }; - expect(() => errorToProblem(SERVICE, e)).toThrow('422'); + + expect(() => errorToProblem(SERVICE, error)).toThrow('422'); }); it('should throw a 502', () => { - const e = { + const error = { message: 'msg', }; - expect(() => errorToProblem(SERVICE, e)).toThrow('502'); + + expect(() => errorToProblem(SERVICE, error)).toThrow('502'); }); }); diff --git a/app/tests/unit/forms/proxy/controller.spec.js b/app/tests/unit/forms/proxy/controller.spec.js index 6ea934267..d52ad6c68 100644 --- a/app/tests/unit/forms/proxy/controller.spec.js +++ b/app/tests/unit/forms/proxy/controller.spec.js @@ -4,6 +4,7 @@ const { getMockReq, getMockRes } = require('@jest-mock/express'); const controller = require('../../../../src/forms/proxy/controller'); const service = require('../../../../src/forms/proxy/service'); const jwtService = require('../../../../src/components/jwtService'); +const { NotFoundError } = require('objection'); const bearerToken = Math.random().toString(36).substring(2); @@ -138,9 +139,30 @@ describe('callExternalApi', () => { expect(service.readProxyHeaders).toBeCalledTimes(1); expect(service.getExternalAPI).toBeCalledTimes(1); - expect(service.createExternalAPIUrl).not.toHaveBeenCalled(); - expect(service.createExternalAPIHeaders).not.toHaveBeenCalled(); + expect(service.createExternalAPIUrl).toBeCalledTimes(1); + expect(service.createExternalAPIHeaders).toBeCalledTimes(1); + // this is the point where we check the status code for external api + expect(axios.get).not.toHaveBeenCalled(); expect(res.status).not.toHaveBeenCalled(); expect(next).toBeCalledTimes(1); }); + + it('should return 400 when headers missing', async () => { + const req = getMockReq({ headers: { 'X-CHEFS-PROXY-DATA': 'encrypted blob of proxy data' } }); + const { res, next } = getMockRes(); + + service.readProxyHeaders = jest.fn().mockReturnValue({}); + service.getExternalAPI = jest.fn().mockRejectedValueOnce(new NotFoundError()); + service.createExternalAPIUrl = jest.fn().mockReturnValue('http://external.api/private'); + service.createExternalAPIHeaders = jest.fn().mockReturnValue({ 'X-TEST-HEADERS': 'test-headers-err' }); + + await controller.callExternalApi(req, res, next); + + expect(service.readProxyHeaders).toBeCalledTimes(1); + expect(service.getExternalAPI).toBeCalledTimes(1); + expect(service.createExternalAPIUrl).not.toHaveBeenCalled(); + expect(service.createExternalAPIHeaders).not.toHaveBeenCalled(); + expect(res.sendStatus).toBeCalledWith(400); + expect(next).not.toHaveBeenCalled(); + }); }); diff --git a/components/package-lock.json b/components/package-lock.json index 60df996b8..5788a680b 100644 --- a/components/package-lock.json +++ b/components/package-lock.json @@ -42,17 +42,21 @@ "ts-sinon": "^2.0.2", "tslint": "^6.1.3", "typescript": "^4.7.4", - "vite": "^4.3.5", + "vite": "^4.5.3", "webpack-cli": "^4.10.0" } }, "node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/core": { @@ -98,34 +102,65 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, "dependencies": { - "@babel/types": "^7.11.5", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, "dependencies": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "dependencies": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { @@ -193,19 +228,34 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/types": "^7.11.0" + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, "node_modules/@babel/helpers": { "version": "7.10.4", @@ -219,20 +269,24 @@ } }, "node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -253,40 +307,55 @@ } }, "node_modules/@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/@babel/traverse/node_modules/ms": { @@ -296,14 +365,17 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@cspotcode/source-map-support": { @@ -327,10 +399,346 @@ "node": ">=10.0.0" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", - "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ "x64" ], @@ -452,18 +860,27 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", @@ -473,9 +890,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -2440,9 +2857,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", - "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", "dev": true, "hasInstallScript": true, "bin": { @@ -2452,28 +2869,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.18", - "@esbuild/android-arm64": "0.17.18", - "@esbuild/android-x64": "0.17.18", - "@esbuild/darwin-arm64": "0.17.18", - "@esbuild/darwin-x64": "0.17.18", - "@esbuild/freebsd-arm64": "0.17.18", - "@esbuild/freebsd-x64": "0.17.18", - "@esbuild/linux-arm": "0.17.18", - "@esbuild/linux-arm64": "0.17.18", - "@esbuild/linux-ia32": "0.17.18", - "@esbuild/linux-loong64": "0.17.18", - "@esbuild/linux-mips64el": "0.17.18", - "@esbuild/linux-ppc64": "0.17.18", - "@esbuild/linux-riscv64": "0.17.18", - "@esbuild/linux-s390x": "0.17.18", - "@esbuild/linux-x64": "0.17.18", - "@esbuild/netbsd-x64": "0.17.18", - "@esbuild/openbsd-x64": "0.17.18", - "@esbuild/sunos-x64": "0.17.18", - "@esbuild/win32-arm64": "0.17.18", - "@esbuild/win32-ia32": "0.17.18", - "@esbuild/win32-x64": "0.17.18" + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" } }, "node_modules/escalade": { @@ -6170,9 +6587,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.0", @@ -6911,9 +7328,9 @@ } }, "node_modules/rollup": { - "version": "3.21.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.5.tgz", - "integrity": "sha512-a4NTKS4u9PusbUJcfF4IMxuqjFzjm6ifj76P54a7cKnvVzJaG12BLVR+hgU2YDGHzyMMQNxLAZWuALsn8q2oQg==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -6927,9 +7344,9 @@ } }, "node_modules/rollup/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -8634,14 +9051,14 @@ } }, "node_modules/vite": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", - "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", "dev": true, "dependencies": { - "esbuild": "^0.17.5", - "postcss": "^8.4.23", - "rollup": "^3.21.0" + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" @@ -8649,12 +9066,16 @@ "engines": { "node": "^14.18.0 || >=16.0.0" }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", + "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", @@ -8667,6 +9088,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, diff --git a/components/package.json b/components/package.json old mode 100755 new mode 100644 index 636662295..ed2573947 --- a/components/package.json +++ b/components/package.json @@ -80,7 +80,7 @@ "ts-sinon": "^2.0.2", "tslint": "^6.1.3", "typescript": "^4.7.4", - "vite": "^4.3.5", + "vite": "^4.5.3", "webpack-cli": "^4.10.0" }, "overrides": { diff --git a/components/src/components/BCAddress/Component.ts b/components/src/components/BCAddress/Component.ts index 9e4e32c04..e3df17217 100644 --- a/components/src/components/BCAddress/Component.ts +++ b/components/src/components/BCAddress/Component.ts @@ -1,6 +1,5 @@ - /* tslint:disable */ -import {Components} from 'formiojs'; +import { Components } from 'formiojs'; import { Constants } from '../Common/Constants'; import editForm from './Component.form'; import _ from 'lodash'; @@ -16,80 +15,82 @@ const ID = 'bcaddress'; const DISPLAY = 'BC Address'; export default class Component extends (ParentComponent as any) { - static schema(...extend) { - - return ParentComponent.schema({ - label: DISPLAY, - type: ID, - key: ID, - provider: 'custom', - providerOptions: { - queryProperty: 'addressString', - - url: import.meta.env.VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL}, - - queryParameters:{"echo": false, - "brief": true, - "minScore": 55, - "onlyCivic": true, - "maxResults": 15, - "autocomplete": true, - "matchAccuracy": 100, - "matchPrecision": "occupant, unit, site, civic_number, intersection, block, street, locality, province", - "precisionPoints": 100,} - - }, ...extend); - } - - static get builderInfo() { - return { - title: DISPLAY, - group: 'advanced', - icon: 'address-book', - weight: 90, - documentation: Constants.DEFAULT_HELP_LINK, - schema: Component.schema() - }; - } - - mergeSchema(component = {}) { - - let components = component['components']; - - if (components) { - return _.omit(component, 'components'); - } - - return component; + static schema(...extend) { + return ParentComponent.schema( + { + label: DISPLAY, + type: ID, + key: ID, + provider: 'custom', + providerOptions: { + queryProperty: 'addressString', + url: import.meta.env.VITE_CHEFS_GEO_ADDRESS_APIURL, + }, + + queryParameters: { + echo: false, + brief: true, + minScore: 55, + onlyCivic: true, + maxResults: 15, + autocomplete: true, + matchAccuracy: 100, + matchPrecision: + 'occupant, unit, site, civic_number, intersection, block, street, locality, province', + precisionPoints: 100, + }, + }, + ...extend + ); + } + + static get builderInfo() { + return { + title: DISPLAY, + group: 'advanced', + icon: 'address-book', + weight: 90, + documentation: Constants.DEFAULT_HELP_LINK, + schema: Component.schema(), + }; + } + + mergeSchema(component = {}) { + let components = component['components']; + + if (components) { + return _.omit(component, 'components'); } - public static editForm = editForm; + return component; + } - async init(){ - super.init(); - } + public static editForm = editForm; - async attach(element) { - super.attach(element); - try { + async init() { + super.init(); + } - let { - providerOptions, - queryParameters, - } = this.component; - if(providerOptions) { - if(!providerOptions.params) { - providerOptions["params"]={} - } - if(queryParameters) { - providerOptions.params ={...providerOptions.params,...queryParameters} - } - } - - } catch (err) { - console.log(`This error is from Custom BC Address component in form.io: Failed to acquire configuration: ${err.message}`); + async attach(element) { + super.attach(element); + try { + let { providerOptions, queryParameters } = this.component; + if (providerOptions) { + if (!providerOptions.params) { + providerOptions['params'] = {}; + } + if (queryParameters) { + providerOptions.params = { + ...providerOptions.params, + ...queryParameters, + }; } + } + } catch (err) { + console.log( + `This error is from Custom BC Address component in form.io: Failed to acquire configuration: ${err.message}` + ); } - + } } export {}; diff --git a/components/src/components/Map/Component.form.ts b/components/src/components/Map/Component.form.ts index cc9dc0133..9b8ac2603 100644 --- a/components/src/components/Map/Component.form.ts +++ b/components/src/components/Map/Component.form.ts @@ -5,42 +5,47 @@ import EditValidation from './editForm/Component.edit.validation'; import SimpleApi from '../Common/Simple.edit.api'; import SimpleConditional from '../Common/Simple.edit.conditional'; export default function (...extend) { - return baseEditForm([ - EditDisplay, - EditData, - { - key: 'api', - ignore: true - }, - { - key: 'layout', - ignore: true - }, - { - key: 'conditional', - ignore: true - }, - { - key: 'logic', - ignore: true - }, - { - label: 'Validation', - key: 'customValidation', - weight: 20, - components: EditValidation - }, - { - label: 'API', - key: 'customAPI', - weight: 30, - components: SimpleApi - }, - { - label: 'Conditional', - key: 'customConditional', - weight: 40, - components: SimpleConditional - } - ], ...extend); + return baseEditForm( + [ + EditDisplay, + { + key: 'data', + ignore: true, + }, + EditData, + { + key: 'api', + ignore: true, + }, + { + key: 'layout', + ignore: true, + }, + { + key: 'conditional', + ignore: true, + }, + { + key: 'logic', + ignore: true, + }, + { + key: 'validation', + ignore: true, + }, + { + label: 'API', + key: 'customAPI', + weight: 30, + components: SimpleApi, + }, + { + label: 'Conditional', + key: 'customConditional', + weight: 40, + components: SimpleConditional, + }, + ], + ...extend + ); } diff --git a/components/src/components/Map/Component.ts b/components/src/components/Map/Component.ts index 3cdac2976..579c23177 100644 --- a/components/src/components/Map/Component.ts +++ b/components/src/components/Map/Component.ts @@ -81,11 +81,14 @@ export default class Component extends (FieldComponent as any) { onDrawnItemsChange: this.saveDrawnItems.bind(this), }); - - // Load existing data if available if (this.dataValue) { - this.mapService.loadDrawnItems(JSON.parse(this.dataValue)); + try { + const parsedValue = JSON.parse(this.dataValue); + this.mapService.loadDrawnItems(parsedValue); + } catch (error) { + console.error('Failed to parse dataValue:', error); + } } } @@ -120,7 +123,6 @@ export default class Component extends (FieldComponent as any) { } }); - // Convert to JSON string const jsonValue = this.component.numPoints === 1 diff --git a/components/src/components/Map/editForm/Component.edit.data.ts b/components/src/components/Map/editForm/Component.edit.data.ts index fe7a284e7..d00ad3fbb 100644 --- a/components/src/components/Map/editForm/Component.edit.data.ts +++ b/components/src/components/Map/editForm/Component.edit.data.ts @@ -1,57 +1,68 @@ import common from '../../Common/Simple.edit.data'; -export default +export default { + key: 'customData', + label: 'Data', + weight: 20, + components: [ { - key: 'data', - components: [ - ...common, - { - label: "Marker Type ", - values: [ - { - label: "Point Marker", - value: "marker" - }, - { - label: "Circle", - value: "circle", - } - ], - defaultValue: "marker", - key: "markerType", - type: "simpleradios", - input: true, - }, - { - label: "How many Points per Submission?", - key: "numPoints", - type: "simplenumber", - defaultValue: 1, - input: true, - }, - - { - label: "Default Zoom Level", - description: "Zoom Levels are from 0 (Most zoomed out) to 18 (most zoomed in).", - defaultValue: 13, - delimiter: false, - requireDecimal: false, - validate: { - isUseForCopy: false, - min: 0, - max: 18 - }, - key: "defaultZoom", - type: "simplenumber", - input: true, - }, - { - label: "Read Only Map", - description: "This allows for the user to view and scroll the map, but not add any input", - key: "readOnlyMap", - type: "simplecheckbox", - input: true, - - } - ] - } + type: 'map', + label: 'Default Value', + key: 'defaultValue', + weight: 5, + placeholder: 'Default Value', + tooltip: + 'This will be the value for this field, before user interaction.', + input: true, + }, + { + label: 'Marker Type ', + values: [ + { + label: 'Add a point marker (drop a pin)', + value: 'marker', + }, + { + label: + 'Add circular area of interest through a point and custom radius', + value: 'circle', + }, + ], + defaultValue: 'marker', + key: 'markerType', + type: 'simpleradios', + input: true, + }, + { + label: 'How many Markers per Submission?', + key: 'numPoints', + type: 'simplenumber', + defaultValue: 1, + input: true, + }, + { + label: 'Default Zoom Level', + description: + 'Zoom Levels are from 0 (Most zoomed out) to 18 (most zoomed in).', + defaultValue: 13, + delimiter: false, + requireDecimal: false, + validate: { + isUseForCopy: false, + min: 0, + max: 18, + }, + key: 'defaultZoom', + type: 'simplenumber', + input: true, + }, + { + label: 'Read Only Map', + description: + 'This allows for the user to view and scroll the map, but not add any input', + key: 'readOnlyMap', + type: 'simplecheckbox', + input: true, + }, + ], +}; diff --git a/components/src/components/Map/services/MapService.ts b/components/src/components/Map/services/MapService.ts index bab5b464d..46585a644 100644 --- a/components/src/components/Map/services/MapService.ts +++ b/components/src/components/Map/services/MapService.ts @@ -9,9 +9,7 @@ const DEFAULT_LAYER_ATTRIBUTION = '© OpenStreetMap contributors'; const DEFAULT_MAP_ZOOM = 13; const DECIMALS_LATLNG = 5; // the number of decimals of latitude and longitude to be displayed in the marker popup -const COMPONENT_EDIT_CLASS = "component-edit-tabs"; - - +const COMPONENT_EDIT_CLASS = 'component-edit-tabs'; interface MapServiceOptions { mapContainer: HTMLElement; @@ -20,7 +18,7 @@ interface MapServiceOptions { form: HTMLCollectionOf; numPoints: number; defaultZoom?: number; - readOnlyMap?: boolean + readOnlyMap?: boolean; onDrawnItemsChange: (items: any) => void; // Support both single and multiple items } @@ -42,7 +40,7 @@ class MapService { let layer = e.layer; if (drawnItems.getLayers().length === options.numPoints) { L.popup() - .setLatLng(layer._latlng) + .setLatLng(layer.getLatLng()) .setContent('

Only one marker for submission

') .openOn(map); } else { @@ -55,7 +53,8 @@ class MapService { } initializeMap(options: MapServiceOptions) { - let { mapContainer, center, drawOptions, form, defaultZoom, readOnlyMap } = options; + let { mapContainer, center, drawOptions, form, defaultZoom, readOnlyMap } = + options; if (drawOptions.rectangle) { drawOptions.rectangle.showArea = false; } @@ -72,7 +71,7 @@ class MapService { map.addLayer(drawnItems); // Add Drawing Controllers - if(!readOnlyMap){ + if (!readOnlyMap) { let drawControl = new L.Control.Draw({ draw: drawOptions, edit: { @@ -82,20 +81,20 @@ class MapService { map.addControl(drawControl); } - //Checking to see if the map should be interactable - const componentEditNode = document.getElementsByClassName(COMPONENT_EDIT_CLASS) + // Checking to see if the map should be interactable + const componentEditNode = + document.getElementsByClassName(COMPONENT_EDIT_CLASS); if (form) { if (form[0]?.classList.contains('formbuilder')) { - map.dragging.disable(); - map.scrollWheelZoom.disable(); - if (this.hasChildNode(componentEditNode[0], mapContainer)) { - map.dragging.enable(); - map.scrollWheelZoom.enable(); - } + map.dragging.disable(); + map.scrollWheelZoom.disable(); + if (this.hasChildNode(componentEditNode[0], mapContainer)) { + map.dragging.enable(); + map.scrollWheelZoom.enable(); + } } - } + } - // Attach Controls to map return { map, drawnItems }; } @@ -132,7 +131,6 @@ class MapService { loadDrawnItems(items: any) { const { drawnItems } = this; - // Ensure drawnItems is defined before attempting to clear layers if (!drawnItems) { console.error('drawnItems is undefined'); return; @@ -140,7 +138,6 @@ class MapService { drawnItems.clearLayers(); - // Check if items is an array if (!Array.isArray(items)) { items = [items]; } @@ -172,12 +169,11 @@ class MapService { } for (let i = 0; i < parent?.childNodes?.length; i++) { if (this.hasChildNode(parent.childNodes[i], targetNode)) { - return true + return true; } } return false; } - } export default MapService; diff --git a/components/src/components/SimpleBCAddress/Component.ts b/components/src/components/SimpleBCAddress/Component.ts index b9b03ccce..df0fb9c8c 100644 --- a/components/src/components/SimpleBCAddress/Component.ts +++ b/components/src/components/SimpleBCAddress/Component.ts @@ -1,6 +1,5 @@ - /* tslint:disable */ -import {Components} from 'formiojs'; +import { Components } from 'formiojs'; import { Constants } from '../Common/Constants'; import editForm from './Component.form'; import _ from 'lodash'; @@ -16,83 +15,83 @@ const ID = 'simplebcaddress'; const DISPLAY = 'Simple BC Address'; export default class Component extends (ParentComponent as any) { - static schema(...extend) { - - return ParentComponent.schema({ - label: DISPLAY, - type: ID, - key: ID, - provider: 'custom', - providerOptions: { - queryProperty: 'addressString', - url:import.meta.env.VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL}, - - queryParameters:{"echo": false, - "brief": true, - "minScore": 55, - "onlyCivic": true, - "maxResults": 15, - "autocomplete": true, - "matchAccuracy": 100, - "matchPrecision": "occupant, unit, site, civic_number, intersection, block, street, locality, province", - "precisionPoints": 100,} - - }, ...extend); - } - - static get builderInfo() { - return { - title: DISPLAY, - group: 'advanced', - icon: 'address-book', - weight: 90, - documentation: Constants.DEFAULT_HELP_LINK, - schema: Component.schema(), - - }; - } - - public static editForm = editForm; - - async init(){ - super.init(); - } - - async attach(element) { - super.attach(element); - try { - - let { - providerOptions, - queryParameters, - - } = this.component; - - if(providerOptions) { - if(!providerOptions.params) { - providerOptions["params"]={} - } - if(queryParameters) { - providerOptions.params ={...providerOptions.params,...queryParameters} - } - } - - } catch (err) { - console.log(`This error is from Custom BC Address component in form.io: Failed to acquire configuration: ${err.message}`); + static schema(...extend) { + return ParentComponent.schema( + { + label: DISPLAY, + type: ID, + key: ID, + provider: 'custom', + providerOptions: { + queryProperty: 'addressString', + url: import.meta.env.VITE_CHEFS_GEO_ADDRESS_APIURL, + }, + + queryParameters: { + echo: false, + brief: true, + minScore: 55, + onlyCivic: true, + maxResults: 15, + autocomplete: true, + matchAccuracy: 100, + matchPrecision: + 'occupant, unit, site, civic_number, intersection, block, street, locality, province', + precisionPoints: 100, + }, + }, + ...extend + ); + } + + static get builderInfo() { + return { + title: DISPLAY, + group: 'advanced', + icon: 'address-book', + weight: 90, + documentation: Constants.DEFAULT_HELP_LINK, + schema: Component.schema(), + }; + } + + public static editForm = editForm; + + async init() { + super.init(); + } + + async attach(element) { + super.attach(element); + try { + let { providerOptions, queryParameters } = this.component; + + if (providerOptions) { + if (!providerOptions.params) { + providerOptions['params'] = {}; + } + if (queryParameters) { + providerOptions.params = { + ...providerOptions.params, + ...queryParameters, + }; } + } + } catch (err) { + console.log( + `This error is from Custom BC Address component in form.io: Failed to acquire configuration: ${err.message}` + ); } + } - mergeSchema(component = {}) { - - let components = component['components']; + mergeSchema(component = {}) { + let components = component['components']; - if (components) { - return _.omit(component, 'components'); - } - - return component; + if (components) { + return _.omit(component, 'components'); } - + return component; + } } export {}; diff --git a/docs/chefs-external-api-configuration.md b/docs/chefs-external-api-configuration.md index 12c421214..fbf46df5b 100644 --- a/docs/chefs-external-api-configuration.md +++ b/docs/chefs-external-api-configuration.md @@ -78,7 +78,7 @@ The user information initially comes from the user's token, as such the values f ## Configuring Form Component -For this example, we assume populating a drop down/select component... +For this example, we assume populating a drop-down/select component... **Data Source Type** = URL @@ -92,7 +92,7 @@ For this example, we assume populating a drop down/select component... | X-CHEFS-EXTERNAL-API-NAME | example-api - External API.name | | X-CHEFS-EXTERNAL-API-PATH | optional - add this value to External API.endpointUrl | -**Value Property**, **Item Template** and all other configuration is up to the Form Designer. +**Value Property**, **Item Template** and all other configurations are up to the Form Designer. `sessionStorage.getItem('X-CHEFS-PROXY-DATA')` is the User Info object in encrypted form that only CHEFS can decrypt. This is generated and stored on the form load. A call is made to the CHEFS backend using the current user's token (similar to fetching the form schema for rendering the form) and CHEFS encrypts the information. This prevents malicious form designers from having access to the user token but allows the form designer to provide context for their External API. @@ -101,3 +101,18 @@ The `sessionStorage` is cleared when the user navigates away from the form. The component will call the CHEFS proxy `{chefs host}/app/api/v1/proxy/external` with the headers, the proxy can decrypt the `X-CHEFS-PROXY-DATA` and formulate the call according to the External API configuration. It is expected that the External API endpoint is a `GET`. + +## HTTP Responses and errors + +Since formio components will make calls during the form design and configuration of the formio components (ie when the Datasource is URL and the URL has been populated), there will be many failed attempts calling the proxy. The most common failures will happen when the headers have not been added to the component configuration, or the `X-CHEFS-EXTERNAL-API-NAME` header has been set but the External API has not been configured. + +The following table will help you understand the HTTP statuses returned when calling `/api/v1/proxy/external`. + +| Http Status | Meaning | +| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 400 | Generally, the formio component has not been completely configured (missing headers) or the External API has not been configured. | +| 407 | The External API is configured and exists but has not been approved. | +| 502 | Call has gone through the CHEFS proxy but failed on the external server (ie 404 not found on your server). Check the message for information on the underlying HTTP Error. | +| 500 | Unexpected CHEFS server error. | + +A successful call through the CHEFS proxy to your External API will return the status code from your External API. diff --git a/openshift/app.dc.yaml b/openshift/app.dc.yaml index 31f9b42dc..198f0e966 100644 --- a/openshift/app.dc.yaml +++ b/openshift/app.dc.yaml @@ -166,7 +166,6 @@ objects: secretKeyRef: key: email name: "${APP_NAME}-contact-secret" - - name: VITE_HOWTOURL valueFrom: secretKeyRef: @@ -177,16 +176,6 @@ objects: secretKeyRef: key: chefstourvideourl name: "${APP_NAME}-landingpagevideourls-secret" - - name: VITE_CHEFS_GEO_ADDRESS_APIURL - valueFrom: - secretKeyRef: - key: chefsgeoaddressapiurl - name: "${APP_NAME}-bcgeoaddress-secret" - - name: VITE_CHEFS_ADVANCE_GEO_ADDRESS_APIURL - valueFrom: - secretKeyRef: - key: chefsadvancegeoaddressapiurl - name: "${APP_NAME}-bcgeoaddress-secret" - name: VITE_BC_GEO_ADDRESS_APIURL valueFrom: secretKeyRef: