From 222ab8dbf860628f6d8ebcc99fa274c4e52ec883 Mon Sep 17 00:00:00 2001 From: PKulkoRaccoonGang Date: Mon, 11 Sep 2023 18:12:33 +0300 Subject: [PATCH 1/5] feat: added Segment track for CLI scripts --- bin/paragon-scripts.js | 3 +++ component-generator/index.js | 4 ++-- component-generator/utils.js | 20 -------------------- utils.js | 22 ++++++++++++++++++++++ 4 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 utils.js diff --git a/bin/paragon-scripts.js b/bin/paragon-scripts.js index dbc9329699..72105dbd25 100755 --- a/bin/paragon-scripts.js +++ b/bin/paragon-scripts.js @@ -5,6 +5,7 @@ const helpCommand = require('../lib/help'); const buildTokensCommand = require('../lib/build-tokens'); const replaceVariablesCommand = require('../lib/replace-variables'); const buildScssCommand = require('../lib/build-scss'); +const { sendTrackInfo } = require('../utils'); const COMMANDS = { /** @@ -173,6 +174,8 @@ const COMMANDS = { const [command, ...commandArgs] = process.argv.slice(2); const executor = COMMANDS[command]; + sendTrackInfo(command, 'trackCLICommands'); + if (!executor) { // eslint-disable-next-line no-console console.log(chalk.red.bold('Unknown command. Usage: paragon .')); diff --git a/component-generator/index.js b/component-generator/index.js index f27712a22e..99db7abb9d 100644 --- a/component-generator/index.js +++ b/component-generator/index.js @@ -4,17 +4,17 @@ const path = require('path'); const { COMPONENT_FILES } = require('./constants'); const { validateComponentName, - sendTrackInfo, createFile, addComponentToExports, addComponentToGit, } = require('./utils'); +const { sendTrackInfo } = require('../utils'); program .argument('', 'Component must have a name', validateComponentName) .action((componentName) => { // send data to analytics - sendTrackInfo(componentName); + sendTrackInfo(componentName, 'trackGenerateComponent'); const componentDir = path.resolve(__dirname, `../src/${componentName}`); // create directory for the component files fs.mkdirSync(componentDir); diff --git a/component-generator/utils.js b/component-generator/utils.js index 5d4b4c2585..c06bbd6ced 100644 --- a/component-generator/utils.js +++ b/component-generator/utils.js @@ -32,25 +32,6 @@ function validateComponentName(value) { return value; } -/** - * Sends request to the Netlify function to inform about generate-component usage. - * @param {string} componentName - component name - */ -function sendTrackInfo(componentName) { - const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; - if (TRACK_ANONYMOUS_ANALYTICS) { - const url = `${BASE_URL}/.netlify/functions/trackGenerateComponent`; - axios.post(url, { componentName }) - .then(result => { - // eslint-disable-next-line no-console - console.log(`Track info is successfully sent (status ${result.status})`); - }).catch(error => { - // eslint-disable-next-line no-console - console.log(`Track info request failed (${error})`); - }); - } -} - /** * Creates a file for the component based on the template. * Note that 'componentName' string is a reserved placeholder, @@ -97,7 +78,6 @@ function addComponentToGit(componentName) { } exports.validateComponentName = validateComponentName; -exports.sendTrackInfo = sendTrackInfo; exports.createFile = createFile; exports.addComponentToExports = addComponentToExports; exports.addComponentToGit = addComponentToGit; diff --git a/utils.js b/utils.js new file mode 100644 index 0000000000..e36e96b2dd --- /dev/null +++ b/utils.js @@ -0,0 +1,22 @@ +const axios = require('axios'); + +/** + * Sends request to the Netlify function to inform about specified event. + * @param {string} eventName - tracking event name + */ +function sendTrackInfo(eventName, trackFunctionName) { + const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; + if (TRACK_ANONYMOUS_ANALYTICS) { + const url = `${BASE_URL}/.netlify/functions/${trackFunctionName}`; + axios.post(url, { eventName }) + .then(result => { + // eslint-disable-next-line no-console + console.log(`Track info is successfully sent (status ${result.status})`); + }).catch(error => { + // eslint-disable-next-line no-console + console.log(`Track info request failed (${error})`); + }); + } +} + +module.exports = { sendTrackInfo }; From cb9dcb813d302f5633bc423bf7cb24dd3c411a7d Mon Sep 17 00:00:00 2001 From: PKulkoRaccoonGang Date: Tue, 12 Sep 2023 16:19:59 +0300 Subject: [PATCH 2/5] refactor: refactoring after review --- package-lock.json | 36 ------------------- www/netlify/functions/trackCLICommands.js | 23 ++++++++++++ .../functions/trackGenerateComponent.js | 4 +-- 3 files changed, 25 insertions(+), 38 deletions(-) create mode 100644 www/netlify/functions/trackCLICommands.js diff --git a/package-lock.json b/package-lock.json index 10835df16a..11ae322957 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12761,42 +12761,6 @@ "node": "*" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/child_process": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", diff --git a/www/netlify/functions/trackCLICommands.js b/www/netlify/functions/trackCLICommands.js new file mode 100644 index 0000000000..be1f9265a0 --- /dev/null +++ b/www/netlify/functions/trackCLICommands.js @@ -0,0 +1,23 @@ +const { v4: uuidv4 } = require('uuid'); +const Analytics = require('analytics-node'); + +const analytics = new Analytics(process.env.SEGMENT_KEY); + +exports.handler = async function eventHandler(event) { + // Only allow POST + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method Not Allowed' }; + } + const { eventName } = JSON.parse(event.body); + // dispatch event to Segment + analytics.track({ + anonymousId: uuidv4(), + event: 'openedx.paragon.functions.track-cli-commands.run', + properties: { eventName }, + }); + + return { + statusCode: 200, + body: JSON.stringify({ success: true }), + }; +}; diff --git a/www/netlify/functions/trackGenerateComponent.js b/www/netlify/functions/trackGenerateComponent.js index b0b29ed3b3..30d149d22f 100644 --- a/www/netlify/functions/trackGenerateComponent.js +++ b/www/netlify/functions/trackGenerateComponent.js @@ -8,12 +8,12 @@ exports.handler = async function eventHandler(event) { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; } - const { componentName } = JSON.parse(event.body); + const { eventName } = JSON.parse(event.body); // dispatch event to Segment analytics.track({ anonymousId: uuidv4(), event: 'openedx.paragon.functions.track-generate-component.created', - properties: { componentName }, + properties: { eventName }, }); return { From e6ccd3579b814306618a94a2db41be7ecaeb3867 Mon Sep 17 00:00:00 2001 From: PKulkoRaccoonGang Date: Mon, 30 Oct 2023 17:14:22 +0200 Subject: [PATCH 3/5] refactor: refactoring after review --- component-generator/utils.js | 1 - package-lock.json | 5 +++-- package.json | 2 +- utils.js | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/component-generator/utils.js b/component-generator/utils.js index c06bbd6ced..f742c3bff5 100644 --- a/component-generator/utils.js +++ b/component-generator/utils.js @@ -1,7 +1,6 @@ const { InvalidOptionArgumentError } = require('commander'); const fs = require('fs'); const path = require('path'); -const axios = require('axios'); const { exec } = require('child_process'); require('dotenv').config(); diff --git a/package-lock.json b/package-lock.json index 11ae322957..db03eb5a55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ ], "dependencies": { "@popperjs/core": "^2.11.4", + "axios": "^0.27.2", "bootstrap": "^4.6.2", "chalk": "^4.1.2", "child_process": "^1.0.2", @@ -86,7 +87,6 @@ "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.22.0", "@typescript-eslint/parser": "^5.22.0", - "axios": "^0.27.2", "axios-mock-adapter": "^1.21.1", "babel-jest": "^28.1.2", "babel-loader": "^8.2.4", @@ -9639,7 +9639,8 @@ }, "node_modules/axios": { "version": "0.27.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { "follow-redirects": "^1.14.9", "form-data": "^4.0.0" diff --git a/package.json b/package.json index 2e13950768..80cc9590a0 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ }, "dependencies": { "@popperjs/core": "^2.11.4", + "axios": "^0.27.2", "bootstrap": "^4.6.2", "chalk": "^4.1.2", "child_process": "^1.0.2", @@ -125,7 +126,6 @@ "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.22.0", "@typescript-eslint/parser": "^5.22.0", - "axios": "^0.27.2", "axios-mock-adapter": "^1.21.1", "babel-jest": "^28.1.2", "babel-loader": "^8.2.4", diff --git a/utils.js b/utils.js index e36e96b2dd..4481b11112 100644 --- a/utils.js +++ b/utils.js @@ -3,6 +3,7 @@ const axios = require('axios'); /** * Sends request to the Netlify function to inform about specified event. * @param {string} eventName - tracking event name + * @param {string} trackFunctionName - tracking function name */ function sendTrackInfo(eventName, trackFunctionName) { const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; From 9787ccb07c50fa6806c6cc5a03ab9ed2451726ec Mon Sep 17 00:00:00 2001 From: PKulkoRaccoonGang Date: Tue, 31 Oct 2023 18:53:34 +0200 Subject: [PATCH 4/5] refactor: refactoring after review --- bin/paragon-scripts.js | 2 +- component-generator/index.js | 2 +- utils.js | 10 ++++---- ...ackCLICommands.js => sendAnalyticsData.js} | 6 ++--- .../functions/trackGenerateComponent.js | 25 ++++++------------- 5 files changed, 17 insertions(+), 28 deletions(-) rename www/netlify/functions/{trackCLICommands.js => sendAnalyticsData.js} (77%) diff --git a/bin/paragon-scripts.js b/bin/paragon-scripts.js index 72105dbd25..9ed5e0beda 100755 --- a/bin/paragon-scripts.js +++ b/bin/paragon-scripts.js @@ -174,7 +174,7 @@ const COMMANDS = { const [command, ...commandArgs] = process.argv.slice(2); const executor = COMMANDS[command]; - sendTrackInfo(command, 'trackCLICommands'); + sendTrackInfo('openedx.paragon.cli-command.used', { command }); if (!executor) { // eslint-disable-next-line no-console diff --git a/component-generator/index.js b/component-generator/index.js index 99db7abb9d..7f37f7bf9b 100644 --- a/component-generator/index.js +++ b/component-generator/index.js @@ -14,7 +14,7 @@ program .argument('', 'Component must have a name', validateComponentName) .action((componentName) => { // send data to analytics - sendTrackInfo(componentName, 'trackGenerateComponent'); + sendTrackInfo('openedx.paragon.functions.track-generate-component.created', { componentName }); const componentDir = path.resolve(__dirname, `../src/${componentName}`); // create directory for the component files fs.mkdirSync(componentDir); diff --git a/utils.js b/utils.js index 4481b11112..667932a4e8 100644 --- a/utils.js +++ b/utils.js @@ -2,14 +2,14 @@ const axios = require('axios'); /** * Sends request to the Netlify function to inform about specified event. - * @param {string} eventName - tracking event name - * @param {string} trackFunctionName - tracking function name + * @param {string} eventId - tracking event id + * @param {object} properties - tracking properties */ -function sendTrackInfo(eventName, trackFunctionName) { +function sendTrackInfo(eventId, properties) { const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; if (TRACK_ANONYMOUS_ANALYTICS) { - const url = `${BASE_URL}/.netlify/functions/${trackFunctionName}`; - axios.post(url, { eventName }) + const url = `${BASE_URL}/.netlify/functions/sendTrackData`; + axios.post(url, { eventId, properties }) .then(result => { // eslint-disable-next-line no-console console.log(`Track info is successfully sent (status ${result.status})`); diff --git a/www/netlify/functions/trackCLICommands.js b/www/netlify/functions/sendAnalyticsData.js similarity index 77% rename from www/netlify/functions/trackCLICommands.js rename to www/netlify/functions/sendAnalyticsData.js index be1f9265a0..964bf57869 100644 --- a/www/netlify/functions/trackCLICommands.js +++ b/www/netlify/functions/sendAnalyticsData.js @@ -8,12 +8,12 @@ exports.handler = async function eventHandler(event) { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; } - const { eventName } = JSON.parse(event.body); + const { eventId, properties } = JSON.parse(event.body); // dispatch event to Segment analytics.track({ anonymousId: uuidv4(), - event: 'openedx.paragon.functions.track-cli-commands.run', - properties: { eventName }, + event: eventId, + properties, }); return { diff --git a/www/netlify/functions/trackGenerateComponent.js b/www/netlify/functions/trackGenerateComponent.js index 30d149d22f..8090e88369 100644 --- a/www/netlify/functions/trackGenerateComponent.js +++ b/www/netlify/functions/trackGenerateComponent.js @@ -1,23 +1,12 @@ -const { v4: uuidv4 } = require('uuid'); -const Analytics = require('analytics-node'); - -const analytics = new Analytics(process.env.SEGMENT_KEY); +const { handler: actualHandler } = require('./sendAnalyticsData'); exports.handler = async function eventHandler(event) { - // Only allow POST - if (event.httpMethod !== 'POST') { - return { statusCode: 405, body: 'Method Not Allowed' }; - } - const { eventName } = JSON.parse(event.body); - // dispatch event to Segment - analytics.track({ - anonymousId: uuidv4(), - event: 'openedx.paragon.functions.track-generate-component.created', - properties: { eventName }, + const body = JSON.parse(event.body); + event.body = JSON.stringify({ + ...body, + eventId: 'openedx.paragon.functions.track-generate-component.created', + properties: { componentName: body.componentName }, }); - return { - statusCode: 200, - body: JSON.stringify({ success: true }), - }; + return actualHandler(event); }; From cae891edcf9b37ce4f13300716baf02f8779bc10 Mon Sep 17 00:00:00 2001 From: PKulkoRaccoonGang Date: Wed, 1 Nov 2023 16:21:54 +0200 Subject: [PATCH 5/5] refactor: code refactoring --- bin/paragon-scripts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/paragon-scripts.js b/bin/paragon-scripts.js index 9ed5e0beda..8b35a7c5a4 100755 --- a/bin/paragon-scripts.js +++ b/bin/paragon-scripts.js @@ -174,8 +174,6 @@ const COMMANDS = { const [command, ...commandArgs] = process.argv.slice(2); const executor = COMMANDS[command]; - sendTrackInfo('openedx.paragon.cli-command.used', { command }); - if (!executor) { // eslint-disable-next-line no-console console.log(chalk.red.bold('Unknown command. Usage: paragon .')); @@ -184,9 +182,11 @@ const COMMANDS = { try { await executor.executor(commandArgs); + sendTrackInfo('openedx.paragon.cli-command.used', { command, status: 'success' }); } catch (error) { // eslint-disable-next-line no-console console.error(chalk.red.bold('An error occurred:', error.message)); + sendTrackInfo('openedx.paragon.cli-command.used', { command, status: 'error', errorMsg: error.message }); process.exit(1); } })();