<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ahmed Elbilal</title>
    <description>The latest articles on Forem by Ahmed Elbilal (@ahmedsudani).</description>
    <link>https://forem.com/ahmedsudani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F969336%2F1bdb6f6e-829a-45e0-8fc6-a511a31d2a36.jpeg</url>
      <title>Forem: Ahmed Elbilal</title>
      <link>https://forem.com/ahmedsudani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ahmedsudani"/>
    <language>en</language>
    <item>
      <title>GraphQL VS API Graph with 2 same examples</title>
      <dc:creator>Ahmed Elbilal</dc:creator>
      <pubDate>Tue, 04 Apr 2023 08:41:18 +0000</pubDate>
      <link>https://forem.com/ahmedsudani/graphql-vs-api-graph-with-2-examples-34f6</link>
      <guid>https://forem.com/ahmedsudani/graphql-vs-api-graph-with-2-examples-34f6</guid>
      <description>&lt;p&gt;GraphQL is all about asking the API for what exactly I need rather than it gives me the whole data, but introduced new concepts like &lt;code&gt;resolvers&lt;/code&gt; and &lt;code&gt;mutations&lt;/code&gt; and changes the whole way you use to write your APIs.&lt;/p&gt;

&lt;p&gt;api-graph is also all about asking the API for what exactly I require rather than it gives me the complete data, but &lt;code&gt;without&lt;/code&gt; changing anything that you use to write.&lt;/p&gt;

&lt;p&gt;We will go throughout to two examples that do the same thing, the first one uses GraphQL and the second uses api-graph.&lt;/p&gt;

&lt;p&gt;It's a simple example that don't use any database, all the data are stored in memory. The two examples have an array of warriors data that includes id and name then we will try to extract one of those two fields but the two libraries GraphQL and api-graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL example
&lt;/h2&gt;

&lt;p&gt;this example is from &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-graphql-api-server-in-node-js" rel="noopener noreferrer"&gt;digitalocean&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express from "express";
import cors from "cors";
import { graphqlHTTP } from "express-graphql";
import { makeExecutableSchema } from "@graphql-tools/schema";

const app = express();
const port = 4000;

// In-memory data store
const data = {
  warriors: [
    { id: "001", name: "Ahmed" },
    { id: "002", name: "Abdalla" },
  ],
};

// Schema
const typeDefs = `
type Warrior {
  id: ID!
  name: String!
}

type Query {
  warriors: [Warrior]
}
`;

// Resolver for warriors
const resolvers = {
  Query: {
    warriors: (obj, args, context) =&amp;gt; context.warriors,
  },
};

const executableSchema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Entrypoint
app.use(
  "/graphql",
  graphqlHTTP({
    schema: executableSchema,
    context: data,
    graphiql: true,
  })
);

app.listen(port, () =&amp;gt; {
  console.log(`Running a server at http://localhost:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuqv6vl5llfitkuo3oez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuqv6vl5llfitkuo3oez.png" alt="GraphQL" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  api-graph example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express from "express";
import cors from "cors";
import apiGraph from "api-graph";

const app = express();
const port = 4000;

// In-memory data store
const data = {
  warriors: [
    { id: "001", name: "Jaime" },
    { id: "002", name: "Jorah" },
  ],
};

app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(apiGraph({ extract: "query" }));
app.post("/api-graph", (req, res) =&amp;gt; res.json(data));
app.listen(port, () =&amp;gt; {
  console.log(`Running a server at http://localhost:${port}`);
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5ixitm3j4fwousrjbex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5ixitm3j4fwousrjbex.png" alt="API Graph" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;api-graph saves the way you use to write apis and GraphQL uses &lt;code&gt;resolvers&lt;/code&gt;, &lt;code&gt;mutations&lt;/code&gt; and changes every thing.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;memory cost&lt;/code&gt; of import in GraphQL is &lt;code&gt;height&lt;/code&gt;, while in api it's &lt;code&gt;low&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrf7ani34hsa5xssjrbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrf7ani34hsa5xssjrbu.png" alt="graphql cost of import" width="729" height="40"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4u08evw592i7s8s6476z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4u08evw592i7s8s6476z.png" alt="api-graph cost of import" width="471" height="27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL More writing while api-graph less writing&lt;/li&gt;
&lt;li&gt;GraphQL &lt;code&gt;{ warriors  { id } }&lt;/code&gt; api-graph &lt;code&gt;{ warriors  : [ { id } ] }&lt;/code&gt; GraphQL use graph query language, but api-graph uses string JSON without values.&lt;/li&gt;
&lt;li&gt;GraphQL has a playground that you can send request from it in the development process, which means it has documents for API, api-graph don't have.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graphql</category>
      <category>javascript</category>
      <category>api</category>
      <category>apigraph</category>
    </item>
    <item>
      <title>Graph query your data in REST API without GraphQL</title>
      <dc:creator>Ahmed Elbilal</dc:creator>
      <pubDate>Sun, 02 Apr 2023 10:07:37 +0000</pubDate>
      <link>https://forem.com/ahmedsudani/graphql-in-your-rest-api-with-one-line-2olp</link>
      <guid>https://forem.com/ahmedsudani/graphql-in-your-rest-api-with-one-line-2olp</guid>
      <description>&lt;h2&gt;
  
  
  API-Graph
&lt;/h2&gt;

&lt;p&gt;Specify exactly what you want from the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckxlpxcb8nvxd2m6e1ok.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckxlpxcb8nvxd2m6e1ok.jpg" alt="why to use GraphQL" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;graph queries&lt;/code&gt; in your rest API &lt;code&gt;without the need for graphQl&lt;/code&gt; and &lt;code&gt;without editing any parts of your logic in the endpoints code&lt;/code&gt;, it just works, but adding &lt;code&gt;one middleware&lt;/code&gt; in your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install api-graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;To use this package, you will need to import it and use it as middleware in your express application. Here is an example of how to use it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import apiGraph from "api-graph";
import express from "express";

const user = {
  id: 1,
  name: "ahmed",
  age: 23,
  photos: [
    { id: 1, path: "img1" },
    { id: 2, path: "img2" },
  ],
};

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(apiGraph({ extract: "graph" }));
app.get("/", (req, res) =&amp;gt; res.json(user));
app.listen(3000, () =&amp;gt; console.log("server running at 3000"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you pass what fields you want to return in body fields when you request the endpoint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body : { graph : "{id, name}" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that's it, only the name and id will be returned from the endpoint&lt;/p&gt;

&lt;h2&gt;
  
  
  Postman
&lt;/h2&gt;

&lt;p&gt;An image that showing sending a request from postman&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F017x69b8puo9c610yzml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F017x69b8puo9c610yzml.png" alt="an image that showing sending a request from postman" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it works&lt;br&gt;
The imported middleware &lt;code&gt;apiGraph&lt;/code&gt; which is the main function that must add to the app, it takes one parameter the extract which is the key that the server will look at when trying to get the query send from the client, and the &lt;code&gt;default&lt;/code&gt; value for it is &lt;code&gt;graphQuery&lt;/code&gt;. The server then gets the values from the key to parse it and extract data from the object that was passed to &lt;code&gt;res.json&lt;/code&gt; function, in case no query was sent from the client then the whole data will be returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;property not found in case you were trying to ask for fields in the data that are not exits.&lt;/li&gt;
&lt;li&gt;Parsing error in case you send an invalid query.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Feel free to take look at api-graph sites in &lt;a href="https://github.com/ahmed-sudani/api-graph" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and in &lt;a href="https://www.npmjs.com/package/api-graph" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>api</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Building “.ignore” mechanism with 30 lines of code</title>
      <dc:creator>Ahmed Elbilal</dc:creator>
      <pubDate>Sun, 27 Nov 2022 14:51:16 +0000</pubDate>
      <link>https://forem.com/ahmedsudani/building-ignore-mechanism-with-30-lines-of-code-4hkg</link>
      <guid>https://forem.com/ahmedsudani/building-ignore-mechanism-with-30-lines-of-code-4hkg</guid>
      <description>&lt;p&gt;Recently we have seen &lt;code&gt;.Ignore&lt;/code&gt; files a lot in many places, GitHub has &lt;code&gt;.gitignore&lt;/code&gt; to ignore file that will not be committed also prettier &lt;code&gt;.prettierignore&lt;/code&gt; to ignore files that will not be formatted and more others. So how can I build such a mechanism ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it will work ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will load the file and change all of it's content to &lt;code&gt;regex&lt;/code&gt; so that we can make the comparing functionality more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fs&lt;/code&gt; module&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will be using &lt;code&gt;fs&lt;/code&gt; module which is one of NodeJS core modules, &lt;code&gt;fs&lt;/code&gt; have promises object which contains a promise version of core &lt;code&gt;fs&lt;/code&gt; functions like &lt;code&gt;raedFile&lt;/code&gt; and &lt;code&gt;writeFile&lt;/code&gt; to help us work with &lt;code&gt;async/await&lt;/code&gt; to make the code cleaner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loading the file&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require("fs");
const loadIgnoreFile = async (file) =&amp;gt; {
  let loadedFile = await fs.promises.readFile(path, { encoding: "utf8" });
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Change &lt;code&gt;*&lt;/code&gt; to &lt;code&gt;.*&lt;/code&gt; for pattern ignore&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;.ignore&lt;/code&gt; files, a person could want to ignore a pattern of files, for example all &lt;code&gt;*.json&lt;/code&gt; files, but regex could understand * with a character before because * means that the preceding character can be repeater more than one time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //change all * to .*
  loadedFile = loadedFile.replace(/\*/g, ".*");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File content to array&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //change file to array
  loadedFile = loadedFile.split("\n");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resolve array items to paths&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, if a person wanted to ignore &lt;code&gt;dist&lt;/code&gt; folder he could enter &lt;code&gt;dist&lt;/code&gt;, &lt;code&gt;./dest&lt;/code&gt; or &lt;code&gt;/dist&lt;/code&gt; which can make the comparison operation more difficult. So we change what ever he entered to a full file path, so the three options of &lt;code&gt;dist&lt;/code&gt; folder will be for example &lt;code&gt;/home/user/project/dist&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //resolve all files
  loadedFile = loadedFile.map((item) =&amp;gt; join(resolve("."), item));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Change paths to groups of regex&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A group in regex in something between two &lt;code&gt;()&lt;/code&gt; for example (ABC) is a group. And then separate each group from other by or operator &lt;code&gt;|&lt;/code&gt; and then to make the regex only restricted to that path we will add &lt;code&gt;^ $&lt;/code&gt; to each regex path. So in our work if we have two paths, let us say &lt;code&gt;/home/user/project/dist&lt;/code&gt; and &lt;code&gt;/home/user/project/node_mdules&lt;/code&gt; they are at the end after converting them to regex will be &lt;code&gt;(^/home/user/project/dist&amp;amp;)|(^/home/user/project/node_mdules$)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //add (^filename$) to all content
  loadedFile = "(^" + loadedFile.join("$)|(^") + "$)";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Returning the result in RegExp object&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  //change loaded file content to regex
  return new RegExp(loadedFile);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;We could also add some checks to see if the file exits and return a default regex if not before we go to all these steps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Final code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require("fs");
const { resolve, join } = require("path");

//load ignore file
const loadIgnoreFile = async (  const path = ".ignore") =&amp;gt; {
  const dfReg = "(.git$)|(node_modules$)";

  //check if .ignore exits
  const ptIgnoreExits = fs.existsSync(path);
  if (!ptIgnoreExits) return new RegExp(dfReg);

  //load .ignore
  let loadedFile = await fs.promises.readFile(path, { encoding: "utf8" });

  // add .git and node_modules to loaded file
  loadedFile += "\n.git\nnode_modules";

  //change all * to .*
  loadedFile = loadedFile.replace(/\*/g, ".*");

  //change .ignore to array
  loadedFile = loadedFile.split("\n");

  //resolve all files
  loadedFile = loadedFile.map((item) =&amp;gt; join(resolve("."), item));

  //add (^filename$) to all content
  loadedFile = "(^" + loadedFile.join("$)|(^") + "$)";

  //change loaded file content to regex
  return new RegExp(loadedFile);
};

module.exports = loadIgnoreFile;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test it&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a simple test and will not contain any test runners or any frameworks like jest or others&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create a file say &lt;code&gt;.ignore&lt;/code&gt; and add to it some dummy names say &lt;code&gt;dist1&lt;/code&gt; and &lt;code&gt;dist2&lt;/code&gt; and put the &lt;code&gt;.ignore&lt;/code&gt; along with this code in the same folder. Create a new file called &lt;code&gt;ignore.test.js&lt;/code&gt; and import the &lt;code&gt;loadIgnore&lt;/code&gt; function and run a function in &lt;code&gt;loadIgnore&lt;/code&gt; called &lt;code&gt;test&lt;/code&gt; since &lt;code&gt;loadIgnore&lt;/code&gt; is actually a regex object as we see above, the &lt;code&gt;test&lt;/code&gt; function will return a boolean value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const loadIgnore = require('./loadIgnore.js');
const filePath = join(resolve("."), "dist1"))
console.log(loadIgnore.test(filePath));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Automate project tree with protree</title>
      <dc:creator>Ahmed Elbilal</dc:creator>
      <pubDate>Sat, 19 Nov 2022 11:11:51 +0000</pubDate>
      <link>https://forem.com/ahmedsudani/automate-project-tree-with-protree-53j7</link>
      <guid>https://forem.com/ahmedsudani/automate-project-tree-with-protree-53j7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Intro&lt;/strong&gt;&lt;br&gt;
Some projects use a tree structure in their README file as some form of good documentation, which may look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── file1
├── file2
└── dir1
│   └── file3
└── dir2
    └── file4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Issue&lt;/strong&gt;&lt;br&gt;
The documentation may be forgotten by some developers, and if they remember, it may be a noisy process to move through the new files and then to align those tree characters &lt;code&gt;└── ├──&lt;/code&gt;  correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protree Automation&lt;/strong&gt;&lt;br&gt;
protree is a CLI tool build with JS to help in building the project tree structure. Protree can create a tree for your project and add it to your markdown with the &lt;code&gt;code block&lt;/code&gt; format. Once you add new files to your project, all you have to do is run protree, and all changes will be handled automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I will assume that you have a project with come folders in it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1- First install protree&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i protree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Command form&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protree path out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Add script to your &lt;code&gt;package.json&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
...
"protree" : "protree . README.md"
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- Add a protree &lt;code&gt;comment&lt;/code&gt; in your README.md file in the place you want the tree to be in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- protree --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5- Run command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run protree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ingoring files&lt;/strong&gt;&lt;br&gt;
By default, protree ignores the &lt;code&gt;.git&lt;/code&gt; and &lt;code&gt;node_modules&lt;/code&gt; directories.&lt;br&gt;
It is possible to exclude more files from being included in the tree structure by creating a &lt;code&gt;.ptignore&lt;/code&gt; file and adding all the ignored files to it.&lt;br&gt;
The &lt;code&gt;.ptignore&lt;/code&gt; file works similarly to the &lt;code&gt;.gitignore&lt;/code&gt; file. You can ignore files or patterns of files, for example, &lt;code&gt;*.json&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;Feel free to read more about &lt;a href="https://github.com/ahmed-sudani/protree#readme" rel="noopener noreferrer"&gt;protree&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
