diff --git a/.gitignore b/.gitignore
index 07e6e47..8777577 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/node_modules
+.vscode/
diff --git a/README.md b/README.md
index e5d2a1f..4aea79b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,49 @@
# node-mentoring-introduction
-Task 1
+Task 3
+https://d17btkcdsmqrmh.cloudfront.net/node-gmp/docs/event-emitter-vs-buffers-vs-streams/Homework
+
+## Subtask 1
+Write your own EventEmitter class.
+It must contain
+- on / addEventListener
method,
+- off / removeEventListener
method,
+- once
method,
+- emit
method,
+- rawListeners
method,
+- listenerCount
method.
+This basic features are sufficient to implement a full system using the eventing model.
+
+Test result:
+
+
+
+## Subtask 2
+Write a class WithTime
which should extend your own class EventEmitter.
+
+WithTime
must execute some Async function with arguments and compute the time taken by this function.
+
+Execution must emit event start and end of execute and console.log of result data. This data must be gotten from Async function.
+
+Test result:
+
+![2023-09-15_20h27_13](https://github.com/kandalova/node-mentoring-introduction/assets/26093763/953a3aae-04fb-4f63-a231-b045a5febb96)
+
+## Subtask 3
+
+Write a program which should do the following:
+- Read the content of csvfile from./csvdirectory
+- Use the csvtojson package to convert csvfile to json object
+- Write the csvfile content to a new txtfile.
+- Do not load all the content of the csvfile into RAM via stream (read/write file content line by line).
+- In case of read/write errors, log them in the console.
+- The program should be started via npm script using nodemon(i.e. npm run task2).
+
+Test result
+
+Parsed csv strings
+
+
+
+Generated file
+
+
diff --git a/csvdirectory/nodejs-hw1-ex1.csv b/csvdirectory/nodejs-hw1-ex1.csv
new file mode 100644
index 0000000..2521a60
--- /dev/null
+++ b/csvdirectory/nodejs-hw1-ex1.csv
@@ -0,0 +1,6 @@
+Book,Author,Amount,Price
+The Compound Effect,Darren Hardy,5,9.48
+The 7 Habits of Highly Effective People,Stephen R. Covey,4,23.48
+The Miracle Morning,Hal Elrod,10,21.34
+Influence: The Psychology of Persuasion,Robert B. Cialdini,4,12.99
+The ONE Thing,Gary Keller,1,11.18
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..e4cac83
--- /dev/null
+++ b/index.js
@@ -0,0 +1,49 @@
+import EventEmitter from "./utils/EventEmitter.js";
+
+const myEmitter = new EventEmitter();
+
+function c1() {
+ console.log('an event occurred!');
+}
+
+function c2() {
+ console.log('yet another event occurred!');
+}
+
+myEmitter.on('eventOne', c1); // Register for eventOne
+myEmitter.on('eventOne', c2); // Register for eventOne
+
+// Register eventOnce for one time execution
+myEmitter.once('eventOnce', () => console.log('eventOnce once fired'));
+myEmitter.once('init', () => console.log('init once fired'));
+
+// Register for 'status' event with parameters
+myEmitter.on('status', (code, msg)=> console.log(`Got ${code} and ${msg}`));
+
+
+myEmitter.emit('eventOne');
+
+// Emit 'eventOnce' -> After this the eventOnce will be
+// removed/unregistered automatically
+myEmitter.emit('eventOnce');
+
+
+myEmitter.emit('eventOne');
+myEmitter.emit('init');
+myEmitter.emit('init'); // Will not be fired
+myEmitter.emit('eventOne');
+myEmitter.emit('status', 200, 'ok');
+
+// Get listener's count
+console.log(myEmitter.listenerCount('eventOne'));
+
+// Get array of rawListeners//
+// Event registered with 'once()' will not be available here after the
+// emit has been called
+console.log(myEmitter.rawListeners('eventOne'));
+
+// Get listener's count after remove one or all listeners of 'eventOne'
+myEmitter.off('eventOne', c1);
+console.log(myEmitter.listenerCount('eventOne'));
+myEmitter.off('eventOne', c2);
+console.log(myEmitter.listenerCount('eventOne'));
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..9b8887a
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,425 @@
+{
+ "name": "mentoring-introduction",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "mentoring-introduction",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.1.1",
+ "anymatch": "^3.1.3",
+ "balanced-match": "^1.0.2",
+ "binary-extensions": "^2.2.0",
+ "brace-expansion": "^1.1.11",
+ "braces": "^3.0.2",
+ "chokidar": "^3.5.3",
+ "concat-map": "^0.0.1",
+ "csvtojson": "^2.0.10",
+ "debug": "^3.2.7",
+ "fill-range": "^7.0.1",
+ "glob-parent": "^5.1.2",
+ "has-flag": "^3.0.0",
+ "ignore-by-default": "^1.0.1",
+ "is-binary-path": "^2.1.0",
+ "is-extglob": "^2.1.1",
+ "is-glob": "^4.0.3",
+ "is-number": "^7.0.0",
+ "lru-cache": "^6.0.0",
+ "minimatch": "^3.1.2",
+ "ms": "^2.1.3",
+ "nodemon": "^3.0.1",
+ "nopt": "^1.0.10",
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.3.1",
+ "pstree.remy": "^1.1.8",
+ "readdirp": "^3.6.0",
+ "semver": "^7.5.4",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "to-regex-range": "^5.0.1",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5",
+ "yallist": "^4.0.0"
+ },
+ "devDependencies": {}
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/csvtojson": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz",
+ "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==",
+ "dependencies": {
+ "bluebird": "^3.5.1",
+ "lodash": "^4.17.3",
+ "strip-bom": "^2.0.0"
+ },
+ "bin": {
+ "csvtojson": "bin/csvtojson"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "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==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/nodemon": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz",
+ "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==",
+ "dependencies": {
+ "chokidar": "^3.5.2",
+ "debug": "^3.2.7",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.1.2",
+ "pstree.remy": "^1.1.8",
+ "semver": "^7.5.3",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5"
+ },
+ "bin": {
+ "nodemon": "bin/nodemon.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nodemon"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pstree.remy": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/simple-update-notifier": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
+ "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
+ "dependencies": {
+ "is-utf8": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dependencies": {
+ "nopt": "~1.0.10"
+ },
+ "bin": {
+ "nodetouch": "bin/nodetouch.js"
+ }
+ },
+ "node_modules/undefsafe": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..607b18a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "mentoring-introduction",
+ "version": "1.0.0",
+ "description": "Task 3",
+ "main": "index.js",
+ "type": "module",
+ "dependencies": {
+ "abbrev": "^1.1.1",
+ "anymatch": "^3.1.3",
+ "balanced-match": "^1.0.2",
+ "binary-extensions": "^2.2.0",
+ "brace-expansion": "^1.1.11",
+ "braces": "^3.0.2",
+ "chokidar": "^3.5.3",
+ "concat-map": "^0.0.1",
+ "csvtojson": "^2.0.10",
+ "debug": "^3.2.7",
+ "fill-range": "^7.0.1",
+ "glob-parent": "^5.1.2",
+ "has-flag": "^3.0.0",
+ "ignore-by-default": "^1.0.1",
+ "is-binary-path": "^2.1.0",
+ "is-extglob": "^2.1.1",
+ "is-glob": "^4.0.3",
+ "is-number": "^7.0.0",
+ "lru-cache": "^6.0.0",
+ "minimatch": "^3.1.2",
+ "ms": "^2.1.3",
+ "nodemon": "^3.0.1",
+ "nopt": "^1.0.10",
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.3.1",
+ "pstree.remy": "^1.1.8",
+ "readdirp": "^3.6.0",
+ "semver": "^7.5.4",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "to-regex-range": "^5.0.1",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5",
+ "yallist": "^4.0.0"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "nodemon index.js",
+ "task2": "nodemon ./utils/withTime.js",
+ "task3": "nodemon ./utils/MyCSVFormatter.js"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC"
+}
diff --git a/utils/EventEmitter.js b/utils/EventEmitter.js
new file mode 100644
index 0000000..eab759a
--- /dev/null
+++ b/utils/EventEmitter.js
@@ -0,0 +1,67 @@
+export default class EventEmitter {
+ listeners = {}; // key-value pair
+
+ addListener(eventName, fn) {
+ this._pushListener(eventName, fn);
+ }
+
+ on(eventName, fn) {
+ this._pushListener(eventName, fn);
+ }
+
+ removeListener(eventName, fn) {
+ this._filterListeners(eventName, fn);
+ }
+
+ off(eventName, fn) {
+ this._filterListeners(eventName, fn);
+ }
+
+ once(eventName, fn) {
+ const onceWrapper = (...args)=>{
+ fn(...args);
+ this.off(eventName, onceWrapper);
+ }
+ this._pushListener(eventName, onceWrapper);
+ }
+
+ emit(eventName, ...args) {
+ if(this.listeners[eventName]){
+ this.listeners[eventName].forEach(listener => {
+ listener(...args);
+ });
+ }
+ }
+
+ listenerCount(eventName) {
+ return this.listeners[eventName] ? this.listeners[eventName].length : 0;
+ }
+
+ rawListeners(eventName) {
+ if(!this.listeners[eventName]){
+ throw new Error("There is no such eventName!")
+ }
+ return [...this.listeners[eventName]];
+ }
+
+ _pushListener(eventName, fn){
+ if(typeof fn !== "function") {
+ throw new Error("Listener must be a function!")
+ }
+
+ if(!this.listeners[eventName]){
+ this.listeners[eventName] = [];
+ }
+ this.listeners[eventName].push(fn);
+ }
+
+ _filterListeners(eventName, fn){
+ if(!this.listeners[eventName]){
+ throw new Error("There is no such eventName!")
+ }
+ this.listeners[eventName] = this.listeners[eventName].filter((currFn)=>currFn !== fn);
+ if(this.listeners[eventName].length === 0){
+ delete this.listeners[eventName];
+ }
+ }
+ }
diff --git a/utils/MyCSVFormatter.js b/utils/MyCSVFormatter.js
new file mode 100644
index 0000000..7335648
--- /dev/null
+++ b/utils/MyCSVFormatter.js
@@ -0,0 +1,44 @@
+import { open, writeFile, appendFile } from 'node:fs/promises';
+import csv from "csvtojson"
+
+async function csvToJson(path){
+ try {
+ const newFilePath='./csvdirectory/nodejs-hw1-ex1.txt';
+ const file = await open(path);
+ let headers;
+ writeFile(newFilePath, '');
+
+ for await (const line of file.readLines()) {
+ console.log(line);
+ csv()
+ .fromString(line)
+ .on('header', (headerLine) => {
+ //header=> [header1, header2, header3]
+ if (!headers) {
+ headers = headerLine
+ }
+ else {
+ const formatLine = getFormatLine(headers, headerLine);
+ appendFile(newFilePath, `${formatLine}\n`);
+ }
+ })
+ .on('error', (err) => {
+ console.log(err)
+ })
+ }
+ }
+ catch(err){
+ console.log(err);
+ }
+}
+
+function getFormatLine(headers, fields){
+ const resultObj = {};
+ fields.forEach((field, idx) => {
+ const key = headers[idx] || `field${idx+1}`;
+ resultObj[key] = field;
+ });
+ return JSON.stringify(resultObj);
+}
+
+csvToJson('./csvdirectory/nodejs-hw1-ex1.csv');
diff --git a/utils/withTime.js b/utils/withTime.js
new file mode 100644
index 0000000..2f125c7
--- /dev/null
+++ b/utils/withTime.js
@@ -0,0 +1,42 @@
+import EventEmitter from "./EventEmitter.js";
+
+class WithTime extends EventEmitter {
+
+ constructor(){
+ super();
+ }
+
+ async execute(asyncFunc, ...args) {
+ try{
+ const start = new Date().getTime();
+ this.emit('begin');
+
+ const endHandler = (time, data)=>{
+ console.log(`Time: ${time}\nData:\n${data}`);
+ }
+ this.on('end', endHandler);
+
+ const response = await asyncFunc(...args);
+ const data = await response.json();
+ const result = JSON.stringify(data, null, " ")
+ const end = new Date().getTime();
+ const time = (end - start)/1000;
+
+ this.emit('end', time, result);
+
+ }
+ catch(err){
+ console.log(err);
+ }
+
+ }
+}
+
+const withTime = new WithTime();
+
+withTime.on('begin', () => console.log('About to execute'));
+withTime.on('end', () => console.log('Done with execute'));
+
+await withTime.execute(fetch, 'https://jsonplaceholder.typicode.com/posts/1');
+
+console.log(withTime.rawListeners("end"));