<?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: Christian Bewernitz</title>
    <description>The latest articles on DEV Community by Christian Bewernitz (@karfau).</description>
    <link>https://dev.to/karfau</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%2F2370%2Fkarfau.png</url>
      <title>DEV Community: Christian Bewernitz</title>
      <link>https://dev.to/karfau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/karfau"/>
    <language>en</language>
    <item>
      <title>Release 0.9.0 of `@xmldom/xmldom`</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Thu, 29 Aug 2024 20:06:11 +0000</pubDate>
      <link>https://dev.to/karfau/release-090-of-xmldomxmldom-4106</link>
      <guid>https://dev.to/karfau/release-090-of-xmldomxmldom-4106</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;xmldom is a javascript &lt;a href="https://ponyfill.com/" rel="noopener noreferrer"&gt;ponyfill&lt;/a&gt; to provide the following APIs &lt;a href="https://caniuse.com/xml-serializer" rel="noopener noreferrer"&gt;that are present in modern browsers&lt;/a&gt; to other runtimes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;convert an XML string into a DOM tree
```
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;new DOMParser().parseFromString(xml, mimeType) =&amp;gt;  Document&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- create, access and modify a DOM tree
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;new DOMImplementation().createDocument(...) =&amp;gt; Document&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- serialize a DOM tree back into an XML string
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;new XMLSerializer().serializeToString(node) =&amp;gt; string&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/xmldom/xmldom/#readme" rel="noopener noreferrer"&gt;xmldom readme&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;Since I started contributing to the forked &lt;code&gt;xmldom&lt;/code&gt; library in June 2020, there have been 40 releases.&lt;/p&gt;

&lt;p&gt;It is a very interesting and challenging project and will most likely stay that way for quite a while.&lt;/p&gt;

&lt;p&gt;According to GitHub over 50 people have contributed to it since it was forked.&lt;/p&gt;

&lt;p&gt;Thank you again to all contributors.&lt;/p&gt;

&lt;p&gt;And this doesn't count all the people that managed to make the move from the original unscoped &lt;code&gt;xmldom&lt;/code&gt; package, to the scoped &lt;code&gt;@xmldom/xmldom&lt;/code&gt; package version &lt;code&gt;0.7.0&lt;/code&gt; to get all security fixes. &lt;br&gt;
&lt;a href="https://github.com/xmldom/xmldom/discussions/270" rel="noopener noreferrer"&gt;The most recent version released as the &lt;code&gt;lts&lt;/code&gt; tag is &lt;code&gt;0.7.13&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last version with breaking changes was &lt;a href="https://github.com/xmldom/xmldom/releases/tag/0.8.0" rel="noopener noreferrer"&gt;&lt;code&gt;0.8.0&lt;/code&gt; which was released on Dec 22, 2021&lt;/a&gt;, almost 3 years ago. &lt;br&gt;
&lt;a href="https://github.com/xmldom/xmldom/discussions/357" rel="noopener noreferrer"&gt;The most recent version released as &lt;code&gt;latest&lt;/code&gt; is &lt;code&gt;0.8.10&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  0.9.0 (2024-08-29)
&lt;/h2&gt;

&lt;p&gt;But what I want to talk about today is &lt;a href="https://github.com/xmldom/xmldom/discussions/435" rel="noopener noreferrer"&gt;all the stuff that has been released under the &lt;code&gt;next&lt;/code&gt; tag&lt;/a&gt; since October 2022.&lt;/p&gt;

&lt;p&gt;I'm really excited about those changes since they are providing a clear foundation for potential future changes.&lt;/p&gt;

&lt;p&gt;TLDR: More alignment with the specs, and differences are made as explicit as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Enforcing &lt;code&gt;mimeType&lt;/code&gt; to give back control
&lt;/h3&gt;

&lt;p&gt;One aspect that makes the implementation complex, is that there are different rules for parsing XML vs HTML.&lt;br&gt;
&lt;code&gt;xmldom&lt;/code&gt; (to some degree) "supported" both flavors from the beginning. It was even not required to pass a &lt;code&gt;mimeType&lt;/code&gt; at all: What rules to apply was decided based on the current default namespace of the XML string/node that was currently being parsed.&lt;/p&gt;

&lt;p&gt;This ends with 0.9.0: From now on the &lt;code&gt;mimeType&lt;/code&gt; in &lt;code&gt;DOMParser.parseFromString(xml, mimeType)&lt;/code&gt; is mandatory and is the only thing that is ever checked to decide whether to apply XML or HTML rules. Basta.&lt;/p&gt;

&lt;p&gt;And that information is preserved in the resulting &lt;code&gt;Document&lt;/code&gt; (new &lt;code&gt;type&lt;/code&gt; property), so when serializing it, the proper rules are applied again.&lt;/p&gt;

&lt;p&gt;This was a massive (and potentially breaking) change, but I'm really excited it is ready, since it made tons of related bug fixes possible/way simpler to implement and also reduces the complexity of the API and the implementation.&lt;/p&gt;

&lt;p&gt;Additionally it now only accepts the &lt;a href="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring-dev" rel="noopener noreferrer"&gt;mime types specified&lt;/a&gt;, and throws a &lt;code&gt;TypeError&lt;/code&gt; in any other case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strictness and Error handling
&lt;/h3&gt;

&lt;p&gt;An aspect that personally confuses me about the error handling of the native browser API is that it always returns a Document and if something went wrong, a &lt;code&gt;parsererror&lt;/code&gt; node will be the first child of the &lt;code&gt;body&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu0e0r53x6jb7l55yggku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu0e0r53x6jb7l55yggku.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since error handling never worked this way in &lt;code&gt;xmldom&lt;/code&gt; but the existing error handling was very complex and confusing and badly documented, 0.9.0 simplifies it and now has a (way more) consistent behavior towards any potential error that happens during parsing: &lt;br&gt;
It throws a &lt;code&gt;ParseError&lt;/code&gt; 🎉, e.g. in one of the following cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In previous versions it was possible for some non well-formed XML strings, that the returned &lt;code&gt;Document&lt;/code&gt; would not have a &lt;code&gt;documentElement&lt;/code&gt;, which will most likely lead to &lt;code&gt;TypeError&lt;/code&gt;s later in the code.&lt;/li&gt;
&lt;li&gt;several non well-formed XML strings will now properly be reported as &lt;code&gt;fatalError&lt;/code&gt; which now always prevents any further processing.&lt;/li&gt;
&lt;li&gt;several things that have previously not been reported as an error or only have been reported as a &lt;code&gt;warning&lt;/code&gt; are now also reported as a &lt;code&gt;fatalError&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are still cases left which are reported as a &lt;code&gt;warning&lt;/code&gt; (especially when parsing HTML) or as an &lt;code&gt;error&lt;/code&gt; which do not stop the data from being processed, but the new error handling makes it very easy to decide how strict the code that uses &lt;code&gt;xmldom&lt;/code&gt; needs to be.&lt;/p&gt;

&lt;p&gt;The (non spec compliant) option that can be passed to the &lt;code&gt;DOMParser&lt;/code&gt; constructor is called &lt;code&gt;onError&lt;/code&gt;.&lt;br&gt;
it takes a function with the following signature:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;ErrorLevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DOMHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ErrorLevel&lt;/code&gt; is either &lt;code&gt;warning&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt; or &lt;code&gt;fatalError&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;xmldom already provides an implementaiton for the two most common use cases:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onErrorStopParsing&lt;/code&gt; to throw a &lt;code&gt;ParseError&lt;/code&gt; also for all &lt;code&gt;error&lt;/code&gt; level issues&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onWarningStopParsing&lt;/code&gt; to throw a &lt;code&gt;ParseError&lt;/code&gt; also for all &lt;code&gt;error&lt;/code&gt; level issues&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;It is a recommendation to apply one of them to stop processing XML on the first signal of anything unexpected:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;// prevent parsing of XML that has &lt;code&gt;error&lt;/code&gt;s&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DOMParser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;onErrorStopParsing&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;parseFromString&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;br&gt;
&lt;span class="c1"&gt;// prevent parsing of XML that has &lt;code&gt;warning&lt;/code&gt;s&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DOMParser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;onWarningStopParsing&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;parseFromString&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  &lt;code&gt;compareDocumentPosition&lt;/code&gt;, extended HTML entities , &lt;code&gt;null&lt;/code&gt; instead of &lt;code&gt;undefined&lt;/code&gt;, ...&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Another fork of the original &lt;code&gt;xmldom&lt;/code&gt; repository made it's way back into our repo by extending the HTML entities to the complete set (also available in 0.8.x) and porting over the implementation of the &lt;code&gt;compareDocumentPosition&lt;/code&gt; API. Thank you, and welcome &lt;a href="https://github.com/zorkow" rel="noopener noreferrer"&gt;&lt;code&gt;@zorkow&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Along the way several places where xmldom so far returned &lt;code&gt;undefined&lt;/code&gt; instead of &lt;code&gt;null&lt;/code&gt;, have been fixed to adhere to the spec.&lt;/p&gt;

&lt;p&gt;And I discovered that the former author seems to have preferred iterating from the end of a list in so many places, that attributes were processed in the reverse order in multiple places, which is now fixed.&lt;/p&gt;

&lt;p&gt;The implementation of the &lt;code&gt;removeChild&lt;/code&gt; API changed quite a bit, to comply to the spec and throws a &lt;code&gt;DOMException&lt;/code&gt; when it should.&lt;/p&gt;

&lt;p&gt;And 3 related bugs were fixed in a way that clearly states what the future direction of &lt;code&gt;xmldom&lt;/code&gt; is:&lt;br&gt;
Support for lax HTML parsing rules will only be provided if proper strict XML parsing doesn't suffer from it.&lt;br&gt;
The former (broken) "support" for automatic self closing tags in HTML is gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  coctype internalSubset
&lt;/h2&gt;

&lt;p&gt;More recently &lt;a href="https://github.com/shunkica" rel="noopener noreferrer"&gt;&lt;code&gt;@shunkica&lt;/code&gt;&lt;/a&gt; invested a huge amount of time end effort to fix tons of issues in the former handling of the &lt;code&gt;internalSubset&lt;/code&gt; part of the &lt;code&gt;!DOCTYPE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is now preserved as part of the &lt;code&gt;internalSubset&lt;/code&gt; property of the &lt;code&gt;doctype&lt;/code&gt; of a &lt;code&gt;Document&lt;/code&gt; and many wrong doctype declarations are now correctly detected as such and reported as a &lt;code&gt;fatalError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also thanks to &lt;a href="https://github.com/kboshold" rel="noopener noreferrer"&gt;&lt;code&gt;@kboshold&lt;/code&gt;&lt;/a&gt; for the latest bug fix in this area.&lt;/p&gt;

&lt;p&gt;Along the way we created a new module containing regular expressions for the relevant grammar, and correctness checks are based on those and they are properly covered by tests.&lt;/p&gt;

&lt;p&gt;It is not the goal of xmldom to become a &lt;a href="https://www.w3.org/TR/xml11/#proc-types" rel="noopener noreferrer"&gt;validating parser&lt;/a&gt;, but this a great step to support those documents that come with more complex DTDs.&lt;/p&gt;

&lt;h3&gt;
  
  
  And there is even more
&lt;/h3&gt;

&lt;p&gt;Up to now development was done using Node v10, since this is also the lowest version xmldom currently supports. As part of the work on the upcoming version, I decided to switch to v18 for development, since more and more devDependencies also made this a minimum requirement. This will be the new minimum runtime version for the time being starting with this release.&lt;/p&gt;

&lt;p&gt;I initiated a &lt;a href="https://github.com/xmldom/xmldom/discussions/495" rel="noopener noreferrer"&gt;public poll / dicussion&lt;/a&gt; to ask people which version of Node or other runtimes they need support for.&lt;br&gt;
The next breaking release will most likely drop support for some older Node versions, if there is no feedback indicating something different.&lt;/p&gt;

&lt;p&gt;Along the way plenty of APIs have received jsdoc comments with proper types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thank you
&lt;/h3&gt;

&lt;p&gt;for taking the time to read through all of this.&lt;/p&gt;

&lt;p&gt;Those are quite some changes, and I'm very excited to be able to ship those. &lt;/p&gt;

&lt;p&gt;I hope you are as excited as I am :)&lt;/p&gt;

&lt;p&gt;If you need more details you can go through the very detailed &lt;a href="https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md" rel="noopener noreferrer"&gt;changelog&lt;/a&gt;, or head over to the repository and &lt;a href="https://github.com/xmldom/xmldom/discussions" rel="noopener noreferrer"&gt;join or start a discussion&lt;/a&gt; or file an issue.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>xml</category>
      <category>opensource</category>
      <category>release</category>
    </item>
    <item>
      <title>Tired of approving dependency PRs?</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Sat, 19 Aug 2023 17:01:56 +0000</pubDate>
      <link>https://dev.to/karfau/tired-of-approving-dependency-prs-1ep3</link>
      <guid>https://dev.to/karfau/tired-of-approving-dependency-prs-1ep3</guid>
      <description>&lt;h2&gt;
  
  
  Dependency PRs?
&lt;/h2&gt;

&lt;p&gt;I'm a huge fan of &lt;a href="https://www.mend.io/renovate/"&gt;https://www.mend.io/renovate/&lt;/a&gt; for updating dependencies PR by PR for multiple reasons.&lt;/p&gt;

&lt;p&gt;So much that I even created a &lt;a href="https://github.com/bettermarks/renovate-config"&gt;shared config at work&lt;/a&gt; with some nice docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Well, they have a automerge option, right?
&lt;/h2&gt;

&lt;p&gt;Yes, and recently it is implemented by enabling "automerge" in GitHub!&lt;/p&gt;

&lt;p&gt;But for most repositories it is reasonable to require somebody to review code changes before they land, which is why we have branch protection with some status checks and at least one reviewer approval.&lt;/p&gt;

&lt;p&gt;And since we don't want the dependency PRs to get into the way, the default option we use is to only automatically create and update them outside of office hours.&lt;/p&gt;

&lt;p&gt;And to reduce cost for GitHub actions that are run for each dependency update PR, we only ever create one at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeated manual work...
&lt;/h2&gt;

&lt;p&gt;So&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the creation of dependency update PRs is automated&lt;/li&gt;
&lt;li&gt;and the testing is automated&lt;/li&gt;
&lt;li&gt;for landing them it still requires a human to approve. Outside of office hours. (So it's either unlikely to get more than a handful landed per day, or it encourages people to work outside of office hours.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this means they usually pile up, as it visible on the nice Dependency Dashboard renovate offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  ... should be automated
&lt;/h2&gt;

&lt;p&gt;I had some attempts on researching different options to solve this problem, like adding some github app and configuring them or adding github actions that would take care of it, but it all sounded quite complicated, so I never really did something about it.&lt;/p&gt;

&lt;p&gt;Recently I listened to &lt;a href="https://changelog.com/jsparty/287"&gt;https://changelog.com/jsparty/287&lt;/a&gt; and learned about &lt;a href="https://val.town"&gt;https://val.town&lt;/a&gt;&lt;br&gt;
I registered during listening to the episode (using my GitHub account) and went through the short introduction tour.&lt;/p&gt;

&lt;p&gt;I didn't immediately have an idea what to do with it, but I was sure it wouldn't take long.&lt;/p&gt;

&lt;p&gt;Last week it hit me:&lt;br&gt;
How difficult would it be to create a val that acts as a webhook for github that would automatically approve PRs that are qualified?&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.val.town/v/karfau.githubWebhookApproveDependencyPRs" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--UbuFE8c9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.val.town/v/karfau.githubWebhookApproveDependencyPRs/thumbnail.png%3Fv%3D30" height="400" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.val.town/v/karfau.githubWebhookApproveDependencyPRs" rel="noopener noreferrer" class="c-link"&gt;
          githubWebhookApproveDependencyPRs | @karfau | Val Town
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          A webhook to approve dependency PRs created by bots The webhook can be configured on the repo or on the org level it needs to receive the  workflow_runs  events it needs to have the  webhookSecret  configured (line 7) it needs to send json payload It will only approve if all of the following conditions are met: the event  action  is  completed  and the  workflow_run.conclusion  has to be  success the event is related to exactly one pull request authored by one of the users listed in  allowedAuthors  (line 5) the  githubApiToken  configured in line 9 needs to have  repo  access to the related repository a branch protection has to be configured that requires a review and that requires at least one status check the current value for  dryRun  is  false  (line 3) If it approves the PR, it leaves a comment pointing to the website of this val.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--zNJXgiBg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.val.town/favicon.ico" width="64" height="64"&gt;
        val.town
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Turns out, it wasn't that difficult, even though I was new to the platform.&lt;/p&gt;

&lt;p&gt;And I received some quick and helpful support on Discord when I was stuck. Thx for that.&lt;/p&gt;

&lt;p&gt;And the best thing about it is, that you can fork it an use it on your own.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>github</category>
      <category>typescript</category>
      <category>valtown</category>
    </item>
    <item>
      <title>I published my first deno package</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Thu, 06 Jan 2022 08:03:21 +0000</pubDate>
      <link>https://dev.to/karfau/i-published-my-first-deno-package-4720</link>
      <guid>https://dev.to/karfau/i-published-my-first-deno-package-4720</guid>
      <description>&lt;p&gt;&lt;a title="Cmglee, CC BY-SA 3.0 &amp;lt;https://creativecommons.org/licenses/by-sa/3.0&amp;gt;, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Comparison_Pythagorean_means.svg" rel="noopener noreferrer"&gt;Cover Image by Cmglee - Own work, CC BY-SA 3.0&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What was it like to do that?
&lt;/h2&gt;

&lt;p&gt;It was so much fun compared to all previous experiences of publishing a (typescript or javascript) package.&lt;/p&gt;

&lt;p&gt;What made it really easy for me to get up to speed with deno:&lt;/p&gt;

&lt;p&gt;Of course the experience to "&lt;a href="https://deno.land/manual/typescript" rel="noopener noreferrer"&gt;just execute typescript&lt;/a&gt;" without having to first research the "currently best way to transpile the code in this use case", is just mind blowing again and again.&lt;/p&gt;

&lt;p&gt;Instead of picking from tons of tools, I was regularly visiting the &lt;a href="https://deno.land/manual" rel="noopener noreferrer"&gt;deno manual&lt;/a&gt;.&lt;br&gt;
Even when I didn't expect something to be provided out of the box, regular searching pointed me to it.&lt;/p&gt;

&lt;p&gt;Deno comes with a &lt;a href="https://deno.land/manual/testing" rel="noopener noreferrer"&gt;test runner&lt;/a&gt; and provides &lt;a href="https://deno.land/manual/testing/assertions" rel="noopener noreferrer"&gt;basic assertions&lt;/a&gt; that can also take care of collecting &lt;a href="https://deno.land/manual/testing/coverage" rel="noopener noreferrer"&gt;coverage&lt;/a&gt; data.&lt;br&gt;
It also comes with a &lt;a href="https://deno.land/manual/tools/linter" rel="noopener noreferrer"&gt;linter&lt;/a&gt; and a (code and docs and code in docs) &lt;a href="https://deno.land/manual/tools/formatter" rel="noopener noreferrer"&gt;formatter&lt;/a&gt; and &lt;a href="https://deno.land/manual/tools" rel="noopener noreferrer"&gt;there is more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But the most fun part was publish the package:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I claimed the library name. (I didn't need to create an account for that!)&lt;/li&gt;
&lt;li&gt;I followed the instructions to add webhook to my github repository&lt;/li&gt;
&lt;li&gt;I created a release on GitHub. This is the step that needs to be repeated to publish a new version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Did you know that the versions on &lt;a href="https://deno.land/x" rel="noopener noreferrer"&gt;https://deno.land/x&lt;/a&gt; are immutable and can not be dropped?)&lt;/p&gt;
&lt;h2&gt;
  
  
  So what package and why?
&lt;/h2&gt;

&lt;p&gt;Thx for asking ;)&lt;/p&gt;

&lt;p&gt;I recently analysed npm packages that are still using an insecure version of another library I'm maintaining, to judge if it makes sense to provide an upgrade PR. Since there are over 2000 dependents on all older versions, and at that point in time over 60 on the versions I care about, I needed to prioritize the packages. So I can first provide update the PRs that have a reasonable impact on reducing the usage and have a good chance of being merged.&lt;/p&gt;

&lt;p&gt;I still have that idea "Maybe I just didn't use the correct search terms?", because I couldn't find any existing/similar library. If you know about something comparable please let me know.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/karfau" rel="noopener noreferrer"&gt;
        karfau
      &lt;/a&gt; / &lt;a href="https://github.com/karfau/scor" rel="noopener noreferrer"&gt;
        scor
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Calculate scores for numeric values or items, and get the "total score" (aka "arithmetic mean" or "weighted arithmetic mean") from multiple scores.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://deno.land/x/scor" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fffe8fc18903584a12d07236feee3051307329b1d86a3beefbe900c425b73098/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f6b61726661752f73636f723f6c6162656c3d64656e6f2e6c616e642f782f73636f7226736f72743d73656d766572" alt="latest version of scor package on deno.land"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;scor&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Calculate scores for numeric values or items, and get the "total score" (aka
&lt;a href="https://en.wikipedia.org/wiki/Arithmetic_mean" rel="nofollow noopener noreferrer"&gt;arithmetic mean&lt;/a&gt; or
&lt;a href="https://en.wikipedia.org/wiki/Weighted_arithmetic_mean" rel="nofollow noopener noreferrer"&gt;weighted arithmetic mean&lt;/a&gt;)
from multiple scores.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Imagine you&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a long list of items to work on, and you want to prioritize them&lt;/li&gt;
&lt;li&gt;want to show the most relevant items to a user before showing more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, let's look at npm packages. Possible criteria are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;number of maintainers&lt;/li&gt;
&lt;li&gt;number of dependencies (direct/transient)&lt;/li&gt;
&lt;li&gt;time since last published version&lt;/li&gt;
&lt;li&gt;version (major &amp;lt; 1?) / dist-tags&lt;/li&gt;
&lt;li&gt;weekly downloads&lt;/li&gt;
&lt;li&gt;source code repo attributes (e.g. GitHub stars/forks)&lt;/li&gt;
&lt;li&gt;quality?&lt;/li&gt;
&lt;li&gt;...?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The different relevant values come in very different "shapes". Once all the data
is gathered per package, depending on the use case the different values are more
or less relevant.&lt;/p&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-s1"&gt;createToMean&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-s1"&gt;distributeWeights&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-s1"&gt;scorForItems&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"https://deno.land/x/scor/scor.ts"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;getPackagesData&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"./npm.ts"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;packages&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-en"&gt;getPackagesData&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/karfau/scor" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It was developed using TDD, so the coverage is 100%.&lt;/p&gt;

&lt;p&gt;To use it in your deno code you can import it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;scor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/x/scor@v1.0.0/scor.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to use the latest version:&lt;br&gt;
&lt;a href="https://deno.land/x/scor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fgithub%2Fv%2Ftag%2Fkarfau%2Fscor%3Flabel%3Dscor%26sort%3Dsemver" alt="latest version of scor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm quite happy about the existing documentation (the readme and doc comments), so I won't repeat it here.&lt;/p&gt;

&lt;p&gt;I'm really curious to see if it's understandable, so please let me know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What' the name about?
&lt;/h2&gt;

&lt;p&gt;Well, I checked for suitable names that are still available as an (unscoped) npm package.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, are you going to publish it to npm?
&lt;/h2&gt;

&lt;p&gt;Maybe, it's currently the last thing on my short list of &lt;a href="https://github.com/karfau/scor#todos" rel="noopener noreferrer"&gt;todos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First I want to collect some feedback, to see if it's worth the additional effort. If you think it is, feel free to create PR.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>deno</category>
      <category>math</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Automating some annoying clicks</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Wed, 30 Sep 2020 06:44:14 +0000</pubDate>
      <link>https://dev.to/karfau/automating-some-annoying-clicks-4f4h</link>
      <guid>https://dev.to/karfau/automating-some-annoying-clicks-4f4h</guid>
      <description>&lt;p&gt;I just automated away something that annoyed me:&lt;/p&gt;

&lt;p&gt;Whenever I'm in some foreign WIFI (e.g. in the train) I need to find the right URL to open in the browser to confirm some dialog or login before having access to the internet.&lt;/p&gt;

&lt;p&gt;I recently found out that I can just enter the IP-address of the primary DNS server from my network information into the browser as the most reliable way.&lt;/p&gt;

&lt;p&gt;But that's still to many clicks for doing it multiple times a day (e.g. when switching between trains), so I composed a few bash commands to do that for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xdg-open "http://$(grep "nameserver" /etc/resolv.conf | tr  -d "nammeserver ")" &amp;gt; /dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what's happening here from inside out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ grep "nameserver" /etc/resolv.conf
nameserver 192.168.8.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;delivers the current primary DNS,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... | tr -d "nameserver "
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;drops the first word and space from the previos command so that only the IP address is left,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"http://$(...)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;prefixes the output from above commands (executed in a sub-shell) to make it a URL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xdg-open "..." &amp;gt; /dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;opens the default browser (because the string is a URL), &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;gt; /dev/null&lt;/code&gt;: without writing some message like "Opening in existing browser session." to the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;&lt;/code&gt;: in the background (without blocking the shell)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I added the whole thing to a new &lt;code&gt;wifi&lt;/code&gt; alias in my &lt;code&gt;~/.extend.bashrc&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;alias wifi='xdg-open "http://$(grep "nameserver" /etc/resolv.conf | tr  -d "nammeserver ")" &amp;gt; /dev/null &amp;amp;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so it's always on my fingertips :) &lt;/p&gt;

&lt;p&gt;PS: It's not working everywhere (e.g. not in the German ICE trains, thanks Deutsche Bahn) &lt;br&gt;
and the next hit of &lt;code&gt;Ctrl+C&lt;/code&gt; adds the output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[n]   Done     ...the command...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I'm very open for suggestion of how to improve it.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>learning</category>
      <category>automation</category>
    </item>
    <item>
      <title>Gute Gewohnheiten für sichere Internet-Nutzung</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Mon, 30 Dec 2019 02:06:39 +0000</pubDate>
      <link>https://dev.to/karfau/gute-gewohnheiten-fur-sichere-internet-nutzung-3f6l</link>
      <guid>https://dev.to/karfau/gute-gewohnheiten-fur-sichere-internet-nutzung-3f6l</guid>
      <description>&lt;p&gt;&lt;em&gt;Dies ist eine Übersetzung von &lt;a href="https://dev.to/victoria/healthy-habits-for-good-cybersecurity-dil"&gt;Healthy habits for cyber security (EN)&lt;/a&gt;, die Links die im Englischen Artikel existieren, im Artikel verweisen auf die gleichen (Englisch sprachigen) Webseiten wie im übersetzten Artikel und enden mit &lt;a href=""&gt;(EN)&lt;/a&gt;. Links die ich zur Erläuterung hinzugefügt habe enden mit &lt;a href=""&gt;(DE)&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So wie in dieser Jahreszeit sich (wieder) eine Erkältung holen, ist das Risiko einem technischem Angriff zu "erliegen" ständig präsent.&lt;br&gt;
Sowohl eine ausgeklügelter Angriff auf der Grundlage sozialer Netzwerke als auch eine Phishing-Mail ohne Grammatik können echte Schäden anrichten.&lt;br&gt;
Niemand der über das Internet kommuniziert ist immun.&lt;/p&gt;

&lt;p&gt;So wie gründliches Händewaschen oder Impfungen können Gewohnheiten das Risiko verringern unabsichtlich einen Angriff weiter zu verteilen.&lt;br&gt;
Da das neue Jahr oft zu neuen Gewohnheiten inspiriert, schlage ich hier ein paar vor, die dabei helfen können, Dich und die Menschen um Dich herum zu schützen.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Frag nach
&lt;/h2&gt;

&lt;p&gt;Es wird immer schwieriger einen Angriff an der Art der Nachricht zu erkennen.&lt;br&gt;
Nachrichten mit gefährlichen Links kommen nicht immer von Fremden. Manchmal sehen sie aus wie alltägliche Kommunikation oder sehen danach aus als ob sie von jemandem sind den man kennt oder mit dem man arbeitet.&lt;br&gt;
Angreifer nutzen subtile aber tief verwurzelte &lt;a href="https://de.wikipedia.org/wiki/Kognitive_Verzerrung"&gt;kognitive Verzerrungen (DE)&lt;/a&gt; die es oft ermöglichen den gesunden Menschenverstand zu „überspringen“. So das der natürliche Impuls ist zu klicken.&lt;/p&gt;

&lt;p&gt;Zum Glück gibt es eine einfache Gewohnheit um diese Art von Attaken zu verhindern: Vor dem Klick nachfragen.&lt;/p&gt;

&lt;p&gt;Vielleicht bekommst Du eine Mail von einem Freund der dringend Hilfe braucht oder von Deinem Chef der gerade in ein Flugzeug steigt. &lt;br&gt;
Es könnte so verlockend oder mysteriös sein wie eine direkte Nachricht von einem Bekannten der einen Link schickt und fragt „😂 Bist Du das?“&lt;/p&gt;

&lt;p&gt;Man muss geistesgegenwärtig sein um die Reaktion zu verhindern auf die diese Angriffe lauern, aber die Abwehr ist schnell und unkompliziert. Schicke eine Textnachricht, rufe kurz and oder geh den Gang runter und frage „Hast Du mir das geschickt?“&lt;/p&gt;

&lt;p&gt;Wenn die Nachricht echt ist, tun ein paar mehr Minuten für die Frage nicht weh. Wenn sie nicht echt ist, hast Du die Person von der es ausging sofort darüber informiert, das sie kompromittiert wurde. Und das kann sehr dazu betragen solch einen Angriff aufzuhalten.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Nutze Ende-zu-Ende verschlüsselte Nachrichten und ermutige andere dazu
&lt;/h2&gt;

&lt;p&gt;Auf die selbe Art wie Impfungen das Risiko verringert, selbst zur Ansteckungsgefahr zu werden, sind sowohl Du als auch Menschen die Du kennst sicherer wenn Du verschlüsselte Kommunikation verwendest.&lt;br&gt;
Ermutige Deine Freunde, Kollegen und Tante Matilda zu einer App wie Signal zu wechseln. Dadurch trägst Du dazu bei, dass weniger Menschen Nachriten Dienste nutzen die leicht angreifbar sind.&lt;/p&gt;

&lt;p&gt;Das bedeutet nicht, das Du aufhören musst angreifbare Dienste zu nutzen. Stattdessen betrachte es als eine Hierarchie. Nutze Signal für wichtige Nachrichten, denen man vertrauen muss, wie Bitten um Geld oder Absprachen zu einer Reise.&lt;br&gt;
Benutze alle andere Kanäle, wie SMS oder soziale Netzwerke, nur für „unwichtige“ Kommunikation.&lt;br&gt;
Wenn jetzt Bitten oder Links die wichtig zu sein scheinen, über „unwichtige“ Kanäle ankommen, wirst Du wahrscheinlich eher vorsichtig sein.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Stecke keine „dreckigen“ USB-Stecker in deinen ***
&lt;/h2&gt;

&lt;p&gt;Du würdest Deine Zähne ja auch nicht mit einer Zahnbürste putzen die Du in einer Gasse gefunden hast. Warum also würdest Du also eine USB-Gerät anstecken, von dem Du nicht weisst wo es war?!&lt;br&gt;
Wir können zwar noch sagen das die menschliche Neugierde clever ausgenutzt wurde, wenn &lt;a href="https://en.wikipedia.org/wiki/2008_cyberattack_on_United_States"&gt;jemand einen gefundenen USB Stick in seinen Computer steckt (EN)&lt;/a&gt;.&lt;br&gt;
Aber wir würden wohl kaum eine &lt;a href="https://www.howtogeek.com/444267/how-safe-are-public-charging-stations"&gt;öffentliche Telefon-Ladestation (EN)&lt;/a&gt; oder ein selbst gekauftes &lt;a href="https://www.theverge.com/2019/8/15/20807854/apple-mac-lightning-cable-hack-mike-grover-mg-omg-cables-defcon-cybersecurity"&gt;USB-Kabel (EN)&lt;/a&gt; verdächtigen.&lt;br&gt;
Sogar scheinbar harmlose USB &lt;a href="https://www.cbsnews.com/news/why-your-usb-device-is-a-security-risk"&gt;Eingabegeräte (EN)&lt;/a&gt; oder &lt;a href="https://www.us-cert.gov/ncas/current-activity/2010/03/08/Energizer-DUO-USB-Battery-Charger-Software-Allows-Remote-System"&gt;wiederaufladbare (EN)&lt;/a&gt; Geräte können ein Risiko darstellen.&lt;/p&gt;

&lt;p&gt;Anders als bei Mails und einigen Diensten zum Versenden von großen Dateien, bei denen die Dateien gescannt und gefiltert werden, bevor sie Deinen Computer erreichen, bedeutet das Einstecken per USB eine direkte und &lt;a href="https://www.wired.com/2014/07/usb-security/"&gt;ungeschützte (EN)&lt;/a&gt; Verbindung.&lt;br&gt;
Sobald diese Verbindung besteht, braucht der Nutzer nichts mehr zu tun, damit eine ganze Menge schlechter Dinge passieren kann. Es ist für Angreifer sehr einfach auf diesem Weg &lt;a href="https://de.wikipedia.org/wiki/Schadprogramm"&gt;Schadsoftware (DE)&lt;/a&gt; oder &lt;a href="https://de.wikipedia.org/wiki/Ransomware"&gt;Ransomware (DE)&lt;/a&gt; auf einem Rechner oder Mobil-Telefon zu installieren.&lt;/p&gt;

&lt;p&gt;Natürlich muss auch nicht auf den Komfort von USB verzichtet werden. Statt mit fragwürdigem Verhalten gegenüber USB Geräten zu beginnen, spare einfach nicht beiKauf von USB Geräten und Kabeln. &lt;br&gt;
Wenn es in Deinen Computer gesteckt werden soll, stelle sicher das Du extra aufmerksam bist.&lt;br&gt;
Kauf es direkt von einem Hersteller (wie den Apple Store) oder Verkäufer die Ihre Lieferkette überwachen.&lt;br&gt;
Stecke wiederaufladbare Geräte nicht an Deinen Rechner. Nutze stattdessen einen &lt;a href="https://heronebag.com/blog/40-hours-drive-time-my-road-trip-charging-essentials/"&gt;Stecker mit USB Anschlüssen (EN)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Praktiziere gute Sicherheits-Gewohnheiten
&lt;/h2&gt;

&lt;p&gt;Deine Geräte gesund und munter zu halten ist eine Frage von guten Gewohnheiten. So wie sich gegen eine Grippe zu schützen, können gute Gewohnheiten Dich und die um Dich herum schützen.&lt;br&gt;
Mach solche gewissenhaften Gewohnheiten zum Teil Deiner Vorhaben für das neue Jahr - oder fange einfach gleich damit an.&lt;/p&gt;

&lt;p&gt;Ich wünsche euch angenehme und sichere Feiertage.&lt;/p&gt;

</description>
      <category>security</category>
      <category>deutsch</category>
    </item>
    <item>
      <title>My first published npm package is called runex</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Tue, 24 Dec 2019 14:39:07 +0000</pubDate>
      <link>https://dev.to/karfau/my-first-published-npm-package-is-called-runex-3ca9</link>
      <guid>https://dev.to/karfau/my-first-published-npm-package-is-called-runex-3ca9</guid>
      <description>&lt;p&gt;Some months ago I got tired of all those tiny differences that you need to consider when writing CLI scripts for node.&lt;/p&gt;

&lt;p&gt;So in the last days I took the time to rewrite a module that I have already copied into more than three repositories:&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/karfau"&gt;
        karfau
      &lt;/a&gt; / &lt;a href="https://github.com/karfau/runex"&gt;
        runex
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Run (javascript) module export as a script
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/runex" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/6731450a9ddb19926fd25e5ac5dc10ca7c7cb442929d3175a413120704de8843/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f72756e6578" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://david-dm.org/karfau/runex" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/e1b4af830fb2754d82f8ee09e5a2d5465c29834afc83a7d8f604d8d2a0d47b1f/68747470733a2f2f64617669642d646d2e6f72672f6b61726661752f72756e65782e737667" alt="dependencies status"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/karfau/runex" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/8f86bddd7e060e8425e3e733f0f4c8e1d5dafe20a000d2cf6806c5a56fb997c7/68747470733a2f2f636f6465636f762e696f2f67682f6b61726661752f72756e65782f6272616e63682f6d61737465722f67726170682f62616467652e737667" alt="codecov - tap --100 is part of CI"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
runex&lt;/h1&gt;
&lt;p&gt;Run module export as a &lt;code&gt;node&lt;/code&gt; or &lt;code&gt;npx&lt;/code&gt; script.&lt;/p&gt;
&lt;p&gt;(See &lt;a href="https://github.com/karfau/runex#why-not-"&gt;Why not ...&lt;/a&gt; for alternative approaches.)&lt;/p&gt;
&lt;h2&gt;
When to use&lt;/h2&gt;
&lt;p&gt;So you have some code that you want to be able to run from the command line
You can of course just write it down into a file and run it with &lt;code&gt;node ./script.js&lt;/code&gt;
Maybe you go one more step and add a &lt;a href="https://en.wikipedia.org/wiki/Hashbang" rel="nofollow"&gt;hashbang&lt;/a&gt; and make it executable
so on a linux shell you run it with just &lt;code&gt;./script.js&lt;/code&gt;.
But this way you can not import the file without executing all the code.
Wrapping all the code into a function and executing it &lt;code&gt;if (require.main === module)&lt;/code&gt; helps with that.
You also manage to parse those arguments you need, maybe using one of the available libraries.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are you able to also call your function from code with those arguments?&lt;/li&gt;
&lt;li&gt;Do you need to make any async call (like…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/karfau/runex"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The first version has already been published to npm:&lt;br&gt;
&lt;a href="https://npmjs.org/package/runex"&gt;https://npmjs.org/package/runex&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So if your module exports a method named &lt;code&gt;run&lt;/code&gt; it can now be used as a CLI tool:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx runex path/to/file.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I still have some ideas for features to  implement, but I'm very happy it's out there now.&lt;/p&gt;

&lt;p&gt;Merry X-Mas and Let me know what you think&lt;/p&gt;

</description>
      <category>node</category>
      <category>cli</category>
      <category>dry</category>
    </item>
    <item>
      <title>Advent github repo cleanup</title>
      <dc:creator>Christian Bewernitz</dc:creator>
      <pubDate>Sat, 07 Dec 2019 21:53:23 +0000</pubDate>
      <link>https://dev.to/karfau/advent-github-repo-cleanup-ndp</link>
      <guid>https://dev.to/karfau/advent-github-repo-cleanup-ndp</guid>
      <description>&lt;p&gt;Today I went through the list of &lt;a href="https://github.com/karfau?tab=repositories"&gt;my repositories on github&lt;/a&gt; to do some cleanup:&lt;/p&gt;

&lt;p&gt;I &lt;a href="https://help.github.com/en/github/administering-a-repository/deleting-a-repository"&gt;deleted&lt;/a&gt; forks that didn't have any (forks or) branches from me that I wanted to keep.&lt;/p&gt;

&lt;p&gt;I &lt;a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/archiving-a-github-repository"&gt;archived&lt;/a&gt; all repositories related to Actionscript/Flash.&lt;/p&gt;

&lt;p&gt;It was a bit tedious but it also feels good. &lt;/p&gt;

&lt;p&gt;The biggest surprise was when I opened the no longer existing repository &lt;a href="https://github.com/karfau/bachelor-thesis"&gt;karfau/bachelor-thesis&lt;/a&gt;, since I expected to see some latex source code but instead it showed the well known instructions for the first commit. &lt;/p&gt;

&lt;p&gt;Since it was created at least nine years ago, that might be a new record for a repo not being initialized? (Since there is no trace of it in my activities I can not prove that one.)&lt;/p&gt;

&lt;p&gt;I'm quite sure I used git when writing the thesis, but obviously I did never push that code. I wonder if I can still find a copy of it on some old hard drive or CD...&lt;/p&gt;

&lt;p&gt;Feel free to share what kind of repos you archived/deleted and what interesting things you (re)discovered while doing that.&lt;/p&gt;

</description>
      <category>github</category>
      <category>archive</category>
      <category>delete</category>
      <category>actionscript</category>
    </item>
  </channel>
</rss>
