mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(curriculum): add Working with Node Core Modules lessons (#65008)
Co-authored-by: Zaira <33151350+zairahira@users.noreply.github.com> Co-authored-by: majestic-owl448 <26656284+majestic-owl448@users.noreply.github.com>
This commit is contained in:
@@ -7728,6 +7728,12 @@
|
||||
"title": "NodeJS Intro Quiz",
|
||||
"intro": ["Test what you have learned about NodeJS in this quiz."]
|
||||
},
|
||||
"lecture-working-with-node-core-modules": {
|
||||
"title": "Working with Node Core Modules",
|
||||
"intro": [
|
||||
"Learn about the node.js core modules, such as fs, buffer, stream, path modules, and more, so you can understand what Node gives you out of the box to build efficient applications without relying on third-party libraries."
|
||||
]
|
||||
},
|
||||
"lecture-understanding-the-http-request-response-model": {
|
||||
"title": "Understanding the HTTP Request-Response Model",
|
||||
"intro": [
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Working with Node Core Modules
|
||||
block: lecture-working-with-node-core-modules
|
||||
superBlock: back-end-development-and-apis-v9
|
||||
---
|
||||
|
||||
## Introduction to the Working with Node Core Modules
|
||||
|
||||
Learn about the node.js core modules, such as fs, buffer, stream, path modules, and more, so you can understand what Node gives you out of the box to build efficient applications without relying on third-party libraries.
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
---
|
||||
id: 695cc6a5eefd305381ec90bc
|
||||
title: What Is the fs Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-fs-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Many languages and frameworks out there provide ways to work with files and folders. Node.js lets you do this with the `fs` or file system module.
|
||||
|
||||
This lesson will focus on the Node `fs` module, how it works, and the three different ways you can use the methods it provides.
|
||||
|
||||
The Node `fs` module provides you with methods for working with files and folders, including opening and closing, reading and writing, and deleting operations.
|
||||
|
||||
The `fs` module is a Node.js standard module, so it's available to use as long as you have Node.js installed in your environment. To use the module, you import it this way:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
```
|
||||
|
||||
The flexibility the `fs` module offers is that it allows you to use its methods both synchronously and asynchronously. The `fs` module methods are asynchronous by default, but for every method, there's a synchronous form:
|
||||
|
||||
```js
|
||||
fs.writeFile() // Asynchronous file writing
|
||||
fs.writeFileSync() // Synchronous file writing
|
||||
|
||||
fs.readFile() // Asynchronous file reading
|
||||
fs.readFileSync() // Synchronous file reading
|
||||
|
||||
fs.open() // Opens a file
|
||||
fs.openAsBlob() // Opens as blob
|
||||
fs.openSync() // Synchronous open
|
||||
fs.opendir() // Opens directory
|
||||
fs.opendirSync() // Synchronous directory open
|
||||
```
|
||||
|
||||
It doesn't end there. Depending on your needs, you can use the methods in three ways:
|
||||
|
||||
- with callbacks, for example `fs.writeFile()` (asynchronous)
|
||||
- with promises if you prefer the `async/await` syntax, for example `fs.promises.writeFile()`
|
||||
- synchronously, for example, `fs.writeFileSync()`
|
||||
|
||||
Here's the basic syntax for the asynchronous usage of the methods:
|
||||
|
||||
```js
|
||||
fs.writeFile("filePath", "content", "utf8", (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log("File written to!");
|
||||
});
|
||||
```
|
||||
|
||||
For the promises version, you can import that from `fs/promises` or chain `promises` to your `fs` import. Here's the syntax:
|
||||
|
||||
```js
|
||||
async function promisesExample() {
|
||||
try {
|
||||
await fs.promises.writeFile("filePath", "content", "utf8");
|
||||
console.log("File written to!");
|
||||
} catch (err) {
|
||||
console.error("Error:", err);
|
||||
}
|
||||
}
|
||||
|
||||
promisesExample();
|
||||
```
|
||||
|
||||
And here's the synchronous version:
|
||||
|
||||
```js
|
||||
try {
|
||||
fs.writeFileSync("filePath", "content", "utf8");
|
||||
console.log("File written to!");
|
||||
} catch (err) {
|
||||
console.error("Error:", err);
|
||||
}
|
||||
```
|
||||
|
||||
Note that using any of the methods synchronously is blocking. In other words, your program will stop running and wait until the operation is finished before moving on to the next line of code.
|
||||
|
||||
For quick scripts, small projects, or one-off tasks, synchronous methods are probably fine. But in real world applications, blocking I/O (input/output) becomes a problem because it can freeze other parts of your app while Node waits for the file system to finish its operations. That slows things down and hurts performance and user experience.
|
||||
|
||||
That's why asynchronous methods exist. They let the rest of your program continue running while Node handles file operations in the background. Traditionally, this used callbacks, but those can get messy fast as your app grows.
|
||||
|
||||
Promises and `async/await` solve that problem. They are still non-blocking, but the code reads like normal synchronous code and is much easier to maintain.
|
||||
|
||||
For this reason, the promises-based approach is generally preferred today, and that's what we'll use in the rest of this lesson.
|
||||
|
||||
The `writeFile()` method lets you write to an existing file. If the file doesn't exist, it creates it in the current directory, then writes the specified content to it.
|
||||
|
||||
Here's how to use the `writeFile()` method:
|
||||
|
||||
```js
|
||||
const fs = require("fs/promises");
|
||||
|
||||
async function writeToFile() {
|
||||
try {
|
||||
await fs.writeFile(
|
||||
"article.md",
|
||||
"## Node `fs` Module: The Complete Guide",
|
||||
"utf8",
|
||||
);
|
||||
console.log("File written to!");
|
||||
} catch (err) {
|
||||
console.error("Error writing to file:", err);
|
||||
}
|
||||
}
|
||||
|
||||
writeToFile(); // File written to!
|
||||
```
|
||||
|
||||
Here's the content of the article.md file after that:
|
||||
|
||||
```md
|
||||
## Node `fs` Module: The Complete Guide
|
||||
```
|
||||
|
||||
The `appendFile()` method lets you add to the content of an existing file. Here's how to use it:
|
||||
|
||||
```js
|
||||
const fs = require("fs/promises");
|
||||
|
||||
async function appendToFile() {
|
||||
try {
|
||||
await fs.appendFile(
|
||||
"article.md",
|
||||
"\nIn this article, you will learn all there is to know about the Node fs module...",
|
||||
"utf8",
|
||||
);
|
||||
console.log("File appended to!");
|
||||
} catch (err) {
|
||||
console.log("Error appending to file:", err);
|
||||
}
|
||||
}
|
||||
|
||||
appendToFile(); // File appended to!
|
||||
```
|
||||
|
||||
The `readFile()` method lets you see what the content of a file is:
|
||||
|
||||
```js
|
||||
const fs = require("fs/promises");
|
||||
|
||||
async function readFileContent() {
|
||||
try {
|
||||
const fileContent = await fs.readFile("article.md", "utf8");
|
||||
console.log("File content:", fileContent);
|
||||
} catch (err) {
|
||||
console.log("File read successfully");
|
||||
}
|
||||
}
|
||||
|
||||
readFileContent();
|
||||
|
||||
/*
|
||||
File content: ## Node `fs` Module: The Complete Guide
|
||||
|
||||
In this article, you will learn all there is to know about the Node fs module...
|
||||
*/
|
||||
```
|
||||
|
||||
If you don't specify the `utf8` character encoding, you will get the content of the file as a buffer:
|
||||
|
||||
```js
|
||||
async function readFileContent() {
|
||||
try {
|
||||
const fileContent = await fs.readFile("article.md");
|
||||
console.log("File content:", fileContent);
|
||||
} catch (err) {
|
||||
console.log("File read successfully");
|
||||
}
|
||||
}
|
||||
|
||||
readFileContent();
|
||||
|
||||
/*
|
||||
File content: <Buffer 23 23 20 4e 6f 64 65 20 60 66 73 60 20 4c 69 62 72 61 72 79 3a 20
|
||||
54 68 65 20 43 6f 6d 70 6c 65 74 65 20 47 75 69 64 65 0a 0a 49 6e 20 74 68 69 73 20 ...
|
||||
72 more bytes>
|
||||
*/
|
||||
```
|
||||
|
||||
In the next lesson, you will learn how to handle a buffer like this with the Node.js Buffer module.
|
||||
|
||||
Lastly, the `unlink()` method lets you delete a file:
|
||||
|
||||
```js
|
||||
const fs = require("fs/promises");
|
||||
|
||||
async function deleteFile() {
|
||||
try {
|
||||
await fs.unlink("article.ts");
|
||||
console.log("File deleted successfully!");
|
||||
} catch (err) {
|
||||
console.error("Error deleting file:", err);
|
||||
}
|
||||
}
|
||||
|
||||
deleteFile();
|
||||
```
|
||||
|
||||
If the file does not exist, you get an error message similar to this:
|
||||
|
||||
```bash
|
||||
Error deleting file: Error: ENOENT: no such file or directory, unlink 'article.ts'
|
||||
```
|
||||
|
||||
If it exists, the file is deleted, and you get the success message you set.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
What is the main purpose of the Node `fs` module?
|
||||
|
||||
## --answers--
|
||||
|
||||
To create dynamic HTML pages in the browser.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how you handle files like text documents or folders directly from Node.js.
|
||||
|
||||
---
|
||||
|
||||
To connect Node.js to a database.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how you handle files like text documents or folders directly from Node.js.
|
||||
|
||||
---
|
||||
|
||||
To interact with the file system for file and folder CRUD operations.
|
||||
|
||||
---
|
||||
|
||||
To manage Node.js package installations.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how you handle files like text documents or folders directly from Node.js.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
Which method in the Node fs module lets you write content to a file, creating it if it doesn't exist?
|
||||
|
||||
## --answers--
|
||||
|
||||
`writeFile()`
|
||||
|
||||
---
|
||||
|
||||
`readFile()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the method that both creates and writes content to a file.
|
||||
|
||||
---
|
||||
|
||||
`appendFile()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the method that both creates and writes content to a file.
|
||||
|
||||
---
|
||||
|
||||
`unlink()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the method that both creates and writes content to a file.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
## --text--
|
||||
|
||||
Which of the following is **NOT** one of the three ways you can use methods in the Node `fs` module?
|
||||
|
||||
## --answers--
|
||||
|
||||
With callbacks, for example `fs.writeFile()`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Two are asynchronous, one is synchronous, and one doesn't exist.
|
||||
|
||||
---
|
||||
|
||||
With promises, for example `fs.promises.writeFile()`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Two are asynchronous, one is synchronous, and one doesn't exist.
|
||||
|
||||
---
|
||||
|
||||
Synchronously, for example `fs.writeFileSync()`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Two are asynchronous, one is synchronous, and one doesn't exist.
|
||||
|
||||
---
|
||||
|
||||
With JSON parsing, for example `fs.parseFile()`.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02c7
|
||||
title: What Is the Buffer Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-buffer-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
JavaScript was originally created to run in web browsers, where its main role was to make web pages interactive. Because of this, early JavaScript focused primarily on handling text in forms and manipulating the Document Object Model (DOM).
|
||||
|
||||
However, not all data on the web is text. Files, images, and videos are binary data, which require different handling mechanisms. In browsers, these types of data are typically processed by specialized components of the browser rather than by JavaScript itself.
|
||||
|
||||
Modern browsers use rendering engines and JavaScript engines to manage these tasks — for example, Blink (with V8) in Chrome, WebKit (with JavaScriptCore) in Safari, and Gecko (with SpiderMonkey) in Firefox.
|
||||
|
||||
Node.js does not run in the browser, so it needed its own way to handle binary data, especially when handling file input and output (I/O) and TCP streams, where data comes in chunks. That's where the `Buffer` module comes in.
|
||||
|
||||
The Node.js `Buffer` module lets you work with binary data like files, images, or network streams directly. With it, you can store and manipulate binaries directly in memory.
|
||||
|
||||
Just like the `fs` module, `Buffer` is one of the core Node.js modules, so you don't need to install it separately before using it.
|
||||
|
||||
To use it, import the module first by destructuring:
|
||||
|
||||
```js
|
||||
const { Buffer } = require("buffer");
|
||||
```
|
||||
|
||||
Then call `Buffer` with the methods it provides. For example, `Buffer.from()` lets you create a buffer from a string, array, or other raw data.
|
||||
|
||||
Here's how to create a `Buffer` from a string and an array:
|
||||
|
||||
```js
|
||||
// Create a buffer from a string
|
||||
const myStrBuffer = Buffer.from("freeCodeCamp");
|
||||
console.log(myStrBuffer); // <Buffer 66 72 65 65 43 6f 64 65 43 61 6d 70>
|
||||
|
||||
// Create a buffer from an array of numbers
|
||||
const myNumBuffer = Buffer.from([
|
||||
70, 82, 69, 69, 67, 79, 68, 69, 67, 65, 77, 80,
|
||||
]);
|
||||
|
||||
console.log(myNumBuffer); // <Buffer 46 52 45 45 43 4f 44 45 43 41 4d 50>
|
||||
```
|
||||
|
||||
While it is possible to use some methods from the `Buffer` module without importing it first, other methods aren't available unless you explicitly import `Buffer`. So it's recommended that you always import Buffer whenever you use it in your projects.
|
||||
|
||||
You can access individual `buffer` elements just like an array:
|
||||
|
||||
```js
|
||||
console.log(myNumBuffer[0]); // 70
|
||||
console.log(myStrBuffer[0]); // 102
|
||||
```
|
||||
|
||||
You can also use the `toString()` method on the buffers to see what they really look like:
|
||||
|
||||
```js
|
||||
console.log(myStrBuffer.toString()); // freeCodeCamp
|
||||
console.log(myNumBuffer.toString()); // FREECODECAMP
|
||||
```
|
||||
|
||||
`Buffer.alloc()` lets you create a new buffer of a given size (number of bytes). Every byte inside it is automatically filled with `0`:
|
||||
|
||||
```js
|
||||
const someBuffer = Buffer.alloc(10);
|
||||
console.log(someBuffer); // <Buffer 00 00 00 00 00 00 00 00 00 00>
|
||||
```
|
||||
|
||||
You can see that the buffer is initialized with zeroes, based on the size passed into the `alloc()` method.
|
||||
|
||||
You can go ahead and use the `Buffer.write()` method to write to this buffer:
|
||||
|
||||
```js
|
||||
someBuffer.write("Hello fCC");
|
||||
|
||||
console.log(someBuffer); // <Buffer 48 65 6c 6c 6f 20 66 43 43 00>
|
||||
console.log(someBuffer.toString()); // Hello fCC
|
||||
```
|
||||
|
||||
If you write more data than the buffer can hold, it will be truncated:
|
||||
|
||||
```js
|
||||
someBuffer.write("Hello freeCodeCamp");
|
||||
|
||||
console.log(someBuffer); // <Buffer 48 65 6c 6c 6f 20 66 72 65 65>
|
||||
console.log(someBuffer.toString()); // Hello free
|
||||
```
|
||||
|
||||
Finally, you can use `Buffer.byteLength()` to show the number of bytes needed to store a string in a certain encoding:
|
||||
|
||||
```js
|
||||
console.log(Buffer.byteLength("Hello freeCodeCamp")); // 18
|
||||
```
|
||||
|
||||
Other `Buffer` methods include:
|
||||
|
||||
- `Buffer.isBuffer()`: checks if a given object is a buffer
|
||||
- `Buffer.compare()`: compares two buffers and returns their sort order
|
||||
- `Buffer.concat()`: joins multiple buffers together into one
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Which of these is **NOT** a Node.js `Buffer` method?
|
||||
|
||||
## --answers--
|
||||
|
||||
`Buffer.from()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles binary data outside of browsers.
|
||||
|
||||
---
|
||||
|
||||
`Buffer.alloc()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles binary data outside of browsers.
|
||||
|
||||
---
|
||||
|
||||
`Buffer.concat()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles binary data outside of browsers.
|
||||
|
||||
---
|
||||
|
||||
`Buffer.insert()`
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
## --text--
|
||||
|
||||
Why does Node.js provide the `Buffer` module?
|
||||
|
||||
## --answers--
|
||||
|
||||
To improve JavaScript performance in browsers.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js deals with data that isn't just text.
|
||||
|
||||
---
|
||||
|
||||
To style web pages with binary-based CSS.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js deals with data that isn't just text.
|
||||
|
||||
---
|
||||
|
||||
To handle binary data like files, images, and TCP streams.
|
||||
|
||||
---
|
||||
|
||||
To convert JavaScript code into machine code.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles binary data outside of browsers.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
What happens if you write more data than a buffer can hold?
|
||||
|
||||
## --answers--
|
||||
|
||||
The buffer automatically resizes to fit all the data.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how `"Hello freeCodeCamp"` becomes `"Hello free"` in one of the examples.
|
||||
|
||||
---
|
||||
|
||||
The extra data is truncated, and only what fits is stored.
|
||||
|
||||
---
|
||||
|
||||
Node.js throws an error and stops execution.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how `"Hello freeCodeCamp"` becomes `"Hello free"` in one of the examples.
|
||||
|
||||
---
|
||||
|
||||
The buffer overwrites data in nearby memory locations.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how `"Hello freeCodeCamp"` becomes `"Hello free"` in one of the examples.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02c8
|
||||
title: What Is the Crypto Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-crypto-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Crypto is another core module that's built into Node.js. It includes tools for things like hashing, encryption, decryption, and creating digital signatures, all of which are used to protect sensitive information and keep your app secure.
|
||||
|
||||
That said, `crypto` gives you low-level building blocks, not plug-and-play security. Writing your own encryption or authentication code can be unsafe if you're not careful. In most cases, it's best to use well-tested libraries like `bcrypt` for password hashing or `jsonwebtoken` (JWT) for handling logins and tokens.
|
||||
|
||||
That said, it's still useful to understand how some of the methods in the crypto module work.
|
||||
|
||||
To use these methods, you need to import the `crypto` module:
|
||||
|
||||
```js
|
||||
const crypto = require("crypto");
|
||||
```
|
||||
|
||||
Some of the methods are used for data transformation purposes, such as the ones for hashing and encrypting data, and some others are for key and security management, such as the ones for generating random values and creating secrets.
|
||||
|
||||
Let's look at the methods for hashing and encrypting data first.
|
||||
|
||||
The `createHash()` method creates a hash object by taking in algorithms like `sha256`, `sha512`, or `md5`. It's a one-way operation, so you can't reverse it.
|
||||
|
||||
`createHash()` is useful for hashing passwords and fingerprinting files. To use it, you pass in your algorithm, use the `update()` method to feed in the data, and finally use `digest()` with an encoding to get the hash value:
|
||||
|
||||
```js
|
||||
const crypto = require("crypto");
|
||||
|
||||
const hashedPassword = crypto
|
||||
.createHash("sha256")
|
||||
.update("myStrongPassword")
|
||||
.digest("hex");
|
||||
|
||||
console.log("createHash result:", hashedPassword);
|
||||
// createHash result: f92c9cfa0ead1bcec05ca75888a4074ba994ad237e5e2a8c7cc6a620378c061d
|
||||
```
|
||||
|
||||
`createHmac()` does almost the same thing as `createHash()`, but it takes things to the next level by accepting a secret key, so only someone with that key can verify the hash. It is ideal for authentication and verifying data integrity:
|
||||
|
||||
```js
|
||||
const crypto = require("crypto");
|
||||
|
||||
const hashedMessage = crypto
|
||||
.createHmac("sha256", "secretkey")
|
||||
.update("important-secret-message")
|
||||
.digest("hex");
|
||||
|
||||
console.log("createHmac result:", hashedMessage);
|
||||
// createHmac result: da48d6f026b6036286b1fb872c63264130d5cc4271f3a213bb6ddca5a023e77e
|
||||
```
|
||||
|
||||
The `createCipheriv()` and `createDecipheriv()` methods encrypt and decrypt data. They both take in an algorithm, a key, and an `iv`, which is a block of random or unique data used at the start of the encryption process:
|
||||
|
||||
```js
|
||||
createCipheriv(algorithm, key, iv);
|
||||
createDecipheriv(algorithm, key, iv);
|
||||
```
|
||||
|
||||
To decrypt the data, the key must be the same, otherwise, the decryption will fail, and you'll either get an error or unreadable gibberish instead of the original message.
|
||||
|
||||
Here are the two in action:
|
||||
|
||||
```js
|
||||
const crypto = require("crypto");
|
||||
|
||||
// A key must match the algorithm length. Here AES-256 is 32 bytes
|
||||
const key = Buffer.from("12345678901234567890123456789012");
|
||||
|
||||
// A fixed IV, 16 bytes for AES
|
||||
const iv = Buffer.from("1234567890123456");
|
||||
|
||||
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
||||
|
||||
let encrypted = cipher.update("Hello campers!", "utf8", "hex");
|
||||
encrypted += cipher.final("hex");
|
||||
|
||||
console.log("Encrypted data:", encrypted);
|
||||
// Encrypted data: 4ee93aa398ab44e3540e4a67ca96bc8c
|
||||
|
||||
// Decrypt the "Hello campers!" message
|
||||
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
||||
let decrypted = decipher.update(encrypted, "hex", "utf8");
|
||||
decrypted += decipher.final("utf8");
|
||||
|
||||
console.log("Decrypted data:", decrypted);
|
||||
// Decrypted data: Hello campers!
|
||||
```
|
||||
|
||||
Another crypto method for data transformation is `sign()` and `verify()`.
|
||||
|
||||
`sign()` creates a digital signature from some data using a private key. This signature proves that the data came from the holder of the private key and has not been tampered with.
|
||||
|
||||
`verify()` then checks that signature, and it fails if the data or signature does not match.
|
||||
|
||||
Now, let's look at the crypto methods for generating random values and creating secrets.
|
||||
|
||||
`randomBytes()` takes in a `size` and generates cryptographically secured tokens. That makes it good for generating UUIDs (universally unique IDs). In addition, it's a good replacement for `Math.random()`, which is not secure for tokens and keys.
|
||||
|
||||
```js
|
||||
console.log("Random Bytes:", crypto.randomBytes(16));
|
||||
// Random Bytes: <Buffer 01 88 aa 1e 2c 38 48 39 26 e1 6b a9 d8 c5 ed 49>
|
||||
```
|
||||
|
||||
The output is a buffer by default. As you learned in the lesson on the Buffer module, you can convert that Buffer to a string with the `toString()` method:
|
||||
|
||||
```js
|
||||
console.log("Random Bytes:", crypto.randomBytes(16).toString("hex"));
|
||||
// Random Bytes: a6154ef5a296fa176ad0f332bd94d712
|
||||
```
|
||||
|
||||
The `'hex'` argument in `toString('hex')` here tells Node to encode the binary data from the Buffer as a hexadecimal string.
|
||||
|
||||
The `randomInt()` method takes in a `min` and `max` values and generates a secure random integer between them. It is useful for OTPs and random selection.
|
||||
|
||||
```js
|
||||
console.log("Random Int:", crypto.randomInt(0, 100)); // 89
|
||||
```
|
||||
|
||||
Again, the upgrade over `Math.random()` and `Math.floor()` is that the method uses cryptographically secure randomness under the hood, so attackers can't predict the resulting random number.
|
||||
|
||||
Another method is `createSecretKey()`. It takes a buffer and generates a raw byte wrapped into a `KeyObject`:
|
||||
|
||||
```js
|
||||
const crypto = require("crypto");
|
||||
|
||||
const secret = crypto.createSecretKey(crypto.randomBytes(32));
|
||||
console.log(secret); // SecretKeyObject [KeyObject] { [Symbol(kKeyType)]: 'secret' }
|
||||
```
|
||||
|
||||
You can then use the `export` method to send out that `KeyObject`:
|
||||
|
||||
```js
|
||||
const secret = crypto.createSecretKey(crypto.randomBytes(32));
|
||||
console.log(secret.export());
|
||||
// <Buffer 53 06 a1 c7 75 69 8b 38 8b a4 b2 f7 1b bc b8
|
||||
// ae e2 d1 bf 67 af 1a 6a 0a 6e a0 29 62 bb 52 52 32>
|
||||
```
|
||||
|
||||
And finally, use `toString()` on the buffer to see the string representation of it:
|
||||
|
||||
```js
|
||||
const secret = crypto.createSecretKey(crypto.randomBytes(32));
|
||||
console.log(secret.export().toString('hex'));
|
||||
// 32dfe5917668580160986f1623bf8152913329c71163be9c3404a110cd78efd6
|
||||
```
|
||||
|
||||
In addition to these, there are:
|
||||
|
||||
- `createPublicKey()` and `createPrivateKey()` that lets you work with keys generated elsewhere
|
||||
- `createDiffieHellman()` for two parties to generate a shared secret without sending the secret directly
|
||||
- `Certificate()` for working with the one used in HTTPS, so you can parse, export, and verify certificate contents
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Which of these is the correct way to import the Node.js crypto module?
|
||||
|
||||
## --answers--
|
||||
|
||||
`const crypto = require('crypto')`
|
||||
|
||||
---
|
||||
|
||||
`const crypto = import('crypto')`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on the syntax Node.js uses for requiring built-in modules.
|
||||
|
||||
---
|
||||
|
||||
`import crypto from 'nodes:crypto'`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on the syntax Node.js uses for requiring built-in modules.
|
||||
|
||||
---
|
||||
|
||||
`crypto = requireModule('crypto')`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on the syntax Node.js uses for requiring built-in modules.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
## --text--
|
||||
|
||||
Which of these statements about `sign()` and `verify()` is correct?
|
||||
|
||||
## --answers--
|
||||
|
||||
`sign()` uses a public key to create a signature, and `verify()` checks it with a private key.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Remember that digital signatures work with private–public key pairs.
|
||||
|
||||
---
|
||||
|
||||
Both `sign()` and `verify()` require only a private key.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Remember that digital signatures work with private–public key pairs.
|
||||
|
||||
---
|
||||
|
||||
`sign()` creates a digital signature with a private key, and `verify()` checks it with the corresponding public key.
|
||||
|
||||
---
|
||||
|
||||
`verify()` can check signatures without needing any key.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Remember that digital signatures work with private–public key pairs.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
What method in the crypto module creates a one-way hash object using algorithms like `sha256`, `sha512`, or `md5`?
|
||||
|
||||
## --answers--
|
||||
|
||||
`createCipheriv()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This method is often used for hashing passwords and fingerprinting files.
|
||||
|
||||
---
|
||||
|
||||
`createDiffieHellman()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This method is often used for hashing passwords and fingerprinting files.
|
||||
|
||||
---
|
||||
|
||||
`createSign()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This method is often used for hashing passwords and fingerprinting files.
|
||||
|
||||
---
|
||||
|
||||
`createHash()`
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02c9
|
||||
title: What Is the os Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-os-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The OS module is another standard module that comes built into Node.js.
|
||||
|
||||
It lets you interact with the current operating system Node is running on so you can access vital information like the OS type, CPU details, available memory, total memory, network interfaces, and more.
|
||||
|
||||
To use the OS module, you import it this way:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
```
|
||||
|
||||
The OS module provides several methods you can use to make your application more system-aware. Let's look at some common ones.
|
||||
|
||||
The `platform()` method retrieves the operating system Node is currently running on:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.platform()); // darwin
|
||||
```
|
||||
|
||||
It can be useful for implementing cross-platform scripting:
|
||||
|
||||
```js
|
||||
if (os.platform() === 'win32') {
|
||||
// Windows specific code
|
||||
} else {
|
||||
// Non-Windows specific code
|
||||
}
|
||||
```
|
||||
|
||||
The `arch()` method shows a string representing the CPU architecture Node.js was compiled for:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.arch()); // arm64
|
||||
```
|
||||
|
||||
This can be useful if you want users to download the correct binaries and dependencies for a given architecture.
|
||||
|
||||
Other possible values are `'x64'`, `'arm'`, `'arm64'`, `'ia32'`, `'mips'`, `'ppc'`, and others.
|
||||
|
||||
`type()` gets the official OS name, so you can programmatically identify operating systems:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.type()); // Darwin (the core OS for macOS, iOS, and other Apple products)
|
||||
```
|
||||
|
||||
`release()` shows the system's OS kernel version, the core part of the operating system that manages system resources and communication between hardware and software components. This method can be useful for tracking compatibility between OS kernel versions and server requirements.
|
||||
|
||||
It returns this as a string like `'20.6.0'`:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.release()); // 25.0.0
|
||||
```
|
||||
|
||||
`version()` returns the specific operating system version with more details than the `release()` method:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.version());
|
||||
// Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:39 PDT 2025;
|
||||
// root:xnu-12377.1.9~141/RELEASE_ARM64_T8103
|
||||
```
|
||||
|
||||
`cpus()` returns an array of objects with details about each logical CPU core. This can help monitor CPU load:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.cpus());
|
||||
|
||||
/*
|
||||
[
|
||||
{
|
||||
model: 'Apple M1',
|
||||
speed: 2400,
|
||||
times: { user: 2184260, nice: 0, sys: 1767340, idle: 8344200, irq: 0 }
|
||||
},
|
||||
{
|
||||
model: 'Apple M1',
|
||||
speed: 2400,
|
||||
times: { user: 2049430, nice: 0, sys: 1641050, idle: 8612980, irq: 0 }
|
||||
},
|
||||
{
|
||||
model: 'Apple M1',
|
||||
speed: 2400,
|
||||
times: { user: 1162300, nice: 0, sys: 1193390, idle: 9986140, irq: 0 }
|
||||
},
|
||||
...
|
||||
]
|
||||
*/
|
||||
```
|
||||
|
||||
`uptime()` shows the time since the system was booted up. It can help determine how long servers have been running:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.uptime()); // 23047
|
||||
```
|
||||
|
||||
`totalmem()` and `freemem()` show the total amount of system memory in bytes and free system memory in bytes, respectively:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.totalmem()); // 8589934592 (8 GB)
|
||||
console.log(os.freemem()); // 93585408 (87 MB)
|
||||
```
|
||||
|
||||
`userInfo()` returns an object containing information about the current system user:
|
||||
|
||||
```js
|
||||
const os = require("os");
|
||||
console.log(os.userInfo());
|
||||
|
||||
/*
|
||||
[Object: null prototype] {
|
||||
uid: 502,
|
||||
gid: 20,
|
||||
username: 'user',
|
||||
homedir: '/Users/user',
|
||||
shell: '/bin/zsh'
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
Lastly, `networkInterfaces()` returns an object containing only network interfaces that have been assigned a network address.
|
||||
|
||||
```js
|
||||
console.log(os.networkInterfaces());
|
||||
|
||||
/*
|
||||
{
|
||||
lo0: [
|
||||
{
|
||||
address: '127.0.0.1',
|
||||
netmask: '255.0.0.0',
|
||||
family: 'IPv4',
|
||||
mac: '00:00:00:00:00:00',
|
||||
internal: true,
|
||||
cidr: '127.0.0.1/8'
|
||||
},
|
||||
{
|
||||
address: '::1',
|
||||
netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
family: 'IPv6',
|
||||
mac: '00:00:00:00:00:00',
|
||||
internal: true,
|
||||
cidr: '::1/128',
|
||||
scopeid: 0
|
||||
}
|
||||
],
|
||||
en0: [
|
||||
{
|
||||
address: '192.168.1.10',
|
||||
netmask: '255.255.255.0',
|
||||
family: 'IPv4',
|
||||
mac: 'aa:bb:cc:dd:ee:ff',
|
||||
internal: false,
|
||||
cidr: '192.168.1.10/24'
|
||||
},
|
||||
{
|
||||
address: 'fe80::abcd:1234:5678:9abc',
|
||||
netmask: 'ffff:ffff:ffff:ffff::',
|
||||
family: 'IPv6',
|
||||
mac: 'aa:bb:cc:dd:ee:ff',
|
||||
internal: false,
|
||||
cidr: 'fe80::abcd:1234:5678:9abc/64',
|
||||
scopeid: 2
|
||||
}
|
||||
],
|
||||
// ...more network interfaces
|
||||
};
|
||||
*/
|
||||
```
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
What do the `os.totalmem()` and `os.freemem()` methods in Node.js display?
|
||||
|
||||
## --answers--
|
||||
|
||||
The total and free memory used by Node.js only.
|
||||
|
||||
### --feedback--
|
||||
|
||||
These methods measure system-level memory, not app-level memory.
|
||||
|
||||
---
|
||||
|
||||
The total and free memory of a specific process.
|
||||
|
||||
### --feedback--
|
||||
|
||||
These methods measure system-level memory, not app-level memory.
|
||||
|
||||
---
|
||||
|
||||
The total and free disk storage space.
|
||||
|
||||
### --feedback--
|
||||
|
||||
These methods measure system-level memory, not app-level memory.
|
||||
|
||||
---
|
||||
|
||||
The total and free system memory in bytes.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
## --text--
|
||||
|
||||
Which of these is a possible value returned by the `os.arch()` method in Node.js?
|
||||
|
||||
## --answers--
|
||||
|
||||
`'Windows'`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Look out for what represents the CPU architecture Node.js was compiled for.
|
||||
|
||||
---
|
||||
|
||||
`'x64'`
|
||||
|
||||
---
|
||||
|
||||
`'intel'`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Look out for what represents the CPU architecture Node.js was compiled for.
|
||||
|
||||
---
|
||||
|
||||
`'CPU1'`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Look out for what represents the CPU architecture Node.js was compiled for.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
What does the Node.js OS module allow you to do?
|
||||
|
||||
## --answers--
|
||||
|
||||
Interact with the current operating system to access details like CPU, memory, and network info.
|
||||
|
||||
---
|
||||
|
||||
Interact with databases and perform SQL queries.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on what gives Node access to system-level info such as OS type and memory details.
|
||||
|
||||
---
|
||||
|
||||
Handle HTTP requests and responses between the client and server.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on what gives Node access to system-level info such as OS type and memory details.
|
||||
|
||||
---
|
||||
|
||||
Manage file uploads and read data from streams.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on what gives Node access to system-level info such as OS type and memory details.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02ca
|
||||
title: What Is the Path Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-path-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The Node.js `path` module lets you work with files and directory paths. It provides several useful methods for handling and transforming directories, including joining, normalizing, and resolving the directories across different platforms and operating systems.
|
||||
|
||||
To use the `path` module, you can import it like this:
|
||||
|
||||
```js
|
||||
const path = require("path");
|
||||
```
|
||||
|
||||
Let's look at some of the methods the `path` module provides and how they work.
|
||||
|
||||
First, you should be aware of the Node.js global variables `__filename` and `__dirname`, AKA "common JS" variables. You don't need the `path` module to access them, which is why they are called global variables.
|
||||
|
||||
`__filename` is the absolute path of the current file and `__dirname` is the absolute path of the directory containing the current file.
|
||||
|
||||
For example, I have a `script.js` file I'm currently working with. Here's what the two methods return:
|
||||
|
||||
```js
|
||||
console.log(__filename);
|
||||
// /Users/user/Desktop/fCC/script-code/node/node-path/script.js
|
||||
|
||||
console.log(__dirname);
|
||||
// /Users/user/Desktop/fCC/script-code/node/node-path
|
||||
```
|
||||
|
||||
You should also be aware of relative and absolute paths.
|
||||
|
||||
A relative path points to a file or folder based on your current working directory. For example, `./assets/src/text-files`.
|
||||
|
||||
An absolute path, on the other hand, gives the complete address of a file or folder from the root of your system, such as `/Users/johndoe/projects/app/assets/src/text-files.`
|
||||
|
||||
The `basename()` method shows the last part of the file, that is, the filename:
|
||||
|
||||
```js
|
||||
console.log(path.basename(__filename)); // script.js
|
||||
```
|
||||
|
||||
`dirname()` returns the directory name of a path:
|
||||
|
||||
```js
|
||||
console.log(path.dirname(__dirname)); // node-path
|
||||
```
|
||||
|
||||
`extname()` returns the extension of the current file:
|
||||
|
||||
```js
|
||||
console.log(path.extname(__filename)); // .js
|
||||
```
|
||||
|
||||
You can also specify a different file to return the extension of:
|
||||
|
||||
```js
|
||||
console.log(path.extname('text-files/text1.txt')); // .txt
|
||||
```
|
||||
|
||||
The `join()` method takes all the path segments you pass in and joins them into one clean, normalized path.
|
||||
|
||||
This could be useful if you want to merge related files in different folders so you can work with them together:
|
||||
|
||||
```js
|
||||
const joinedPath = path.join("src", "assets", "text-files");
|
||||
console.log(joinedPath); // src/assets/text-files
|
||||
```
|
||||
|
||||
Windows uses backslashes to separate directories, so the result will be `src\assets\text-files`.
|
||||
|
||||
In addition, the `join()` method automatically fixes wrong slashes and removes extra ones:
|
||||
|
||||
```js
|
||||
const wrongPath = path.join("/src//", "assets", "text-files");
|
||||
console.log(wrongPath); // /src/assets/text-files
|
||||
```
|
||||
|
||||
The `resolve()` method turns a sequence of path segments into an absolute path. It starts from your current working directory and results in a full path that points to the exact location on the device:
|
||||
|
||||
```js
|
||||
const absolutePath = path.resolve("assets", "src", "text-files");
|
||||
console.log(absolutePath);
|
||||
// /Users/user/Desktop/fCC/script-code/node/node-path/assets/src/text-files
|
||||
```
|
||||
|
||||
The difference between `join()` and `resolve()` is that `join()` creates a relative path, while `resolve()` returns an absolute path.
|
||||
|
||||
Lastly, there are the `parse()` and `format()` methods.
|
||||
|
||||
`parse()` takes a directory or file and returns an object that contains the breakdown of its parts, such as the system root, its directory, extension, and the filename:
|
||||
|
||||
```js
|
||||
const parsedFile = path.parse(__filename);
|
||||
|
||||
console.log(parsedFile);
|
||||
/*
|
||||
{
|
||||
root: '/',
|
||||
dir: '/Users/user/Desktop/fCC/script-code/node/node-path',
|
||||
base: 'script.js',
|
||||
ext: '.js',
|
||||
name: 'script'
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
`format()`, on the other hand, builds a path from an object containing directory, name, and extension:
|
||||
|
||||
```js
|
||||
const formattedDirectory = path.format({
|
||||
dir: "/users/johndoe/docs",
|
||||
name: "file",
|
||||
ext: ".txt",
|
||||
});
|
||||
|
||||
console.log(formattedDirectory); // /users/johndoe/docs/file.txt
|
||||
```
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
What is the difference between `path.dirname()` and `path.extname()` in Node.js?
|
||||
|
||||
## --answers--
|
||||
|
||||
`dirname()` removes the file extension, while `extname()` removes the directory name.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on which one deals with directories and which one deals with file extensions.
|
||||
|
||||
---
|
||||
|
||||
`dirname()` returns the full file path, while `extname()` returns the directory name.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on which one deals with directories and which one deals with file extensions.
|
||||
|
||||
---
|
||||
|
||||
`dirname()` returns the directory name of a path, while `extname()` returns the file's extension.
|
||||
|
||||
---
|
||||
|
||||
`dirname()` and `extname()` both return the same value but in different formats.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Focus on which one deals with directories and which one deals with file extensions.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
## --text--
|
||||
|
||||
Which `path` method builds a complete file path from an object containing directory, name, and extension properties?
|
||||
|
||||
## --answers--
|
||||
|
||||
`path.parse()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about what the opposite of `parse()` is.
|
||||
|
||||
---
|
||||
|
||||
`path.format()`
|
||||
|
||||
---
|
||||
|
||||
`path.resolve()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about what the opposite of `parse()` is.
|
||||
|
||||
---
|
||||
|
||||
`path.join()`
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about what the opposite of `parse()` is.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
What do the Node.js global variables `__filename` and `__dirname` provide access to?
|
||||
|
||||
## --answers--
|
||||
|
||||
The absolute path of the current file and its containing directory.
|
||||
|
||||
---
|
||||
|
||||
The name of the current module and its dependencies.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which variables automatically give you full file and folder paths without using the path module.
|
||||
|
||||
---
|
||||
|
||||
The relative path to the Node.js installation directory.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which variables automatically give you full file and folder paths without using the path module.
|
||||
|
||||
---
|
||||
|
||||
The URL of the running web server and its hostname.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about which variables automatically give you full file and folder paths without using the path module.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02cb
|
||||
title: What Is the Process Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-process-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
`process` is one of the most important Node.js core modules. It gives you access to information about the current Node.js process, and lets you control it while your app is running.
|
||||
|
||||
When you execute a command like `node script.js` in the terminal, Node.js starts a process, which is a running instance of the Node program that executes the `script.js` file. This process has its own memory, environment, and execution context.
|
||||
|
||||
The current process is exposed globally through the `process` module, so you don't even need to import it. As long as you have Node.js installed, then you can call it anywhere.
|
||||
|
||||
The `process` module exposes properties and methods for you to get certain information about the current execution context.
|
||||
|
||||
`process.env` gets you information about the current environment Node is running on. This always returns a giant object with many parameters, so here's how you can access some of the most important information directly:
|
||||
|
||||
```js
|
||||
// Gets all environment variables available to the current Node.js process
|
||||
console.log(process.env);
|
||||
|
||||
// Gets the current Node.js environment mode (like 'development' or 'production')
|
||||
console.log(process.env.NODE_ENV); // development
|
||||
|
||||
// Gets the path of the shell program running the Node.js process
|
||||
console.log(process.env.SHELL); // /bin/bash
|
||||
|
||||
// Gets the system PATH variable where executables are searched for
|
||||
console.log(process.env.PATH); // /usr/local/bin:/usr/bin:/bin
|
||||
|
||||
// Gets the present working directory from where the process was started
|
||||
console.log(process.env.PWD); // /Users/johndoe/projects/myapp
|
||||
|
||||
// Gets the username of the user running the current process
|
||||
console.log(process.env.USER); // johndoe
|
||||
```
|
||||
|
||||
`process.argv` lets you read command-line arguments:
|
||||
|
||||
```js
|
||||
console.log(process.argv);
|
||||
/*
|
||||
script.js --watch
|
||||
Hello world
|
||||
[
|
||||
'/Users/user/.nvm/versions/node/v22.17.0/bin/node',
|
||||
'/Users/user/Desktop/fCC/script-code/node/node-process/script.js',
|
||||
'--watch'
|
||||
]
|
||||
*/
|
||||
```
|
||||
|
||||
The `cwd()` method shows the current working directory:
|
||||
|
||||
```js
|
||||
console.log(process.cwd());
|
||||
```
|
||||
|
||||
Process events are a core feature of Node.js that let your app respond to key moments in its lifecycle, like when it's about to exit, encounters an error, or receives a system signal.
|
||||
|
||||
The `exit` event, for example, runs right before the Node.js process finishes:
|
||||
|
||||
```js
|
||||
process.on("exit", (code) => {
|
||||
console.log(`Process exiting with code: ${code}`);
|
||||
});
|
||||
|
||||
// Process exiting with code: 0
|
||||
```
|
||||
|
||||
The `uncaughtException` event is triggered when an error is not caught in your code, which can help you prevent crashes:
|
||||
|
||||
```js
|
||||
process.on("uncaughtException", (err) => {
|
||||
console.error("Uncaught error:", err.message);
|
||||
});
|
||||
```
|
||||
|
||||
Lastly, the `warning` event is triggered when Node.js emits a process warning:
|
||||
|
||||
```js
|
||||
process.on("warning", (warning) => {
|
||||
console.warn("Warning name:", warning.name);
|
||||
console.warn("Warning message:", warning.message);
|
||||
});
|
||||
```
|
||||
|
||||
You can then use the `emitWarning()` method to trigger a custom warning:
|
||||
|
||||
```js
|
||||
// Example warning with the emitWarning() method
|
||||
process.emitWarning('This is a custom warning message', 'CustomWarning');
|
||||
|
||||
/*
|
||||
Warning name: CustomWarning
|
||||
Warning message: This is a custom warning message
|
||||
*/
|
||||
```
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
What does the `process.emitWarning()` method do?
|
||||
|
||||
## --answers--
|
||||
|
||||
It stops the process when a custom warning occurs.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles custom warnings through events.
|
||||
|
||||
---
|
||||
|
||||
It triggers a custom warning event that can be handled by the warning listener.
|
||||
|
||||
---
|
||||
|
||||
It logs an error and exits the process immediately.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles custom warnings through events.
|
||||
|
||||
---
|
||||
|
||||
It restarts the Node.js process after showing a warning.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles custom warnings through events.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
## --text--
|
||||
|
||||
How do you use the process module?
|
||||
|
||||
## --answers--
|
||||
|
||||
By calling it directly since it's a global object.
|
||||
|
||||
---
|
||||
|
||||
By enabling it in the Node.js configuration file.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about why you can access process anywhere without setup.
|
||||
|
||||
---
|
||||
|
||||
By installing it manually using npm before calling it.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about why you can access process anywhere without setup.
|
||||
|
||||
---
|
||||
|
||||
By importing it using require('process') before each use.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about why you can access process anywhere without setup.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
## --text--
|
||||
|
||||
What are process events used for?
|
||||
|
||||
## --answers--
|
||||
|
||||
To define environment variables for the application.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js reacts to lifecycle changes during execution.
|
||||
|
||||
---
|
||||
|
||||
To create new processes for parallel execution.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js reacts to lifecycle changes during execution.
|
||||
|
||||
---
|
||||
|
||||
To listen for and respond to important lifecycle moments like exit, errors, or system signals.
|
||||
|
||||
---
|
||||
|
||||
To manage file paths and extensions in the system.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js reacts to lifecycle changes during execution.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
---
|
||||
id: 695cc8f280fef0cc3bed02cc
|
||||
title: What Is the Stream Module and How Does It Work?
|
||||
challengeType: 19
|
||||
dashedName: what-is-the-stream-module-and-how-does-it-work
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The last core Node.js module we'll look at is `stream`. This module helps you handle data efficiently, especially when the data is too large to load all at once, like reading a big text file or downloading a large video.
|
||||
|
||||
Instead of waiting to read or write all the data before doing anything, streams process chunks of data as they arrive, similar to how you can start watching a YouTube video before the whole video finishes loading.
|
||||
|
||||
There are four main types of streams in Node.js: readable, writable, duplex, and transform:
|
||||
|
||||
- Readable streams let you read data in chunks (for example, reading a large file).
|
||||
- Writable streams let you write data in chunks (for example, saving a file).
|
||||
- Duplex streams can both read and write data.
|
||||
- Transform streams are a special kind of duplex stream that can change or process the data as it flows through.
|
||||
|
||||
You can import the stream classes you need by destructuring them from the stream module:
|
||||
|
||||
```js
|
||||
const { Readable, Writable, Transform } = require("stream");
|
||||
```
|
||||
|
||||
Most of the time, you don't need to create custom stream classes yourself. For everyday file operations, built-in methods like `fs.createReadStream()` and `fs.createWriteStream()` are usually all you need.
|
||||
|
||||
These two methods take the path of the file to read or write. This means you also need the `fs` and `path` modules to implement streaming on many occasions.
|
||||
|
||||
Here's how you can read data from a file, say an `input.txt` file:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const inputFilePath = path.join(__dirname, "input.txt");
|
||||
|
||||
// Readable stream
|
||||
const readInputFileStream = fs.createReadStream(inputFilePath);
|
||||
console.log(readInputFileStream);
|
||||
```
|
||||
|
||||
This will not do anything yet, as you need to use the events from the stream to read the data. For example, you can listen to the `data` event this way:
|
||||
|
||||
```js
|
||||
readInputFileStream.on("data", (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes of data`);
|
||||
}); // Received 622 bytes of data
|
||||
```
|
||||
|
||||
You can also log the chunk of data to the console:
|
||||
|
||||
```js
|
||||
readInputFileStream.on("data", (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes of data`);
|
||||
console.log("Received data:", chunk);
|
||||
});
|
||||
|
||||
/*
|
||||
Received 622 bytes of data
|
||||
Received data: <Buffer 4c 6f 72 65 6d 20 69 70 73 75 6d
|
||||
20 64 6f 6c 6f 72 20 73 69 74 20 61 6d 65 74 20 63 6f 6e
|
||||
73 65 63 74 65 74 75 72 20 61 64 69 70 69 73 69 63 69 6e 67 ... 572 more bytes>
|
||||
*/
|
||||
```
|
||||
|
||||
Since it returns a buffer, you can call the `toString()` method to convert it into readable text:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const inputFilePath = path.join(__dirname, "input.txt");
|
||||
|
||||
// Readable stream
|
||||
const readInputFileStream = fs.createReadStream(inputFilePath);
|
||||
|
||||
readInputFileStream.on("data", (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes of data`);
|
||||
console.log("Received data:", chunk.toString());
|
||||
});
|
||||
/*
|
||||
Received 622 bytes of data
|
||||
Received data: Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus sint facilis
|
||||
aliquid. Odio voluptatibus veniam saepe consectetur alias modi non fuga in,
|
||||
tempore explicabo numquam maiores quod inventore quibusdam! Nam cumque repellat
|
||||
facere voluptatem nulla aliquam atque ratione numquam ea aperiam porro ducimus
|
||||
animi tempora laboriosam, labore quae voluptatum? Nam, hic quas dolore
|
||||
repudiandae placeat eius! Voluptate reiciendis totam hic expedita tenetur. Nisi
|
||||
ipsa ad facere optio sint debitis. Magni nostrum sit ipsa saepe suscipit facilis
|
||||
eaque doloribus assumenda, minima fuga tempore, porro, debitis rem harum in
|
||||
*/
|
||||
```
|
||||
|
||||
To implement a writable stream, particularly when you're reading from one file and writing to another, you need to create the read stream first, followed by the write stream:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const inputFilePath = path.join(__dirname, "input.txt");
|
||||
const outputFilePath = path.join(__dirname, "output.txt");
|
||||
|
||||
// Create the read stream first
|
||||
const readInputFileStream = fs.createReadStream(inputFilePath);
|
||||
|
||||
// Create the write stream
|
||||
const writeOutputFileStream = fs.createWriteStream(outputFilePath);
|
||||
```
|
||||
|
||||
Next, use the `.pipe()` method to connect the readable stream to the writable stream. This lets Node.js automatically read data from the source and write it to the destination, chunk by chunk:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const inputFilePath = path.join(__dirname, "input.txt");
|
||||
const outputFilePath = path.join(__dirname, "output.txt");
|
||||
|
||||
// Create the read stream first
|
||||
const readInputFileStream = fs.createReadStream(inputFilePath);
|
||||
|
||||
// Create the write stream
|
||||
const writeOutputFileStream = fs.createWriteStream(outputFilePath);
|
||||
|
||||
// Pipe the read stream to the write stream
|
||||
readInputFileStream.pipe(writeOutputFileStream);
|
||||
```
|
||||
|
||||
Then you can listen for the `finish` and `error` events on the writable stream to know when the streaming is complete or if something goes wrong:
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const inputFilePath = path.join(__dirname, "input.txt");
|
||||
const outputFilePath = path.join(__dirname, "output.txt");
|
||||
|
||||
// Create the read stream first
|
||||
const readInputFileStream = fs.createReadStream(inputFilePath);
|
||||
|
||||
// Create the write stream
|
||||
const writeOutputFileStream = fs.createWriteStream(outputFilePath);
|
||||
|
||||
readInputFileStream.pipe(writeOutputFileStream);
|
||||
|
||||
writeOutputFileStream.on("finish", () => {
|
||||
console.log("All data has been written to the file");
|
||||
});
|
||||
|
||||
writeOutputFileStream.on("error", (err) => {
|
||||
console.error("Error writing to file:", err);
|
||||
});
|
||||
```
|
||||
|
||||
The `finish` event tells you that the stream is complete and there is no more data to write, while the error event helps you catch problems that might happen during writing, like permissions issues or missing directories.
|
||||
|
||||
# --questions--
|
||||
|
||||
## --text--
|
||||
|
||||
Which of these are the four main types of streams?
|
||||
|
||||
## --answers--
|
||||
|
||||
Request, Response, Event, and Error streams.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles reading, writing, and transforming data.
|
||||
|
||||
---
|
||||
|
||||
Readable, Editable, Duplex, and Transform streams.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles reading, writing, and transforming data.
|
||||
|
||||
---
|
||||
|
||||
Data, File, HTTP, and Buffer streams.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles reading, writing, and transforming data.
|
||||
|
||||
---
|
||||
|
||||
Readable, Writable, Duplex, and Transform streams.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
## --text--
|
||||
|
||||
What lets you implement a custom readable and writable stream?
|
||||
|
||||
## --answers--
|
||||
|
||||
The `stream` module using Readable and Writable classes.
|
||||
|
||||
---
|
||||
|
||||
The `http` module.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the module that provides base classes for creating custom streams.
|
||||
|
||||
---
|
||||
|
||||
The `fs` module using `createReadStream()` and `createWriteStream()`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles reading, writing, and transforming data.
|
||||
|
||||
---
|
||||
|
||||
The events module.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about how Node.js handles reading, writing, and transforming data.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
## --text--
|
||||
|
||||
What events can you use on a writable stream to know when streaming completes or an error occurs?
|
||||
|
||||
## --answers--
|
||||
|
||||
`end` and `close`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the writable stream events that signal completion and failure.
|
||||
|
||||
---
|
||||
|
||||
`finish` and `error`.
|
||||
|
||||
---
|
||||
|
||||
`start` and `stop`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the writable stream events that signal completion and failure.
|
||||
|
||||
---
|
||||
|
||||
`done` and `fail`.
|
||||
|
||||
### --feedback--
|
||||
|
||||
Think about the writable stream events that signal completion and failure.
|
||||
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "Working with Node Core Modules",
|
||||
"isUpcomingChange": true,
|
||||
"dashedName": "lecture-working-with-node-core-modules",
|
||||
"helpCategory": "Backend Development",
|
||||
"blockLayout": "challenge-list",
|
||||
"challengeOrder": [
|
||||
{
|
||||
"id": "695cc6a5eefd305381ec90bc",
|
||||
"title": "What Is the fs Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02c7",
|
||||
"title": "What Is the Buffer Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02c8",
|
||||
"title": "What Is the Crypto Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02c9",
|
||||
"title": "What Is the os Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02ca",
|
||||
"title": "What Is the Path Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02cb",
|
||||
"title": "What Is the Process Module and How Does It Work?"
|
||||
},
|
||||
{
|
||||
"id": "695cc8f280fef0cc3bed02cc",
|
||||
"title": "What Is the Stream Module and How Does It Work?"
|
||||
}
|
||||
],
|
||||
"blockLabel": "lecture"
|
||||
}
|
||||
@@ -16,7 +16,11 @@
|
||||
{
|
||||
"dashedName": "nodejs-core-modules",
|
||||
"comingSoon": true,
|
||||
"blocks": ["review-node-js-core-modules", "quiz-node-js-core-modules"]
|
||||
"blocks": [
|
||||
"lecture-working-with-node-core-modules",
|
||||
"review-node-js-core-modules",
|
||||
"quiz-node-js-core-modules"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dashedName": "node-package-manager",
|
||||
|
||||
Reference in New Issue
Block a user