{"_id":"@alu0101233499org/espree-logging-solution","_rev":"1-94186f50b174f4f7fc0b4287151f7df4","name":"@alu0101233499org/espree-logging-solution","dist-tags":{"latest":"0.3.1"},"versions":{"0.3.0":{"name":"@alu0101233499org/espree-logging-solution","author":{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"},"description":"Adds logs to javascript code","type":"module","bin":{"funlog":"bin/log.js"},"repository":{"type":"git","url":"git+https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499.git"},"scripts":{"log":"./bin/log.js -h","test":"mocha test/test.mjs","cov":"nyc --reporter=lcov --reporter=text npm run test","doc":"jsdoc ./src/*js"},"nyc":{"all":true,"include":["src/*.js"]},"dependencies":{"acorn":"^8.8.2","chai":"^4.3.6","commander":"^10.0.0","escodegen":"^2.0.0","espree":"^9.4.1","estraverse":"^5.2.0","nyc":"^15.1.0","underscore":"^1.12.0"},"version":"0.3.0","devDependencies":{"jsdoc":"^4.0.2","mocha":"^10.2.0"},"main":"salida.js","directories":{"test":"test"},"license":"ISC","gitHead":"09c0bce7f37afe6f7b3a2c77fbb84cc9fed1c0aa","bugs":{"url":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499/issues"},"homepage":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499#readme","_id":"@alu0101233499org/espree-logging-solution@0.3.0","_nodeVersion":"19.6.0","_npmVersion":"9.4.0","dist":{"integrity":"sha512-fzBXiZIyPHaa4YqRQ+gbMs7tj39SAAHBe4pc1kuv+/qcplp37J5AhhnE80EiQ8EcawmrsyCB/+zxUAKqk4aeMA==","shasum":"d5ede6a51ffc62856bdc80cba3346e2d9a3d39b4","tarball":"https://registry.npmjs.org/@alu0101233499org/espree-logging-solution/-/espree-logging-solution-0.3.0.tgz","fileCount":79,"unpackedSize":2303956,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0i9RRrSTRLLg1EGAWvbndtY9UuanF/yIPVsm25OUaYAIgaxBBKdXv9QYOTqvkteNT6aFK+veBorYKUey6Hflqf3c="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkANC6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqkLg//SXqgzB4w/Ph3NtklCZ4cFrKIXYSPqGHFW+T+9PC9+liCRnqK\r\nls1h4SwTs3JWieC89csKbVNsPlXs63hjXjpONr7Cr6S+UR85sW5BfhBkBgc3\r\nL5tgbmq+JqcjnOUmNSwwqcPgx54w61s+jkkjBegTWRog78q1PNjvLBUxWtGM\r\nqeisROrELhfF0XM81Q+lNRoHiFX9TZ5cB7BiozIXBYg+5RF8qOXy1yRcHRnK\r\noRHKLxNNoFe6QCy/q3Tq5n19ZCL/sWWa0wZfTDejTDZpDFHjBddK2OqJrcz3\r\nliSlRsAxy1Cfs0fvGiT8C21ug4fJbVLTBwvODYRTNSNzHH6pNmHcQH3IZ4nX\r\npaUn/S9rGUrjzC++j18S7dVO8ICdLz9sdhEtKico6u+Cw/VH6sLB6sM9Z6r5\r\nOZIReWjtLooaxdNqePSnYlU9Mka+UmchnvUGyqkBtYCF5+yesnwwaTzz7kxB\r\nhyglTYqu0xB5DGKd0H4dHNOdu8i748ZXUI0yjQuUZ2pZc4UVKGBBE0NtkDxw\r\nGgecbpds//zFtOIbQZb/IOgDVvLTbheInu31Gk0yG+YVOxrh8kQzrA6lHT0J\r\n9U4uBEeFmhl43cgyXIjMj1oLbbKr9sM18eFAyOM6XTPe7cOMTmaETZd52D2Q\r\nNcEqzpO+4indY0gLJmnog/3BXcME9kT+oNo=\r\n=1T5g\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"},"maintainers":[{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/espree-logging-solution_0.3.0_1677775034528_0.6140318322671738"},"_hasShrinkwrap":false},"0.3.1":{"name":"@alu0101233499org/espree-logging-solution","author":{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"},"description":"Adds logs to javascript code","type":"module","bin":{"funlog":"bin/log.js"},"repository":{"type":"git","url":"git+https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499.git"},"scripts":{"log":"./bin/log.js -h","test":"mocha test/test.mjs","cov":"nyc --reporter=lcov --reporter=text npm run test","doc":"jsdoc ./src/*js"},"nyc":{"all":true,"include":["src/*.js"]},"dependencies":{"@alu0101233499org/espree-logging-solution":"^0.3.0","acorn":"^8.8.2","chai":"^4.3.6","commander":"^10.0.0","escodegen":"^2.0.0","espree":"^9.4.1","estraverse":"^5.2.0","nyc":"^15.1.0","underscore":"^1.12.0"},"version":"0.3.1","devDependencies":{"jsdoc":"^4.0.2","mocha":"^10.2.0"},"main":"salida.js","directories":{"test":"test"},"license":"ISC","gitHead":"66d76946cd309b210e042ab6e1b581471f15fb59","bugs":{"url":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499/issues"},"homepage":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499#readme","_id":"@alu0101233499org/espree-logging-solution@0.3.1","_nodeVersion":"19.6.0","_npmVersion":"9.4.0","dist":{"integrity":"sha512-zzy29hqZgXDnzVbv+nBYrhkGrckSYc81FpF/1bvpJTvg13ywcpU9swN0rNnfTqxzFHNeg5Ibc/fe0oaWedAM+w==","shasum":"b8adeefb58a85331544cf3066a4d9085b7beff25","tarball":"https://registry.npmjs.org/@alu0101233499org/espree-logging-solution/-/espree-logging-solution-0.3.1.tgz","fileCount":80,"unpackedSize":2390204,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFJxowb4WcwuIojIPQ5TYJZV3eh8XmFD3zVmSJPtScgzAiAp/4pxd8O3yhLzaiUFOCLNzJyqfSfhtpDjUNwTnSVS8w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkANWhACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoO+A/+LM5hjkwJhqUYrUwS2Fyq+8NrzrXYcOqBtADYiixmaDaRjU1L\r\ndWFmEsk40TBvq13VJQ7giJMWlovChvIuZ4YDqi0kfzvl1UfRMkhv+YcB1qGK\r\nmXnHTaFjtr4QckudJu9u+z6ocjyJnRHtK4189DufRI3Ma+Wbqpaey3FADrD2\r\nFCq6RTGUpq2Qyt0F6UPn/QoO9Jvsl/Vz06Yci+2kFM9bRNaz6JhWSMl4TNU0\r\nYWWy4sqNGhlQDzi6hrI+4ufPZZAHi8JuxYm6Uiy1E2vhuJONx5p66kxW8WWP\r\nwV0jcq22nO/HFqaxceYc5Rlpc2Qsicm/Zv0yBwuB2Vu2EFdDlJT8Aaz2eWqZ\r\nZJ3fbnIuHx04cyM7Dd1f8idgCvlN1wEnZqpxJ47WzaJCax1Y2zHY+Lzj9mAs\r\nsitCffepw/vbjEX4C5ZWxut7IBEQV8GIwOrby5cpyTuHx1+yk7sPoS+clTYm\r\nuHkF3KfzvboeD3Ucrx8pZ1yWaXfmEOd84DlkciTUgcYzrq3KnvXXp+i2P08m\r\nnwTzwEMre3MZbAvfsMmvHjWjt64iX1576IvD2SPapBJdzVzoNR7QdF1y85ok\r\niyLBMqYK+gPH2qGjtagnVWobLc9ienzfiiU30QoBmfVuRBFnXOGphapRt/8S\r\no4HzzqXVRRNP8qjnm+syX3FlPkD0FUchOu4=\r\n=z+5M\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"},"maintainers":[{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/espree-logging-solution_0.3.1_1677776289634_0.07975936424911634"},"_hasShrinkwrap":false}},"time":{"created":"2023-03-02T16:37:14.447Z","0.3.0":"2023-03-02T16:37:14.810Z","modified":"2023-03-02T16:58:09.929Z","0.3.1":"2023-03-02T16:58:09.815Z"},"maintainers":[{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"}],"description":"Adds logs to javascript code","homepage":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499#readme","repository":{"type":"git","url":"git+https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499.git"},"author":{"name":"alu0101233499org","email":"alu0101233499@ull.edu.es"},"bugs":{"url":"https://github.com/ULL-ESIT-PL-2223/espree-logging-gabriel-perez-gonzalez-alu0101233499/issues"},"license":"ISC","readme":"# Assignment: Espree Logging\n\n[![Open in Codespaces](https://classroom.github.com/assets/launch-codespace-f4981d0f882b2a3f0472912d15f9806d57e124e0fc890972558857b51b24a6f9.svg)](https://classroom.github.com/open-in-codespaces?assignment_repo_id=10311247)\n\nIn this assignment, we must have done the following main objectives:\n\n* Show the function's name each time we enter a function.\n* Show the function's parameters each time we enter a function.\n* Show the line where the function was initialized.\n\nThese steps will be executed each time the program encounters a **Function Declaration**, **Function Expression** or **Arrow Function**.\n\nThe `logging-espree.js` code was modified in order to show all the values I said previously:\nExample:\n\n```javascript\nfunction foo(a, b) {\n    var x = 'blah';\n    var y = (function (z) {\n        return z + 3;\n    })(2);\n}\n\nfoo(1, 'wut', 3);\n```\n\n```javascript\nfunction foo(a, b) {\n    console.log(`Entering foo(${ a }, ${ b }) at line 1.`);\n    var x = 'blah';\n    var y = function (z) {\n        console.log(`Entering <anonymous function>(${ z }) at line 3.`);\n        return z + 3;\n    }(2);\n}\n\nfoo(1, 'wut', 3);\n```\n\n## Task 1: CLI with [Commander.js](https://www.npmjs.com/package/commander)\n\nFor the first task, as usual, I created a **CLI** with *Commmander*. The code was almost complete, but I added a name to the program.\nThe result is the following one:\n\n![Commander](img/commander.png)\n\nThe name is in the *Usage* section. It's default value is *log*, but I changed it to *./bin/log.js*.\n\n## Task 2: Scripts in *package.json* and imported modules\n\nThe first thing was to add some dependencies in order to work with tests, make better documentation reports and use code coverage. The following lines represent the dependencies I added:\n\n```javascript\n\"chai\": \"^4.3.6\",\n\"nyc\": \"^15.1.0\",\n\"jsdoc\": \"^4.0.2\"\n```\n\nAlso, I added a couple of scripts to the *package.json* file, so I can carry on some tasks a little easier.\n\n```javascript\n\"scripts\": {\n    \"log\": \"./bin/log.js -h\",\n    \"test\": \"mocha\",\n    \"cov\": \"nyc --reporter=lcov --reporter=text npm run test\",\n    \"doc\": \"jsdoc ./src\"\n},\n```\n\n## Task 3: Add function and parameters names\n\nTo fulfill this task, I needed to complete the following functions:\n\n* *addLogging(code)*: Allows to build the AST and traverses it. It's main objective is to call the *addBeforeCode(node)* function in order to modify the **AST**, only in the required functions. It is important to say that the *ecmaVersion* in the first line is necessary if we want to work with backticks (``). This occurs because **Espree** does not support them in old versions.\n\n    ```javascript\n    export function addLogging(code) {\n        let ast = espree.parse(code, {ecmaVersion: 12});\n        estraverse.traverse(ast, {\n        enter: function(node, parent) {\n            if (node.type === 'FunctionDeclaration' ||\n                node.type === 'FunctionExpression') {\n                addBeforeCode(node);\n            }\n        }\n        });\n        return escodegen.generate(ast);\n    }\n    ```\n\n* *addBeforeCode(node)*: Allows to modify the **AST**, inserting code in it. All I had to do was to take the name of the function and it's arguments. With that, I created a string that has all the information.\n\n    ```javascript\n    function addBeforeCode(node) {\n        let parameters = '';\n\n        // Function name.\n        let name = node.id ? node.id.name : '<anonymous function>';\n\n        // Function parameters.\n        if (node.params.length != 0) {\n            parameters = node.params.map(param => ` \\${ ${param.name} }`);\n            parameters[0] = parameters[0].slice(1);\n        }\n\n        // Creating the code to insert.\n        let beforeCode = `console.log(\\`Entering ${name}(${parameters})\\`);`;\n\n        // Creating the new node.\n        let beforeNodes = espree.parse(beforeCode, {ecmaVersion: 12}).body;\n\n        // Adding the new node.\n        node.body.body = beforeNodes.concat(node.body.body);\n    }\n    ```\n\nIf we run the code with the following function:\n\n```javascript\nfunction foo(a, b) {\n    var x = 'blah';\n    var y = (function (z) {\n        return z + 3;\n    })(2);\n}\n```\n\nThe result shows this, at this point:\n\n![First try](img/try1.png)\n\n## Task 4: Arrow functions supported\n\nThis task is easily acomplished if we modify the *addLogging(code)* function. The only thing that is needed is to change the conditional clause, adding a new condition that supports **ArrowFunctionExpression**. With this, the task is completed.\n\n```javascript\nexport function addLogging(code) {\n    let ast = espree.parse(code, {ecmaVersion: 12});\n    estraverse.traverse(ast, {\n      enter: function(node, parent) {\n        if (node.type === 'FunctionDeclaration' ||\n            node.type === 'FunctionExpression' ||\n            node.type === 'ArrowFunctionExpression') {\n            addBeforeCode(node);\n        }\n      }\n    });\n    return escodegen.generate(ast);\n}\n```\n\nIf we try this modified function with the following code (contains an arrow function):\n\n```javascript\nfunction foo(a, b, c) {\n    let x = 'tutu';\n    let y = (function (x) { return x * x })(2);\n    let z = (e => { return e + 1 })(4);\n    console.log(x,y,z);\n}\n```\n\nThe result shows that the arrow function assigned to *let z* is visited, showing that it's name is anonymous and it's \"e\" parameter:\n\n![Second try](img/try2.png)\n\n## Task 5: Add line number\n\nIn order to show the line number, we must modify our two functions. This happens because the following reasons:\n\n* In the *addLogging(code)* function, when we parse the code, we must add an option that allows the resultant **AST** to have the location information. This means that, aside from other information, the **AST** will have the lines where all the nodes are located inside the code.\n\n    ```javascript\n    export function addLogging(code) {\n        let ast = espree.parse(code, {ecmaVersion: 12, loc: true});\n        estraverse.traverse(ast, {\n        enter: function(node, parent) {\n            if (node.type === 'FunctionDeclaration' ||\n                node.type === 'FunctionExpression' ||\n                node.type === 'ArrowFunctionExpression') {\n                addBeforeCode(node);\n            }\n        }\n        });\n        return escodegen.generate(ast);\n    }\n    ```\n\n* In the *addBeforeCode(node)* function, we need to extract the location and add it to our modified code.\n\n    ```javascript\n    function addBeforeCode(node) {\n        let parameters = '';\n\n        // Function name.\n        let name = node.id ? node.id.name : '<anonymous function>';\n\n        // Function parameters.\n        if (node.params.length != 0) {\n            parameters = node.params.map(param => ` \\${ ${param.name} }`);\n            parameters[0] = parameters[0].slice(1);\n        }\n\n        // Creating the code to insert.\n        let beforeCode = `console.log(\\`Entering ${name}(${parameters}) at line ${node.loc.start.line}\\`);`;\n\n        // Creating the new node.\n        let beforeNodes = espree.parse(beforeCode, {ecmaVersion: 12}).body;\n\n        // Adding the new node.\n        node.body.body = beforeNodes.concat(node.body.body);\n    }\n    ```\n\nOnce all the changes are done, if we try the functions with the arrow function code we tried in the previous task, the result is:\n\n![Third try](img/try3.png)\n\n## Task 6: Testing\n\nIn this task, we must use Mocha in order to execute a set of tests to make sure the code is working fine.\nThe tests are separated in some files:\n\n* **Input files**: They are located in the *test/data/inputs* folder and their content is a **JS** code.\n\n    ```javascript\n    function foo(a, b) {   \n        var x = 'blah';   \n        var y = (function () {\n            return 3;\n        })();\n    }     \n    foo(1, 'wut', 3);\n    ```\n\n* **Expected files**: They are located in the *test/data/expected* folder and their content is a **JS** code, which must be the resultant code when we apply the transformations. This is, each time it enters a function, it must be able to write the *console.log* with it's information.\n\n    ```javascript\n    function foo(a, b) {\n        console.log(`Entering foo(${ a }, ${ b }) at line 1`);\n        var x = 'blah';\n        var y = function () {\n            console.log(`Entering <anonymous function>() at line 3`);\n            return 3;\n        }();\n    }\n    foo(1, 'wut', 3);\n    ```\n\n* **Result files**: They are located in the *test/data/results* folder and their content is the expected execution of the generated **JS** code.\n\n    ```javascript\n    Entering foo(1, wut) at line 1\n    Entering <anonymous function>() at line 3\n    ```\n\n* **Output files**: They are located in the *test/data/outputs* folder and their content is the execution of the generated **JS** code. Their content is deleted when the tests pass successfully.\n\n    ```javascript\n    Entering foo(1, wut) at line 1\n    Entering <anonymous function>() at line 3\n    ```\n\nAlso, we need a file where our tests will be described (*test/test-description.mjs*) and a file where our tests will be executed (*test/test.mjs*).\n\n* **Test description file**: In this file, I defined each test as an object with it's files.\n\n    ```javascript\n    export default [\n    {\n        input: 'test1.js',\n        output: 'logged1.js',\n        correctLogged: 'correct-logged1.js',\n        correctOut: 'logged-out1.txt'\n    },\n    {\n        input: 'test2.js',\n        output: 'logged2.js',\n        correctLogged: 'correct-logged2.js',\n        correctOut: 'logged-out2.txt'\n    },\n    {\n        input: 'test3.js',\n        output: 'logged3.js',\n        correctLogged: 'correct-logged3.js',\n        correctOut: 'logged-out3.txt'\n    },\n    {\n        input: 'test4.js',\n        output: 'logged4.js',\n        correctLogged: 'correct-logged4.js',\n        correctOut: 'logged-out4.txt'\n    }\n    ]\n    ```\n\n* **Test execution file**: In this file, the tests will be executed with a *for* loop that will iterate through the test description array.\n\n    ```javascript\n    import { transpile } from \"../src/logging-espree.js\";\n    import assert from 'assert';\n    import * as fs from \"fs/promises\";\n    import { dirname } from 'path';\n    import { fileURLToPath } from 'url';\n\n    const __dirname = dirname(fileURLToPath(import.meta.url));\n    import Tst from './test-description.mjs';\n\n    const Test = Tst.map(t => ({\n        input: __dirname + '/data/inputs/' + t.input,\n        output: __dirname + '/data/outputs/' + t.output,\n        correctLogged: __dirname + '/data/expected/' + t.correctLogged,\n        correctOut: __dirname + '/data/results/' + t.correctOut,\n    })\n    )\n\n    function removeSpaces(s) {\n        return s.replace(/\\s/g, '');\n    }\n\n    for (let i = 0; i < Test.length; i++) {\n        it(`transpile(${Tst[i].input}, ${Tst[i].output})`, async () => {\n\n            // Compile the input and check the output program is what expected\n            await transpile(Test[i].input, Test[i].output);\n            let output = await fs.readFile(Test[i].output, 'utf-8');\n            let expected = await fs.readFile(Test[i].correctLogged, 'utf-8');\n            assert.equal(removeSpaces(output), removeSpaces(expected));\n            await fs.unlink(Test[i].output);\n\n            // Run the output program and check the logged output is what expected\n            let correctOut = await fs.readFile(Test[i].correctOut, 'utf-8');\n\n            let oldLog = console.log; // mocking console.log\n            let result = [];\n            let resultantString;\n            console.log = function (...s) {\n                if (s.length > 1) {\n                    let sString = s.join(' ');\n                    s = [sString];\n                }\n                result.push(s);\n                resultantString = result.join('\\n');\n            };\n            eval(output);\n\n            assert.equal(removeSpaces(resultantString), removeSpaces(correctOut));\n            console.log = oldLog;\n        });  \n    }\n    ```\n\nWith these steps, if we execute the tests, we might be able to see that they are passed successfully:\n\n![Testing](img/tests.png)\n\nThere's a problem with **asynchronous testing** that is making my tests to pass whenever they want.\n\n## Task 7: Code Coverage\n\nI had problems when I generated the code coverage report. Even with a correct script in the *package.json* file, the coverage report shows 0 code coverage. This happenned even after adding some options to **Nyc** in order to include the code coverage specifically:\n\n```javascript\n\"nyc\": {\n    \"all\": true,\n    \"include\": [ \"src/*.js\" ]\n},\n```\n\nI searched about this issue, and it seems that **Nyc** does not work with **ES6** modules anymore, so a solution may be using **CommonJS** modules in the whole project.\n\n![Coverage](img/coverage.png)\n\n## Task 8: CI with GitHub Actions\n\nIf we want to use Continuous Integration with GitHub Actions, the only thing I had to do was editing the *.github/workflows/nodejs.yml* file and fill it with the following lines:\n\n```yml\n# Write your workflow for CI here\nname: CI\n\n# Controls when the workflow will run\non:\n  # Triggers the workflow on push or pull request events but only for the $default-branch branch\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# A workflow run is made up of one or more jobs that can run sequentially or in parallel\njobs:\n  # This workflow contains a single job called \"build\"\n  build:\n    # The type of runner that the job will run on\n    runs-on: ubuntu-latest\n\n    # Steps represent a sequence of tasks that will be executed as part of the job\n    steps:\n      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it\n      - uses: actions/checkout@v2\n\n      - name: Install\n        run: npm install\n\n      - name: Run tests\n        run: npm run test\n```\n\nWhen we make a push to the repo, we can see the continuous integration execution, with all the jobs and steps we defined:\n\n![Continuous Integration](img/integration.png)\n\n## Task 9: Documentation with JSDoc\n\nIf we want to create a documentation report with **JSDoc**, we must follow some steps:\n\n* **Adding JSDoc script to the package.json**: We need to add a script that allows to generate the documentation report.\n\n    ```javascript\n    \"doc\": \"jsdoc ./src/*js\"\n    ```\n\n* **Adding JSDoc comments to the functions**: The **JSDoc** comments have the following structure:\n\n    ```javascript\n    /**\n     * Read the file with the JS program, calls addLogin to add the login messages and writes the output.\n     * @param {string} inputFile Input file's name.\n     * @param {string} outputFile Output file's name.\n     */\n    export async function transpile(inputFile, outputFile) {\n        let code = await fs.readFile(inputFile, 'utf8');\n        code = addLogging(code);\n        fs.writeFile(outputFile, code, err => {\n        if (err) {\n            console.error(err);\n            return;\n        }\n        });\n    }\n    ```\n\nIf we run the script a documentation report will be generated in the */out* folder. If we open the *index.html* with **LiveServer** we can see the following page:\n\n![Documentation](img/documentation.png)\n\n## Task 10: Publishing the module in NPM and GitHub\n\nIn order to publish the package in **NPM**, I needed to create an account and organizations in **NPM**. This allows to publish unlimited free packages in it.\n\nI have encountered many problems and I couldn't accomplish this task. This occurred because I couldn't log in to the **npm registry** due to the Virtual Machine, which doesn't allow to open the website (because of the xdg-open, that calls the system in order to run the URL in the preferred browser, which is not posible in the Virtual Machine). One possible solution may be developing this assignment in my PC instead of the Virtual Machine.\n\n![Error](img/npm.png)\n\n### Solving the errors\n\nAfter the class session, I solved a couple of errors that happenned because of the use of the Virtual Machine. I prepared my PC's environment in order to work with this assignment and I could achieve the task of publishing the module in **NPM**. Here's an image of it:\n\n![Published](img/published.png)\n","readmeFilename":"README.md"}