<?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>DEV Community: Connor Bode</title>
    <description>The latest articles on DEV Community by Connor Bode (@connorbode).</description>
    <link>https://dev.to/connorbode</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%2F131532%2F8e99ebc3-406e-415f-9571-9157b5320ede.jpg</url>
      <title>DEV Community: Connor Bode</title>
      <link>https://dev.to/connorbode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/connorbode"/>
    <language>en</language>
    <item>
      <title>Why I run my own software business (Part 1)</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Wed, 13 Jan 2021 05:38:15 +0000</pubDate>
      <link>https://dev.to/connorbode/why-i-run-my-own-software-business-part-1-f66</link>
      <guid>https://dev.to/connorbode/why-i-run-my-own-software-business-part-1-f66</guid>
      <description>&lt;p&gt;I've been running &lt;a href="https://matix.io"&gt;https://matix.io&lt;/a&gt; since 2014. It definitely hasn't been the easiest path.. but if I could do it over I wouldn't change a thing.&lt;/p&gt;

&lt;p&gt;Why go through the struggle? It's a much safer bet to take a full-time job and great jobs aren't hard to find as a software developer.&lt;/p&gt;

&lt;p&gt;In this 6 part series I'm going to be covering why I choose to run my own software development business, instead of working for an organization.&lt;/p&gt;

&lt;h1&gt;
  
  
  Part 1: Independence
&lt;/h1&gt;

&lt;p&gt;When I was younger, my father made a tough decision to take a job 3,000 kilometers away from his family. He would work three weeks away from home, and be home for one week. It was really tough for us. It caused tension between him and my mother, and nearly broke the family apart.&lt;/p&gt;

&lt;p&gt;It's debatable whether he needed to do this. There are always options, but my father took the job because he felt he needed to bring in more money to support his family. Where we were living, the opportunities in his line of work weren't providing sufficient income. He had climbed the ladder to a management role, but felt restricted. He considered other professions, but the time &amp;amp; money investment was too great - he needed to support his family now. Knowing he could make substantially more in a different location, he took that leap.&lt;/p&gt;

&lt;p&gt;A few years after, my family relocated to where my father was working &amp;amp; earning more. I made the decision not to go. I was nearing the end of high school and nearly ready to be on my own. I had friends and a life, and wasn't prepared to start over in a new place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overall, these years were full of hardship for myself and for my family.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being a skilled employee comes with great comforts. You have a regular salary. That salary will be deposited in your bank account with such certainty that you can expect it to be there. Your employer withholds your income taxes, so you don't have to worry about coming up short when it's tax season. The government provides you with employee protections - if you get fired, you're getting a nice comfy package to help you coast until you find your next job. Everything is great! Buy a house, get a car, save for retirement. You're living the dream.&lt;/p&gt;

&lt;p&gt;But you're dependent on the job market. You're dependent on the demand for your skilled expertise. You're dependent on your employer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running a business is different.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My entry into business was by selling a service, my skilled expertise. At the surface, it's not that much different than an employee-employer relationship where expertise is traded for money. My employer is my client.&lt;/p&gt;

&lt;p&gt;There's more risk of them not paying, and I have to handle everything from finding them (sales) to sending them a bill (accounting). There are no employee protections. Sounds like a shit deal.&lt;/p&gt;

&lt;p&gt;But there's a hidden gem here: you start developing the skills to generate money on your own. You look for opportunities to provide value &amp;amp; earn money, because if you don't you will starve. You repeat the process more frequently than you would in a long-term employment position. You iterate to survive. You hone your resilience.&lt;/p&gt;




&lt;p&gt;You can see a sneak preview of the next chapters of this story in this Twitter thread (&amp;amp; if you like my story &amp;amp; my writing, please follow me!)&lt;/p&gt;



&lt;blockquote class="twitter-tweet"&gt;
&lt;br&gt;
&lt;p&gt;1) Independence: when I was younger, my dad had to make some tough decisions about working out of town. It was hard for our family, and I don't want to put my family through the same experience. I've made a lot of decisions to reduce my dependence on others (including employers).&lt;/p&gt;— Connor Bode (&lt;a class="comment-mentioned-user" href="https://dev.to/connorbode"&gt;@connorbode&lt;/a&gt;
) &lt;a href="https://twitter.com/connorbode/status/1347094783747969029?ref_src=twsrc%5Etfw"&gt;January 7, 2021&lt;/a&gt;&lt;br&gt;
&lt;/blockquote&gt; 

</description>
      <category>career</category>
      <category>freelancing</category>
      <category>business</category>
      <category>entrepreneur</category>
    </item>
    <item>
      <title>If you're freelancing, you need to track these metrics.</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Wed, 28 Oct 2020 22:39:16 +0000</pubDate>
      <link>https://dev.to/connorbode/if-you-re-freelancing-you-need-to-track-these-metrics-560k</link>
      <guid>https://dev.to/connorbode/if-you-re-freelancing-you-need-to-track-these-metrics-560k</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I just published a lengthy tweet about important data for freelancers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/connorbode/status/1321491561897586690"&gt;https://twitter.com/connorbode/status/1321491561897586690&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would love a boost! If you like the content, follow me on Twitter and on IH for more.&lt;/p&gt;

&lt;p&gt;Summary: I talk about metrics you should keep track of in your sales, project management, and accounting activities.&lt;/p&gt;

</description>
      <category>freelance</category>
    </item>
    <item>
      <title>HTMLField with Image Uploads in Django Admin</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Tue, 07 Apr 2020 03:12:01 +0000</pubDate>
      <link>https://dev.to/connorbode/htmlfield-with-image-uploads-in-django-admin-ec9</link>
      <guid>https://dev.to/connorbode/htmlfield-with-image-uploads-in-django-admin-ec9</guid>
      <description>&lt;p&gt;Well, this is mostly a reminder for myself on how to do this. The goal is to set up a generic "HTMLField" for models, which you can add photos to as well.&lt;/p&gt;

&lt;p&gt;Here are the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://github.com/romanvm/django-tinymce4-lite"&gt;django-tinymce4-lite&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://github.com/smacker/django-filebrowser-no-grappelli"&gt;django-filebrowser-no-grappelli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In your &lt;code&gt;settings.py&lt;/code&gt;, add &lt;code&gt;X_FRAME_OPTIONS = 'sameorigin'&lt;/code&gt; (the filebrowser uses an iFrame which gets blocked by default)&lt;/li&gt;
&lt;li&gt;Let's say your MEDIA_ROOT is &lt;code&gt;/media&lt;/code&gt;, and you want to upload files to &lt;code&gt;/media/uploads&lt;/code&gt;. In &lt;code&gt;settings.py&lt;/code&gt;, add &lt;code&gt;FILEBROWSER_DIRECTORY = 'uploads/'&lt;/code&gt;. Then, make sure &lt;code&gt;/media/uploads&lt;/code&gt; actually is a folder, or you will see an error.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>django</category>
    </item>
    <item>
      <title>Copy-paste in tmux</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Tue, 24 Mar 2020 20:00:16 +0000</pubDate>
      <link>https://dev.to/connorbode/copy-paste-in-tmux-1gdj</link>
      <guid>https://dev.to/connorbode/copy-paste-in-tmux-1gdj</guid>
      <description>&lt;p&gt;tmux is a great tool if you live in the shell. Sometimes you'll need to copy-paste between windows &amp;amp; panes. If you have a vertically split window, you can't use the mouse to copy text from one side to the other.&lt;/p&gt;

&lt;p&gt;Here's how to copy-paste between tmux windows or panes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ctrl+b,[&lt;/code&gt; allows you to move your cursor around&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+space&lt;/code&gt; starts copying from where the cursor is&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+w&lt;/code&gt; grabs the selection to the tmux clipboard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+b,]&lt;/code&gt; pastes the clipboard out to the current window / pane&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it, hope it helps you!&lt;/p&gt;




&lt;p&gt;If this helped you, follow me on dev.to for more tips. I use dev.to as a journal, where I record any tricks that I see myself using regularly. You'll probably find it useful too!&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>linux</category>
      <category>macos</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Image Resizing from the shell</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Sat, 21 Dec 2019 22:41:07 +0000</pubDate>
      <link>https://dev.to/connorbode/image-resizing-from-the-shell-4jfl</link>
      <guid>https://dev.to/connorbode/image-resizing-from-the-shell-4jfl</guid>
      <description>&lt;p&gt;Here's a scenario I encounter pretty often:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I download an image from Unsplash&lt;/li&gt;
&lt;li&gt;I move the image into the folder of a webapp&lt;/li&gt;
&lt;li&gt;The image is like 1GB because it's so high quality, and that's no good for download speeds from the webapp&lt;/li&gt;
&lt;li&gt;I need to resize it to make it smaller.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could open up a GUI to resize the image (preview on MacOS works really well for this).. but sometimes I just want to stay in teh terminal.&lt;/p&gt;

&lt;p&gt;The tool to solve the problem in the terminal is ImageMagick.&lt;/p&gt;

&lt;p&gt;There are two commands I typically use. The first is &lt;code&gt;identify &amp;lt;image&amp;gt;&lt;/code&gt; which will tell you the current width &amp;amp; height of the image.&lt;/p&gt;

&lt;p&gt;The second I use is &lt;code&gt;convert &amp;lt;source_image&amp;gt; -resize 1000x &amp;lt;destination_image&amp;gt;&lt;/code&gt;. This will resize the source image to a width of 1000px, and will maintain the aspect ratio for the height.&lt;/p&gt;

&lt;p&gt;There's a lot more you can do with ImageMagick tools. If you know some tricks, let everyone know in teh comments!&lt;/p&gt;




&lt;p&gt;Hopefully this is useful for you. If you're looking for more tips on Linux &amp;amp; development, follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>macos</category>
    </item>
    <item>
      <title>Running (and killing) multiple processes in a single shell script</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Wed, 11 Dec 2019 19:48:53 +0000</pubDate>
      <link>https://dev.to/connorbode/running-and-killing-multiple-processes-in-a-single-shell-script-1kki</link>
      <guid>https://dev.to/connorbode/running-and-killing-multiple-processes-in-a-single-shell-script-1kki</guid>
      <description>&lt;p&gt;Something I'm regularly doing during my daily development is running build / server processes.  &lt;/p&gt;

&lt;p&gt;For example, right now I'm working on a project that requires a Django development web server as well as a &lt;code&gt;sass --watch&lt;/code&gt; process to compile CSS.  Often I'm also running some node processes like &lt;code&gt;react-native&lt;/code&gt; or &lt;code&gt;babel&lt;/code&gt; or something.&lt;/p&gt;

&lt;p&gt;For me, it's annoying to have 10 terminals open running all of these processes. &lt;/p&gt;

&lt;p&gt;I'd rather run it in a single file. A common solution is to use the latest build utility to wire everything up.  My opinion is that it's more useful &amp;amp; natural to just call the binaries directly from a bash script.&lt;/p&gt;

&lt;p&gt;Here's how you can run multiple processes at once (assuming we have binaries or shell scripts called &lt;code&gt;program_1&lt;/code&gt;, &lt;code&gt;program_2&lt;/code&gt;, and &lt;code&gt;program_3&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# start the first program and fork it&lt;/span&gt;
program_1 &amp;amp;

&lt;span class="c"&gt;# store the process ID&lt;/span&gt;
&lt;span class="nv"&gt;program_1_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="c"&gt;# start the second program and fork it&lt;/span&gt;
program_2 &amp;amp;

&lt;span class="c"&gt;# store the process ID&lt;/span&gt;
&lt;span class="nv"&gt;program_2_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="c"&gt;# trap ctrl-c so that we can kill&lt;/span&gt;
&lt;span class="c"&gt;# the first two programs&lt;/span&gt;
&lt;span class="nb"&gt;trap &lt;/span&gt;onexit INT
&lt;span class="k"&gt;function &lt;/span&gt;onexit&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="nv"&gt;$program_1_pid&lt;/span&gt;
  &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="nv"&gt;$program_2_pid&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# start the third program, don't fork it&lt;/span&gt;
program_3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it.  Name this script something like &lt;code&gt;script.sh&lt;/code&gt; and run it using &lt;code&gt;bash script.sh&lt;/code&gt;.  All three of your programs will run.  When you exit (by pressing ctrl+c), first &lt;code&gt;program_3&lt;/code&gt; will quit, then the function &lt;code&gt;onexit&lt;/code&gt; will execute, stopping the other two programs.&lt;/p&gt;




&lt;p&gt;That's all for now, hopefully this will help you in your dev life.&lt;/p&gt;

&lt;p&gt;Follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt; for more as I learn &amp;amp; build.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
    </item>
    <item>
      <title>Chaining SSH tunnels</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Tue, 10 Dec 2019 22:56:49 +0000</pubDate>
      <link>https://dev.to/connorbode/chaining-ssh-tunnels-3dfg</link>
      <guid>https://dev.to/connorbode/chaining-ssh-tunnels-3dfg</guid>
      <description>&lt;p&gt;So here's my scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Machine A has SSH exposed to the internet&lt;/li&gt;
&lt;li&gt;Machine B is on the same LAN as Machine A, but is not exposed to the internet&lt;/li&gt;
&lt;li&gt;Machine A has SSH access to Machine B via the LAN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's say I'm outside the network and I want to have direct access to a port on Machine B (maybe I need to &lt;code&gt;rsync&lt;/code&gt; something using the SSH port, or maybe I want to forward a database port).  For this example, we'll assume we want to forward SSH port 22.&lt;/p&gt;

&lt;h2&gt;
  
  
  Port forward Machine B to Machine A
&lt;/h2&gt;

&lt;p&gt;First, let's make Machine B's SSH port available from Machine A&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh machine_a &lt;span class="c"&gt;# to open a shell on Machine A&lt;/span&gt;
ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 2222:localhost:22 machine_b &lt;span class="c"&gt;# to open a tunnel from Machine B to Machine A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(Leave this shell open and start a new one for the next step)&lt;/p&gt;

&lt;h2&gt;
  
  
  Port forward Machine A to my computer
&lt;/h2&gt;

&lt;p&gt;Next, let's forward the port we opened to our local machine&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 2222:localhost:2222 machine_a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Use the port
&lt;/h2&gt;

&lt;p&gt;Now you can use the SSH port to directly access Machine B:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-p2222&lt;/span&gt; localhost &lt;span class="c"&gt;# to open a shell on Machine B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or SCP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-P2222&lt;/span&gt; /path/to/item localhost:/remote/path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or &lt;code&gt;rsync&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;rsync &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'ssh -p2222'&lt;/span&gt; /path/to/item localhost:/remote/path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Hope this helps!&lt;/p&gt;




&lt;p&gt;If you found this helpful, follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt; for more on Linux, coding, etc.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ssh</category>
    </item>
    <item>
      <title>.ai files on Linux</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Thu, 28 Nov 2019 17:35:00 +0000</pubDate>
      <link>https://dev.to/connorbode/ai-files-on-linux-4lhl</link>
      <guid>https://dev.to/connorbode/ai-files-on-linux-4lhl</guid>
      <description>&lt;p&gt;Designers work with all sorts of programs, and most of them don't run on Linux.&lt;/p&gt;

&lt;p&gt;Adobe Illustrator is one of those programs.&lt;/p&gt;

&lt;p&gt;If you're a developer on Linux and a designer hands you a .ai file to work with, it's going to make your life difficult.&lt;/p&gt;

&lt;p&gt;Here are some tricks I've learned to get what you need out of the illustrator file:&lt;/p&gt;

&lt;h2&gt;
  
  
  Adobe Illustrator .ai files are just PDFs
&lt;/h2&gt;

&lt;p&gt;This is great, because it allows us to use various PDF tools to extract the information we need.&lt;/p&gt;

&lt;p&gt;We're going to make use of &lt;a href="https://poppler.freedesktop.org/"&gt;poppler&lt;/a&gt;, a PDF library, to extract some of the information we need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting images from an Adobe Illustrator .ai file on Linux
&lt;/h2&gt;

&lt;p&gt;From poppler, we get the &lt;code&gt;pdfimages&lt;/code&gt; command, which will dump all of the images inside of a .ai file.&lt;/p&gt;

&lt;p&gt;Here's the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pdfimages my_file.pdf /output/directory/image-file-prefix
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Images will be exported as &lt;code&gt;/output/directory/image-file-prefix-000.ppm&lt;/code&gt;, &lt;code&gt;/output/directory/image-file-prefix-001.ppm&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;From there, you can open the images and convert them as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting fonts from an Adobe Illustrator .ai file on Linux
&lt;/h2&gt;

&lt;p&gt;Poppler also gives us &lt;code&gt;pdffonts&lt;/code&gt; to list the fonts in a .ai file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pdffonts my_file.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Extracting vector art from a .ai file on Linux
&lt;/h2&gt;

&lt;p&gt;Unfortunately, I don't have a great solution for this.  It seems that there are tools to export your .ai file to a giant .svg, but there would be many layers within that SVG.&lt;/p&gt;

&lt;p&gt;Since the vector you want to export can be complex, and might include multiple layers itself, the user would have to interact at this point in order to choose which layers make up the object we want to export.&lt;/p&gt;

&lt;p&gt;Inkscape is one solution, but it is very slow for large .ai files and exporting objects is tedious.&lt;/p&gt;

&lt;p&gt;GIMP may be able to do this, but I've not yet discovered the way.  For the moment, I'm just screenshotting the vectors and luckily I haven't needed any transparent backgrounds so far.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you have tips here, please comment!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;That's all for now.  Follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt; for more on Linux, Python, VIM, etc.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>pdf</category>
      <category>illustrator</category>
      <category>ai</category>
    </item>
    <item>
      <title>Checking the licenses used by your NPM dependencies</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Thu, 21 Nov 2019 16:32:59 +0000</pubDate>
      <link>https://dev.to/connorbode/checking-the-licenses-used-by-your-npm-dependencies-58bi</link>
      <guid>https://dev.to/connorbode/checking-the-licenses-used-by-your-npm-dependencies-58bi</guid>
      <description>&lt;p&gt;Hey everyone, just a quick tip on how you can audit your NPM dependencies to make sure you're not infringing copyright.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do I care about licensing?
&lt;/h2&gt;

&lt;p&gt;Open-source software is great, but it doesn't necessarily mean it's free to use.  Software projects are released under difference licenses.  Typically in a project repo, this will be in the &lt;code&gt;LICENSE&lt;/code&gt; file in the top level of the repo.&lt;/p&gt;

&lt;p&gt;The way you license your software defines many things including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether you grant use of the software&lt;/li&gt;
&lt;li&gt;Whether you grant commercial use of the software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;These two points are extremely important.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might think the software you are using is free until you get slapped with an invoice or a lawsuit!  &lt;/p&gt;

&lt;p&gt;As an example that's not related to NPM but is related to software licensing, check out &lt;a href="https://www.virtualbox.org/wiki/Licensing_FAQ"&gt;VirtualBox's licences&lt;/a&gt;.  tldr; VirtualBox is licensed under GPL2, while VirtualBox Extensions are under a custom license which requires a fee for commercial use.  Supplementary reading: &lt;a href="https://www.theregister.co.uk/2019/10/04/oracle_virtualbox_merula/"&gt;Oracle demands $12,200 for use of VirtualBox Extension Pack&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we verify the licenses of the packages we're using?
&lt;/h2&gt;

&lt;p&gt;This ends up being pretty easy due to &lt;a href="https://www.npmjs.com/package/license-checker"&gt;&lt;code&gt;license-checker&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's the procedure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;npm install license-checker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx license-checker&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will give you a printout of all the licensing details of packages used in your project.  &lt;/p&gt;

&lt;p&gt;Other cool features of the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Print a summary of licenses used by &lt;code&gt;npx license-checker --summary&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Include it in your CI/CD pipeline by providing it with a whitelist or a blacklist of licenses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope this helps you to audit the packages you're using!&lt;/p&gt;




&lt;p&gt;I write about development stuff in all sorts of areas (Node, Python, Linux, Android, iOS, etc.).  If you're interested, follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt;.  I'll keep writing as I learn &amp;amp; discover. &lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>meta</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>The best way to KILL (..a process on Mac or Linux)</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Thu, 14 Nov 2019 17:21:56 +0000</pubDate>
      <link>https://dev.to/connorbode/the-best-way-to-kill-30ad</link>
      <guid>https://dev.to/connorbode/the-best-way-to-kill-30ad</guid>
      <description>&lt;p&gt;What's the best way to kill a process in Linux (or Mac)?&lt;/p&gt;

&lt;p&gt;Ok, I lied, it's actually probably not the &lt;strong&gt;best&lt;/strong&gt; way.  There are probably better ways to use only &lt;code&gt;ps&lt;/code&gt; to find the processes you're looking for.  But this method uses two awesome shell tools, &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;awk&lt;/code&gt;, which you can use in other ways.&lt;/p&gt;

&lt;p&gt;The final command I use is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kill -9 $(ps aux | grep "[y]our-process-name" | awk '{print $2}')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's going to send a &lt;code&gt;SIGKILL&lt;/code&gt; to every process you grepped for.&lt;/p&gt;

&lt;p&gt;How did we get there?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Find the processes you want to shut down&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ps aux&lt;/code&gt; is going to print out all of the processes currently running, including the name of the user that is running it.&lt;/p&gt;

&lt;p&gt;We don't necessarily need all that information right now, but it's a good command to remember if you ever need to see what's running on a system.&lt;/p&gt;

&lt;p&gt;Next, we'll filter out the processes we want to find using a search query.  Often, I'm trying to kill detached Django dev server instances, which run under the command &lt;code&gt;python manage.py runserver&lt;/code&gt;.  To filter those out, I'll run &lt;code&gt;ps aux | grep manage.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, this also locates the &lt;code&gt;grep&lt;/code&gt; process itself (since &lt;code&gt;grep&lt;/code&gt; will be running still when &lt;code&gt;ps aux&lt;/code&gt; is executed).  By the time we get to our &lt;code&gt;kill&lt;/code&gt; function, the &lt;code&gt;grep&lt;/code&gt; process will be finished, so I use a little trick to filter out the &lt;code&gt;grep&lt;/code&gt;: &lt;code&gt;ps aux | grep "[m]anage.py"&lt;/code&gt;.  If you want to skip that, no problem.. you'll just see an error message that you weren't able to kill one of the processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Get the process IDs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;awk&lt;/code&gt; is a cool tool designed for processing patterns &amp;amp; text.  After we run &lt;code&gt;ps aux | grep "[m]anage.py"&lt;/code&gt;, we have tabular output. The process ID is in the second column of the output, and &lt;code&gt;awk&lt;/code&gt; helps us to only print that second column.&lt;/p&gt;

&lt;p&gt;How?&lt;/p&gt;

&lt;p&gt;You just pipe your output to &lt;code&gt;awk '{print $2}'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Kill it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, we wrap all of that up into a subquery, and kill the result:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kill -9 $(ps aux | grep "[m]anage.py" | awk '{print $2}')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep in mind that this is a process suicide, not graceful shutdown.  You can do a lot more with &lt;a href="https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals"&gt;POSIX signals&lt;/a&gt; if you're interested.&lt;/p&gt;




&lt;p&gt;Hopefully this tip was helpful for you!&lt;/p&gt;

&lt;p&gt;Follow me here on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt; for more on Linux, web, and app development!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>macos</category>
    </item>
    <item>
      <title>Creating a Postgres database + user</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Mon, 04 Nov 2019 17:40:37 +0000</pubDate>
      <link>https://dev.to/connorbode/creating-a-postgres-database-user-f3h</link>
      <guid>https://dev.to/connorbode/creating-a-postgres-database-user-f3h</guid>
      <description>&lt;p&gt;Let's create a new database + a user to access it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;su - postgres&lt;/code&gt; to get a shell as the postgres user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;psql&lt;/code&gt; to get a postgres shell&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create database db_name;&lt;/code&gt; to create the database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create user user_name with encrypted password 'user_password';&lt;/code&gt; to create the user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grant all privileges on database db_name to user_name;&lt;/code&gt; to grant the user all privileges on the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it really.&lt;/p&gt;




&lt;p&gt;As a brief aside, I like to write my SQL in all lowercase.  I find it really annoying to use all caps for statements and all lowercase for variables, which seems to be a syntactic standard with no real benefit?  Anyone else do this / have a comment on this?&lt;/p&gt;




&lt;p&gt;Follow me on dev.to for more code blurbs, or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>sql</category>
    </item>
    <item>
      <title>@property decorator</title>
      <dc:creator>Connor Bode</dc:creator>
      <pubDate>Tue, 29 Oct 2019 12:30:10 +0000</pubDate>
      <link>https://dev.to/connorbode/property-decorator-2d38</link>
      <guid>https://dev.to/connorbode/property-decorator-2d38</guid>
      <description>&lt;p&gt;Just a quick blurb about a nice feature in Python.&lt;/p&gt;

&lt;p&gt;Let's say you have the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can create a new person like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mickey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Micky'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Mouse'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# spoiler, he's not actually a person
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You might find yourself often wanting to get Mickey's full name, "Mickey Mouse" in your code.  To do this, you'll probably do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fullname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mickey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mickey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;
&lt;span class="c1"&gt;# or maybe you'll use format, or printf, 
# depending on your style and how much coffee you've had that day.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, after you get tired of doing that all the time, you'll go back and add a method to your Person class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and you'll instead use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mickey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# ==&amp;gt; Mickey Mouse
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;now.. the &lt;code&gt;@property&lt;/code&gt; decorator really just gives us a coding style advantage.  &lt;code&gt;mickey.name&lt;/code&gt; would feel more natural than &lt;code&gt;mickey.name()&lt;/code&gt;, since the name is always returning the same value, and feels more like a property than a function.&lt;/p&gt;

&lt;p&gt;So how is it used?&lt;/p&gt;

&lt;p&gt;Again, let's modify the class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;

  &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we can get the name as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mickey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;# ==&amp;gt; Mickey Mouse
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;That's it for now!  If you're interested in Python, Django, Linux, VIM, tmux (and all these other random tools in my tech stack) follow me on dev.to or on &lt;a href="https://twitter.com/connorbode"&gt;Twitter @connorbode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll post tips as I code!&lt;/p&gt;

</description>
      <category>python</category>
    </item>
  </channel>
</rss>
