Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/llle_project/egl-konnector
1 result
Show changes
Commits on Source (13)
node_modules
build
\ No newline at end of file
{
"extends": ["cozy-app", "plugin:prettier/recommended"],
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true,
"parser": "flow"
}
]
}
}
......@@ -21,7 +21,7 @@ include:
- template: Security/SAST.gitlab-ci.yml
unit-test:
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:16.14.2-alpine3.14
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:20.12.0-alpine3.19
stage: test
before_script:
- apk add git
......@@ -36,7 +36,7 @@ unit-test:
- junit.xml
build-dev:
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:16.14.2-alpine3.14
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:20.12.0-alpine3.19
stage: build
before_script:
- apk add git
......@@ -45,15 +45,15 @@ build-dev:
- yarn
- yarn build
- git config --global user.name build-token
- git config --global user.email "$GIT_USER"
- git config --global user.password "$GIT_PWD"
- git config user.email "$GIT_USER"
- git remote set-url origin https://"$GIT_USER":"$GIT_PWD"@forge.grandlyon.com/web-et-numerique/factory/llle_project/egl-konnector.git
- git config --global user.email build-token
- git config --global user.password "$BUILD_TOKEN"
- git config user.email build-token
- git remote set-url origin https://build-token:"$BUILD_TOKEN"@forge.grandlyon.com/web-et-numerique/factory/llle_project/egl-konnector.git
- git config --global credential.helper store
- yarn deploy-dev
build:
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:16.14.2-alpine3.14
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:20.12.0-alpine3.19
stage: build
before_script:
- apk add git
......@@ -62,10 +62,10 @@ build:
- yarn
- yarn build
- git config --global user.name build-token
- git config --global user.email "$GIT_USER"
- git config --global user.password "$GIT_PWD"
- git config user.email "$GIT_USER"
- git remote set-url origin https://"$GIT_USER":"$GIT_PWD"@forge.grandlyon.com/web-et-numerique/factory/llle_project/egl-konnector.git
- git config --global user.email build-token
- git config --global user.password "$BUILD_TOKEN"
- git config user.email build-token
- git remote set-url origin https://build-token:"$BUILD_TOKEN"@forge.grandlyon.com/web-et-numerique/factory/llle_project/egl-konnector.git
- git config --global credential.helper store
- yarn deploy
only:
......
v20.12.0
......@@ -5,4 +5,4 @@
"tabWidth": 2,
"trailingComma": "es5",
"arrowParens": "avoid"
}
}
\ No newline at end of file
......@@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [1.3.0](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector/compare/v1.2.5...v1.3.0) (2024-09-30)
### Features
* **SAU:** Add the instance name as a Sentry tag ([e15e17c](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector/commit/e15e17c89cb55c56ef0de4b8b68b3341d712e651))
* update prices ([f8c4c15](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector/commit/f8c4c15632e9f112585bae983426731f04bcc61c))
### Bug Fixes
* **data:** aborts if no data ([28ef855](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector/commit/28ef855892e5c9e49cb1e09ceea5c1899a49a192))
### [1.2.5](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector/compare/v1.2.4...v1.2.5) (2024-02-28)
......
{
"presets": [
[
"cozy-app",
{
"node": true,
"react": false,
"lib": true
}
]
]
}
{
"COZY_URL": "http://cozy.tools:8080/",
"fields": {
"eglBaseURL": "",
"eglAPIAuthKey": "",
"login": 1234567,
"password": ""
},
"COZY_PARAMETERS": {
"secret": {
"eglBaseURL": "",
"eglAPIAuthKey": "",
"boBaseUrl": "https://ecolyo-agent-rec.apps.grandlyon.com/"
}
}
}
}
\ No newline at end of file
{
"version": "1.2.5",
"version": "1.3.0",
"name": "EGL",
"type": "konnector",
"language": "node",
......
{
"name": "egl",
"version": "1.2.5",
"version": "1.3.0",
"description": "",
"repository": {
"type": "git",
......@@ -10,58 +10,33 @@
"author": "Grand Lyon",
"license": "AGPL-3.0",
"main": "./src/index.js",
"eslintConfig": {
"extends": [
"cozy-app"
]
},
"eslintIgnore": [
"build"
],
"husky": {
"hooks": {
"pre-commit": "yarn lint"
}
},
"scripts": {
"start": "node ./src/index.js",
"dev": "cozy-konnector-dev",
"standalone": "cozy-konnector-standalone",
"lint": "eslint src --fix",
"pretest": "npm run clean",
"check": "konitor check .",
"test": "jest",
"test:cov": "jest --coverage",
"clean": "rm -rf ./data",
"build": "webpack",
"lint": "eslint --fix .",
"deploy": "git-directory-deploy --directory build/ --branch ${DEPLOY_BRANCH:-build}",
"deploy-dev": "git-directory-deploy --directory build/ --branch ${DEPLOY_BRANCH:-build-dev}",
"cozyPublish": "cozy-app-publish --token $REGISTRY_TOKEN --build-commit $(git rev-parse ${DEPLOY_BRANCH:-build})",
"travisDeployKey": "./bin/generate_travis_deploy_key"
},
"dependencies": {
"@sentry/node": "7.30.0",
"@sentry/tracing": "7.30.0",
"axios": "1.2.2",
"cozy-konnector-libs": "4.56.4",
"jest": "^29.7.0",
"@sentry/node": "8.8.0",
"@sentry/tracing": "7.114.0",
"axios": "1.7.2",
"cozy-konnector-libs": "^5.11.0",
"luxon": "^3.4.3"
},
"devDependencies": {
"copy-webpack-plugin": "6.1.1",
"cozy-app-publish": "0.25.0",
"cozy-jobs-cli": "1.20.2",
"cozy-konnector-build": "1.4.4",
"eslint": "5.16.0",
"eslint-config-cozy-app": "1.6.0",
"eslint-plugin-prettier": "3.0.1",
"git-directory-deploy": "1.5.1",
"husky": "4.3.0",
"cozy-jobs-cli": "^2.4.2",
"cozy-konnector-build": "^1.7.0",
"jest": "^29.7.0",
"jest-junit": "^16.0.0",
"konitor": "0.10.2",
"standard-version": "^9.5.0",
"svgo": "1.3.2",
"webpack": "5.75.0",
"webpack-cli": "5.0.1"
"standard-version": "^9.5.0"
}
}
......@@ -14,7 +14,7 @@ function format(data) {
log('info', 'origin response size is: ' + data.length)
/** Filter loads where value is 0 */
const filteredData = data.filter(value => value.ValeurIndex !== 0)
let formattedLoads = []
const formattedLoads = []
for (let i = 1; i < filteredData.length; i++) {
const previousValue = filteredData[i - 1]
const currentValue = filteredData[i]
......
const { format } = require('../../src/helpers/format')
const { format } = require('./format')
const mockCaptureMessage = jest.fn()
jest.mock('@sentry/node', () => ({
......
const { log } = require('cozy-konnector-libs')
const axios = require('axios').default
const Sentry = require('@sentry/node')
const { DateTime } = require('luxon')
require('../types/types')
/**
* @param {string} boBaseUrl
*/
async function getPrices(boBaseUrl) {
const boWaterPricesUrl = new URL('/api/common/prices/1', boBaseUrl).href
try {
/** @type {Price[]} */
const prices = (await axios.get(boWaterPricesUrl)).data
return prices
} catch (error) {
log('error', 'Could not fetch BO prices')
Sentry.captureException(error, {
tags: {
section: 'getPrices',
},
})
return null
}
}
/**
* Apply the given prices to the given data array and return the result.
* @param {FormattedData[]} data
* @param {Price[]} fluidPrices
*/
async function applyPrices(data, fluidPrices) {
// Sort prices by descending start date
fluidPrices.sort(
(a, b) =>
DateTime.fromISO(b.startDate, { zone: 'UTC' }).toMillis() -
DateTime.fromISO(a.startDate, { zone: 'UTC' }).toMillis()
)
return data.map(load => {
// Select the first price that is before the load date
const loadDate = DateTime.fromObject(
{
year: load.year,
month: load.month,
day: load.day,
},
{ zone: 'UTC' }
)
const fluidPrice = fluidPrices.find(p => {
const startDate = DateTime.fromISO(p.startDate, { zone: 'UTC' })
return loadDate >= startDate
})
if (!fluidPrice) return load
return { ...load, price: fluidPrice.price * load.load }
})
}
module.exports = { getPrices, applyPrices }
const axios = require('axios')
const { getPrices, applyPrices } = require('../../src/helpers/prices')
jest.mock('axios')
jest.mock('cozy-konnector-libs', () => ({
log: jest.fn(),
}))
describe('getPrices', () => {
const boBaseUrl = 'https://example.com'
it('should return null when axios throws an error', async () => {
// Mock axios to throw an error
axios.get.mockRejectedValue(new Error('Network Error'))
const result = await getPrices(boBaseUrl)
expect(result).toBeNull()
})
})
describe('applyPrices', () => {
it('should apply prices to data', async () => {
const data = [
{ year: 2024, month: 1, day: 31, hour: 0, minute: 0, load: 10 },
{ year: 2024, month: 2, day: 1, hour: 0, minute: 0, load: 10 },
{ year: 2024, month: 2, day: 2, hour: 0, minute: 0, load: 10 },
]
const prices = [
{ startDate: '2024-01-31T00:00:00Z', price: 1 },
{ startDate: '2024-02-01T00:00:00Z', price: 2 },
{ startDate: '2024-02-02T00:00:00Z', price: 3 },
]
const result = await applyPrices(data, prices)
expect(result).toStrictEqual([
{
year: 2024,
month: 1,
day: 31,
hour: 0,
minute: 0,
load: 10,
price: 10,
},
{ year: 2024, month: 2, day: 1, hour: 0, minute: 0, load: 10, price: 20 },
{ year: 2024, month: 2, day: 2, hour: 0, minute: 0, load: 10, price: 30 },
])
})
it('should not apply prices if data is before prices', async () => {
const data = [
{ year: 2020, month: 1, day: 14, hour: 0, minute: 0, load: 10 },
]
const prices = [{ startDate: '2024-01-14T00:00:00Z', price: 1 }]
const result = await applyPrices(data, prices)
expect(result).toStrictEqual([
{ year: 2020, month: 1, day: 14, hour: 0, minute: 0, load: 10 },
])
})
it('should not apply prices if prices are empty', async () => {
const data = [
{ year: 2024, month: 1, day: 14, hour: 0, minute: 0, load: 10 },
]
const prices = []
const result = await applyPrices(data, prices)
expect(result).toStrictEqual([
{ year: 2024, month: 1, day: 14, hour: 0, minute: 0, load: 10 },
])
})
})
......@@ -13,12 +13,13 @@ function aggregateMonthlyLoad(data) {
const monthlyLoad = {}
for (const entry of data) {
const { year, month, load } = entry
const { year, month, load, price } = entry
const monthKey = `${year}-${month}`
if (!monthlyLoad[monthKey]) {
monthlyLoad[monthKey] = {
load: load,
price: price,
year: year,
month: month,
day: 0,
......@@ -28,6 +29,7 @@ function aggregateMonthlyLoad(data) {
}
} else {
monthlyLoad[monthKey].load += load
monthlyLoad[monthKey].price += price
}
}
......@@ -45,11 +47,12 @@ function aggregateYearlyLoad(data) {
const yearlyLoad = {}
for (const entry of data) {
const { year, load } = entry
const { year, load, price } = entry
if (!yearlyLoad[year]) {
yearlyLoad[year] = {
load: load,
price: price,
year: year,
month: 0,
day: 0,
......@@ -59,6 +62,7 @@ function aggregateYearlyLoad(data) {
}
} else {
yearlyLoad[year].load += load
yearlyLoad[year].price += price
}
}
......
require('./instrument.js') // Sentry initialization
const {
BaseKonnector,
log,
......@@ -10,9 +11,6 @@ const axios = require('axios').default
const { DateTime } = require('luxon')
const Sentry = require('@sentry/node')
const Tracing = require('@sentry/tracing') // Needed for tracking performance in Sentry
const { version } = require('../package.json')
const { isDev } = require('./helpers/env')
const { rangeDate } = require('./types/constants')
const {
aggregateMonthlyLoad,
......@@ -21,6 +19,7 @@ const {
filterFirstYearlyLoad,
} = require('./helpers/utils')
const { format } = require('./helpers/format')
const { getPrices, applyPrices } = require('./helpers/prices.js')
require('./types/types')
const manualExecution = process.env.COZY_JOB_MANUAL_EXECUTION === 'true'
......@@ -39,26 +38,6 @@ const endDateString = DateTime.now()
module.exports = new BaseKonnector(start)
/**
* Sentry configuration
*/
Sentry.init({
dsn:
'https://3f97baf46c2b44c2bd9e0c371abe3e05@grandlyon.errors.cozycloud.cc/2',
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 1.0,
release: version,
environment: isDev() ? 'development' : 'production',
debug: isDev(),
integrations: [
// enable HTTP calls tracing
new Sentry.Integrations.Http({ tracing: true }),
],
})
/**
* The start function is run by the BaseKonnector instance only when it receives all the account information (fields).
* When you run this connector in 'standalone' or 'dev' mode, the account information comes from the ./konnector-dev-config.json file.
......@@ -67,65 +46,71 @@ Sentry.init({
* @param {object} cozyParameters - Cozy platform parameters.
*/
async function start(fields, cozyParameters) {
const transaction = Sentry.startTransaction({
op: 'konnector',
name: 'EGL Konnector',
})
transaction.startChild({ op: 'Konnector starting' })
try {
// Local debug data
// const baseUrl = fields.eglBaseURL
// const apiAuthKey = fields.eglAPIAuthKey
const baseUrl = cozyParameters.secret.eglBaseURL
const eglBaseUrl = cozyParameters.secret.eglBaseURL
const boBaseUrl = cozyParameters.secret.boBaseUrl
const apiAuthKey = cozyParameters.secret.eglAPIAuthKey
log('info', 'Authenticating ...')
const response = await authenticate(
fields.login,
fields.password,
baseUrl,
eglBaseUrl,
apiAuthKey
)
log('info', 'Successfully logged in')
const eglData = await getData(response, baseUrl, apiAuthKey)
if (!eglData) {
let eglData = await getData(response, eglBaseUrl, apiAuthKey)
if (eglData.length === 0) {
log('debug', 'No data found')
transaction.setStatus(Tracing.SpanStatus.Ok)
transaction.finish()
return
}
log('info', 'Fetching BO prices')
const prices = await getPrices(boBaseUrl)
if (prices && prices.length > 0) {
log('info', 'Found BO prices, applying them to EGL data')
eglData = await applyPrices(eglData, prices)
}
log('debug', 'Process EGL daily data')
const filteredDays = await hydrateAndFilter(
const filterDayKeys = [...rangeDate.day.keys, 'load']
if (prices) filterDayKeys.push('price')
const daysToUpdate = await hydrateAndFilter(
eglData,
rangeDate.day.doctype,
{
keys: ['year', 'month', 'day', 'load'],
}
{ keys: filterDayKeys }
)
log('debug', 'Store EGL daily load data')
await updateOrCreate(
filteredDays,
daysToUpdate,
rangeDate.day.doctype,
rangeDate.day.keys
)
const { year: firstYear, month: firstMonth } = eglData[0]
log('debug', 'Aggregate EGL yearly load data')
log('debug', 'Aggregate EGL monthly load data')
const monthlyLoads = aggregateMonthlyLoad(eglData)
log('debug', 'Filter first month aggregate if already in database')
const filteredMonthlyLoads = filterFirstMonthlyLoad(
const filteredMonthlyLoads = await filterFirstMonthlyLoad(
firstMonth,
firstYear,
monthlyLoads
)
const filterMonthKeys = [...rangeDate.month.keys, 'load']
if (prices) filterMonthKeys.push('price')
const monthsToUpdate = await hydrateAndFilter(
filteredMonthlyLoads,
rangeDate.month.doctype,
{ keys: filterMonthKeys }
)
log('debug', 'Store aggregated EGL monthly load data')
await updateOrCreate(
filteredMonthlyLoads,
monthsToUpdate,
rangeDate.month.doctype,
rangeDate.month.keys
)
......@@ -134,17 +119,25 @@ async function start(fields, cozyParameters) {
const yearlyLoads = aggregateYearlyLoad(monthlyLoads)
log('debug', 'Filter first year aggregate if already in database')
const filteredYearlyLoads = filterFirstYearlyLoad(firstYear, yearlyLoads)
const filteredYearlyLoads = await filterFirstYearlyLoad(
firstYear,
yearlyLoads
)
const filterYearKeys = [...rangeDate.year.keys, 'load']
if (prices) filterYearKeys.push('price')
const yearsToUpdate = await hydrateAndFilter(
filteredYearlyLoads,
rangeDate.year.doctype,
{ keys: filterYearKeys }
)
log('debug', 'Store aggregated EGL yearly load data')
await updateOrCreate(
filteredYearlyLoads,
yearsToUpdate,
rangeDate.year.doctype,
rangeDate.year.keys
)
transaction.setStatus(Tracing.SpanStatus.Ok)
transaction.finish()
} catch (error) {
const errorMessage = `EGL konnector encountered an error. Response data: ${JSON.stringify(
error.message
......@@ -152,10 +145,9 @@ async function start(fields, cozyParameters) {
Sentry.captureMessage(errorMessage, {
tags: {
section: 'start',
login: fields.login,
},
})
transaction.setStatus(Tracing.SpanStatus.Aborted)
transaction.finish()
await Sentry.flush()
throw error
}
......@@ -173,45 +165,55 @@ async function start(fields, cozyParameters) {
* @returns {Promise<AuthResponse>} - The authentication response containing a token.
*/
async function authenticate(login, password, baseUrl, apiAuthKey) {
log('info', 'Authenticating ...')
const authRequest = {
method: 'post',
url: baseUrl + '/connect.aspx',
headers: {
AuthKey: apiAuthKey,
'Content-Type': 'application/x-www-form-urlencoded',
},
data: {
login: login,
pass: password,
return Sentry.startSpan(
{
name: 'authenticate',
},
}
async span => {
log('info', 'Authenticating ...')
const authRequest = {
method: 'post',
url: baseUrl + '/connect.aspx',
headers: {
AuthKey: apiAuthKey,
'Content-Type': 'application/x-www-form-urlencoded',
},
data: {
login: login,
pass: password,
},
}
try {
/** @type {AuthResponse} */
const respData = (await axios(authRequest)).data
try {
/** @type {AuthResponse} */
const respData = (await axios(authRequest)).data
if (respData.codeRetour === 100) {
return respData
}
const errorMessage = `Authentication failed. Response data: ${respData?.libelleRetour}`
log('error', errorMessage)
throw new Error(errors.VENDOR_DOWN)
} catch (error) {
log('error', error.response?.data)
Sentry.captureException(error, {
tags: {
section: 'authenticate',
},
extra: {
compte: login,
},
})
if (error.response?.data.codeRetour === -4) {
throw new Error(errors.LOGIN_FAILED)
if (respData.codeRetour === 100) {
return respData
}
const errorMessage = `Authentication failed. Response data: ${respData?.libelleRetour}`
log('error', errorMessage)
log('error', `Code retour: ${respData?.codeRetour}`)
throw new Error(errors.VENDOR_DOWN)
} catch (error) {
log('error', error.response?.data)
Sentry.captureException(error, {
tags: {
section: 'authenticate',
},
extra: {
compte: login,
},
})
if (error.response?.data.codeRetour === -4) {
span.setStatus({ code: 2, message: 'unauthenticated' })
throw new Error(errors.LOGIN_FAILED)
}
span.setStatus({ code: 2, message: 'internal_error' })
throw new Error(errors.VENDOR_DOWN)
}
}
throw new Error(errors.VENDOR_DOWN)
}
)
}
/**
......@@ -225,66 +227,74 @@ async function authenticate(login, password, baseUrl, apiAuthKey) {
* @returns {Promise<FormattedData[]>} - A promise that resolves to the retrieved and formatted data.
*/
async function getData(response, baseUrl, apiAuthKey) {
const dataRequest = {
method: 'post',
url: baseUrl + '/getAllAgregatsByAbonnement.aspx',
headers: {
AuthKey: apiAuthKey,
'Content-Type': 'application/x-www-form-urlencoded',
},
data: {
token: response.resultatRetour.token,
num_abt: response.resultatRetour.num_abt,
date_debut: startDateString,
date_fin: endDateString,
return Sentry.startSpan(
{
name: 'getData',
},
}
async span => {
const dataRequest = {
method: 'post',
url: baseUrl + '/getAllAgregatsByAbonnement.aspx',
headers: {
AuthKey: apiAuthKey,
'Content-Type': 'application/x-www-form-urlencoded',
},
data: {
token: response.resultatRetour.token,
num_abt: response.resultatRetour.num_abt,
date_debut: startDateString,
date_fin: endDateString,
},
}
try {
/** @type {GetDataResponse} */
const respData = (await axios(dataRequest)).data
try {
/** @type {GetDataResponse} */
const respData = (await axios(dataRequest)).data
switch (respData.codeRetour) {
case 100:
// Sort data by date
respData.resultatRetour.sort(function(a, b) {
return new Date(a.DateReleve) - new Date(b.DateReleve)
switch (respData.codeRetour) {
case 100:
// Sort data by date
respData.resultatRetour.sort(
(a, b) => new Date(a.DateReleve) - new Date(b.DateReleve)
)
return format(respData.resultatRetour)
case -2:
log(
'error',
`Get data failed. codeRetour -2. ${respData.libelleRetour}`
)
throw errors.LOGIN_FAILED
case -1:
log(
'error',
`Get data failed. codeRetour -1. ${respData.libelleRetour}`
)
throw errors.VENDOR_DOWN
default:
log(
'error',
`Get data failed. ${respData.codeRetour}. ${respData.libelleRetour}`
)
log('error', respData)
throw errors.UNKNOWN_ERROR
}
} catch (error) {
log('debug', error.message)
Sentry.captureException(error, {
tags: {
section: 'getData',
},
extra: {
start: startDateString,
end: endDateString,
},
})
return format(respData.resultatRetour)
case -2:
log(
'error',
`Get data failed. codeRetour -2. ${respData.libelleRetour}`
)
throw errors.LOGIN_FAILED
case -1:
log(
'error',
`Get data failed. codeRetour -1. ${respData.libelleRetour}`
)
throw errors.VENDOR_DOWN
default:
log(
'error',
`Get data failed. ${respData.codeRetour}. ${respData.libelleRetour}`
)
throw errors.UNKNOWN_ERROR
}
} catch (error) {
log('debug', error.message)
Sentry.captureException(error, {
tags: {
section: 'getData',
},
extra: {
start: startDateString,
end: endDateString,
},
})
if (axios.isAxiosError(error)) {
throw new Error(errors.VENDOR_DOWN)
span.setStatus({ code: 2, message: 'internal_error' })
if (axios.isAxiosError(error)) {
throw new Error(errors.VENDOR_DOWN)
}
throw error
}
}
throw error
}
)
}
const Sentry = require('@sentry/node')
const { version } = require('../package.json')
const { isDev } = require('./helpers/env')
Sentry.init({
dsn: 'https://3f97baf46c2b44c2bd9e0c371abe3e05@grandlyon.errors.cozycloud.cc/2',
tracesSampleRate: 1.0,
release: version,
environment: isDev() ? 'development' : 'production',
debug: isDev(),
autoSessionTracking: true,
})
Sentry.setTag('instance', process.env.COZY_URL)
......@@ -8,6 +8,7 @@
* @property {number} day - The day of the data point.
* @property {number} hour - The hour of the data point (in this case, always 0).
* @property {number} minute - The minute of the data point (in this case, always 0).
* @property {number} price - The price of the data point.
* @property {string} type - The type of the data point.
*/
......@@ -37,3 +38,11 @@
* @property {number} num_abt
* @property {string} token
*/
/**
* @typedef {Object} Price
* @property {number} fluidtype
* @property {number} price
* @property {string} startDate
* @property {string} endDate
*/
var path = require('path')
const CopyPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')
const fs = require('fs')
const SvgoInstance = require('svgo')
const entry = require('./package.json').main
const readManifest = () =>
JSON.parse(fs.readFileSync(path.join(__dirname, './manifest.konnector')))
const svgo = new SvgoInstance({
plugins: [
{
inlineStyles: { onlyMatchedOnce: false },
},
],
})
let iconName
try {
iconName = JSON.parse(fs.readFileSync('manifest.konnector', 'utf8')).icon
// we run optimize only on SVG
if (!iconName.match(/\.svg$/)) iconName = null
} catch (e) {
// console.error(`Unable to read the icon path from manifest: ${e}`)
}
const appIconRX = iconName && new RegExp(`[^/]*/${iconName}`)
module.exports = {
entry,
target: 'node',
mode: 'none',
output: {
path: path.join(__dirname, 'build'),
filename: 'index.js',
},
plugins: [
new CopyPlugin({
patterns: [
{ from: 'manifest.konnector' },
{ from: 'package.json' },
{ from: 'README.md' },
{ from: 'assets', transform: optimizeSVGIcon },
{ from: '.travis.yml' },
{ from: 'LICENSE' },
],
}),
new webpack.DefinePlugin({
__WEBPACK_PROVIDED_MANIFEST__: JSON.stringify(readManifest()),
}),
],
module: {
// to ignore the warnings like :
// WARNING in ../libs/node_modules/bindings/bindings.js 76:22-40
// Critical dependency: the request of a dependency is an expression
// Since we cannot change this dependency. I think it won't hide more important messages
exprContextCritical: false,
},
}
function optimizeSVGIcon(buffer, path) {
if (appIconRX && path.match(appIconRX)) {
return svgo.optimize(buffer).then(resp => resp.data)
} else {
return buffer
}
}
module.exports = require('cozy-konnector-build/webpack.config')
This diff is collapsed.