<?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: Emre YARTAŞI</title>
    <description>The latest articles on DEV Community by Emre YARTAŞI (@yartasdev).</description>
    <link>https://dev.to/yartasdev</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%2F2029642%2F38f1ec87-59d0-4a43-a64f-bffcc9992139.jpg</url>
      <title>DEV Community: Emre YARTAŞI</title>
      <link>https://dev.to/yartasdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yartasdev"/>
    <language>en</language>
    <item>
      <title>Stop Hand-Copying Java .properties Into Your JS Stack</title>
      <dc:creator>Emre YARTAŞI</dc:creator>
      <pubDate>Sun, 03 May 2026 13:53:57 +0000</pubDate>
      <link>https://dev.to/yartasdev/stop-hand-copying-java-properties-into-your-js-stack-76m</link>
      <guid>https://dev.to/yartasdev/stop-hand-copying-java-properties-into-your-js-stack-76m</guid>
      <description>&lt;h2&gt;
  
  
  Stop Hand-Copying Java &lt;code&gt;.properties&lt;/code&gt; Into Your JS Stack
&lt;/h2&gt;

&lt;p&gt;If you have ever straddled a Java backend and a JavaScript frontend, you have probably stared at a &lt;code&gt;.properties&lt;/code&gt; file and thought: &lt;em&gt;I just need this as JSON—or as a module I can import.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You could transcribe keys by hand. You could write a one-off script that breaks on the first escaped newline. Or you could use a small tool that speaks the &lt;strong&gt;real&lt;/strong&gt; Java properties format and hands you &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;TypeScript&lt;/strong&gt;, or &lt;strong&gt;JSON&lt;/strong&gt; in a shape you control.&lt;/p&gt;

&lt;p&gt;This post introduces &lt;a href="https://www.npmjs.com/package/@yartasdev/properties-to-js" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;@yartasdev/properties-to-js&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;—a CLI and library that does exactly that, with options for nesting, flattening, key casing, and readable formatting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it in the browser:&lt;/strong&gt; &lt;a href="https://yartasdev.github.io/properties-to-js/playground" rel="noopener noreferrer"&gt;&lt;strong&gt;Playground&lt;/strong&gt;&lt;/a&gt; — paste &lt;code&gt;.properties&lt;/code&gt; text, toggle flatten / casing, and see JSON, JS, or TS output without installing anything. (If you self-host docs, use your own &lt;code&gt;/playground&lt;/code&gt; URL.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full docs:&lt;/strong&gt; &lt;a href="https://yartasdev.github.io/properties-to-js/documentation/introduction" rel="noopener noreferrer"&gt;Documentation site&lt;/a&gt; (GitHub Pages from the same repo).&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem in one sentence
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.properties&lt;/code&gt; files are a lingua franca on the JVM; modern Node and browser code usually want structured JS or JSON.&lt;/strong&gt; Bridging the two should be boring, reliable, and repeatable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a &lt;code&gt;.properties&lt;/code&gt; file, really?
&lt;/h2&gt;

&lt;p&gt;Java’s classic configuration format looks deceptively simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lines starting with &lt;code&gt;#&lt;/code&gt; or &lt;code&gt;!&lt;/code&gt; are comments.&lt;/li&gt;
&lt;li&gt;Each entry is typically &lt;code&gt;key=value&lt;/code&gt; or &lt;code&gt;key:value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Values can span lines when you end a line with &lt;code&gt;\&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Escape sequences like &lt;code&gt;\n&lt;/code&gt;, &lt;code&gt;\r&lt;/code&gt;, &lt;code&gt;\t&lt;/code&gt;, and Unicode &lt;code&gt;\uXXXX&lt;/code&gt; are part of the spec.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last part matters. “Almost parsing” properties with a few &lt;code&gt;split('=')&lt;/code&gt; lines works until it does not—until someone adds a multiline value, a colon in the right place, or an escape sequence your regex did not anticipate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;properties-to-js&lt;/code&gt;&lt;/strong&gt; is built around treating the input as a real properties document, then emitting output your stack can consume without surprises.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you get out of the box
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multiple output formats
&lt;/h3&gt;

&lt;p&gt;You choose &lt;strong&gt;&lt;code&gt;json&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;js&lt;/code&gt;&lt;/strong&gt;, or &lt;strong&gt;&lt;code&gt;ts&lt;/code&gt;&lt;/strong&gt; via the &lt;strong&gt;&lt;code&gt;--type&lt;/code&gt; / &lt;code&gt;-t&lt;/code&gt;&lt;/strong&gt; flag. The output file extension &lt;strong&gt;must match&lt;/strong&gt; that type (for example &lt;code&gt;-t js&lt;/code&gt; with &lt;code&gt;output.js&lt;/code&gt;, &lt;code&gt;-t ts&lt;/code&gt; with &lt;code&gt;output.ts&lt;/code&gt;). The default type is &lt;strong&gt;&lt;code&gt;json&lt;/code&gt;&lt;/strong&gt;, so a plain &lt;code&gt;output.json&lt;/code&gt; works without extra flags; for JavaScript or TypeScript modules, pass &lt;strong&gt;&lt;code&gt;-t js&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;-t ts&lt;/code&gt;&lt;/strong&gt; explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested structure by default
&lt;/h3&gt;

&lt;p&gt;Keys with dot segments such as &lt;code&gt;app.name&lt;/code&gt; or &lt;code&gt;database.host&lt;/code&gt; naturally become nested objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.name=MyApp
database.port=5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes a tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyApp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5432&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That mirrors how many teams &lt;em&gt;think&lt;/em&gt; about configuration: sections and fields, not a flat bag of strings—unless you explicitly want the flat bag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional flattening with a custom delimiter
&lt;/h3&gt;

&lt;p&gt;Some systems, environment-variable conventions, or legacy integrations prefer a &lt;strong&gt;single level&lt;/strong&gt; of keys. Enable flattening and pick a delimiter (for example &lt;code&gt;_&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; config.properties &lt;span class="nt"&gt;-o&lt;/span&gt; config.js &lt;span class="nt"&gt;-t&lt;/span&gt; js &lt;span class="nt"&gt;--flatted&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"_"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might get &lt;code&gt;app_name&lt;/code&gt;, &lt;code&gt;database_port&lt;/code&gt;, and so on—predictable and easy to grep or map into other tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case transformation for keys
&lt;/h3&gt;

&lt;p&gt;Need uppercase or lowercase keys for consistency with APIs, env vars, or team style? Flags like &lt;code&gt;--uppercase&lt;/code&gt; and &lt;code&gt;--lowercase&lt;/code&gt; apply to the key material so you do not have to post-process with another script.&lt;/p&gt;

&lt;h3&gt;
  
  
  CLI and programmatic API
&lt;/h3&gt;

&lt;p&gt;Use it as a &lt;strong&gt;global or npx-invoked CLI&lt;/strong&gt; (&lt;code&gt;properties-to-js&lt;/code&gt; when installed globally), or &lt;strong&gt;&lt;code&gt;import { Converter } from '@yartasdev/properties-to-js'&lt;/code&gt;&lt;/strong&gt; and call &lt;strong&gt;&lt;code&gt;Converter.convertForFile&lt;/code&gt;&lt;/strong&gt; (read a file, write a file) or &lt;strong&gt;&lt;code&gt;Converter.convertForContent&lt;/code&gt;&lt;/strong&gt; (string in, formatted string out) from your own build scripts, tests, or scaffolding tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prettier-formatted output
&lt;/h3&gt;

&lt;p&gt;Generated files are run through &lt;strong&gt;Prettier&lt;/strong&gt; so diffs stay readable and your repository does not fill with accidental formatting noise every time someone regenerates config.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation and first run
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Global install&lt;/strong&gt; (gives you the &lt;code&gt;properties-to-js&lt;/code&gt; command):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @yartasdev/properties-to-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Project dependency&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @yartasdev/properties-to-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No install&lt;/strong&gt;, one-off run (note the scoped package name for &lt;code&gt;npx&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @yartasdev/properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; input.properties &lt;span class="nt"&gt;-o&lt;/span&gt; output.js &lt;span class="nt"&gt;-t&lt;/span&gt; js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your shell mangles flags after &lt;code&gt;npx&lt;/code&gt;, this pattern is your friend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @yartasdev/properties-to-js &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; input.properties &lt;span class="nt"&gt;-o&lt;/span&gt; output.js &lt;span class="nt"&gt;-t&lt;/span&gt; js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the package is installed locally in a project, you can also run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; input.properties &lt;span class="nt"&gt;-o&lt;/span&gt; output.js &lt;span class="nt"&gt;-t&lt;/span&gt; js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JSON only&lt;/strong&gt; (default type is &lt;code&gt;json&lt;/code&gt;, matches &lt;code&gt;.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @yartasdev/properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; input.properties &lt;span class="nt"&gt;-o&lt;/span&gt; output.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A concrete walkthrough
&lt;/h2&gt;

&lt;p&gt;Imagine &lt;code&gt;config.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Application Configuration
&lt;/span&gt;&lt;span class="py"&gt;app.name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;MyApp&lt;/span&gt;
&lt;span class="py"&gt;app.version&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="py"&gt;app.debug&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# Database Settings
&lt;/span&gt;&lt;span class="py"&gt;database.host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;database.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5432&lt;/span&gt;
&lt;span class="py"&gt;database.name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mydb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Default (nested)&lt;/strong&gt; output is easy to read and maps cleanly to nested types in TypeScript if you emit &lt;code&gt;.ts&lt;/code&gt; or wrap the object in your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; config.properties &lt;span class="nt"&gt;-o&lt;/span&gt; config.json
&lt;span class="c"&gt;# or&lt;/span&gt;
properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; config.properties &lt;span class="nt"&gt;-o&lt;/span&gt; config.ts &lt;span class="nt"&gt;-t&lt;/span&gt; ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flattened&lt;/strong&gt; with &lt;code&gt;_&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; config.properties &lt;span class="nt"&gt;-o&lt;/span&gt; config.js &lt;span class="nt"&gt;-t&lt;/span&gt; js &lt;span class="nt"&gt;--flatted&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"_"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get one object with keys like &lt;code&gt;app_name&lt;/code&gt;, &lt;code&gt;database_host&lt;/code&gt;—useful when you must not assume nesting in downstream code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uppercase&lt;/strong&gt; nested keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;properties-to-js &lt;span class="nt"&gt;-i&lt;/span&gt; config.properties &lt;span class="nt"&gt;-o&lt;/span&gt; config.js &lt;span class="nt"&gt;-t&lt;/span&gt; js &lt;span class="nt"&gt;--uppercase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sections become &lt;code&gt;APP&lt;/code&gt;, &lt;code&gt;DATABASE&lt;/code&gt;, and so on—handy when your style guide or integration expects shouting keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  Programmatic usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  File → file
&lt;/h3&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;Converter&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="s1"&gt;@yartasdev/properties-to-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Converter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convertForFile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.properties&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;flatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lowercase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paths are resolved under &lt;code&gt;process.cwd()&lt;/code&gt;. Use &lt;code&gt;type: 'json' | 'js' | 'ts'&lt;/code&gt; and an &lt;code&gt;output&lt;/code&gt; path whose extension matches.&lt;/p&gt;

&lt;h3&gt;
  
  
  String → string (no filesystem)
&lt;/h3&gt;

&lt;p&gt;Ideal for HTTP bodies, tests, or generated snippets:&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;Converter&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="s1"&gt;@yartasdev/properties-to-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.name=Demo&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;app.port=3000&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Converter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convertForContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;flatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lowercase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// moduleText is a Prettier-formatted string (e.g. export default { ... };)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CLI reference (quick)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Short&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--input&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Path to the &lt;code&gt;.properties&lt;/code&gt; file&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--output&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output path (extension must match &lt;code&gt;--type&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;json&lt;/code&gt;, &lt;code&gt;js&lt;/code&gt;, or &lt;code&gt;ts&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--delimiter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delimiter used when keys are flattened&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--flatted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Flatten nested keys to a single level&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--uppercase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uppercase keys&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--lowercase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lowercase keys&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  When this tool shines
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backend and frontend share a source of truth.&lt;/strong&gt; The JVM side keeps canonical &lt;code&gt;.properties&lt;/code&gt;; your Vite, Next, or Node service generates checked-in or CI-built JS/JSON from the same file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You are documenting or prototyping.&lt;/strong&gt; Turn a small sample properties file into JSON for an OpenAPI example, a Storybook mock, or a README snippet without manual transcription errors. The &lt;a href="https://yartasdev.github.io/properties-to-js/playground" rel="noopener noreferrer"&gt;&lt;strong&gt;Playground&lt;/strong&gt;&lt;/a&gt; is perfect for quick experiments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You want CI to own regeneration.&lt;/strong&gt; A single command in GitHub Actions (or any runner) refreshes artifacts before tests or deploys—no “forgot to update the JSON” drift.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You value boring correctness.&lt;/strong&gt; Comments, escapes, and multiline rules exist for a reason; a dedicated converter is less exciting than a bespoke five-line parser—and that is the point.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Honest scope
&lt;/h2&gt;

&lt;p&gt;This tool solves &lt;strong&gt;properties → JS/TS/JSON&lt;/strong&gt; with sensible structural options. It is not a full configuration platform: it does not merge profiles, resolve Spring placeholders, or replace your secrets manager. If your properties layer does heavy macro expansion, you may still need a JVM-side step—or a documented subset of keys—for the JS output to match production exactly.&lt;/p&gt;

&lt;p&gt;Where it fits is the &lt;strong&gt;straightforward&lt;/strong&gt; path: standard files, clear keys, predictable output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it and shape it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Package:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@yartasdev/properties-to-js" rel="noopener noreferrer"&gt;&lt;code&gt;@yartasdev/properties-to-js&lt;/code&gt; on npm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source and issues:&lt;/strong&gt; &lt;a href="https://github.com/yartasdev/properties-to-js" rel="noopener noreferrer"&gt;github.com/yartasdev/properties-to-js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playground:&lt;/strong&gt; &lt;a href="https://yartasdev.github.io/properties-to-js/playground" rel="noopener noreferrer"&gt;yartasdev.github.io/properties-to-js/playground&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://yartasdev.github.io/properties-to-js/" rel="noopener noreferrer"&gt;yartasdev.github.io/properties-to-js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you hit an edge case—a surprising escape, a Unicode edge, a key pattern you need supported—open an issue with a minimal &lt;code&gt;.properties&lt;/code&gt; sample. Real files beat abstract specs every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;@yartasdev/properties-to-js&lt;/code&gt;&lt;/strong&gt; exists so you spend less time being a human clipboard between JVM config and JS-friendly data. One CLI command (or one &lt;code&gt;await Converter.convertForFile(...)&lt;/code&gt; / &lt;code&gt;convertForContent(...)&lt;/code&gt;) gives you nested or flat structures, optional casing, and Prettier-clean output—so you can focus on the application, not on re-parsing &lt;code&gt;=&lt;/code&gt; for the hundredth time.&lt;/p&gt;

&lt;p&gt;If this sounds useful for your stack, install it, run it on a properties file you already have, or open the &lt;a href="https://yartasdev.github.io/properties-to-js/playground" rel="noopener noreferrer"&gt;&lt;strong&gt;Playground&lt;/strong&gt;&lt;/a&gt; with a paste from production (sanitized). If the generated module drops straight into your project, that is the whole story—and a good reason to star the repo or leave a note on dev.to about how you wired it in.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>cli</category>
      <category>java</category>
    </item>
    <item>
      <title>Cobertura Coverage Reports for CI/CD Pipelines: @yartasdev/cobertura-collect</title>
      <dc:creator>Emre YARTAŞI</dc:creator>
      <pubDate>Thu, 05 Sep 2024 15:01:50 +0000</pubDate>
      <link>https://dev.to/yartasdev/cobertura-coverage-reports-for-cicd-pipelines-yartasdevcobertura-collect-3h59</link>
      <guid>https://dev.to/yartasdev/cobertura-coverage-reports-for-cicd-pipelines-yartasdevcobertura-collect-3h59</guid>
      <description>&lt;p&gt;In CI/CD processes, test coverage is critical for measuring the quality of our software projects. However, in large projects where tests run in parallel across different modules or even on different machines, multiple Cobertura coverage files may be generated. In such cases, correctly collecting and merging these coverage reports into a single report becomes essential. This is where &lt;a href="https://www.npmjs.com/package/@yartasdev/cobertura-collect" rel="noopener noreferrer"&gt;@yartasdev/cobertura-collect&lt;/a&gt; comes into play!&lt;/p&gt;

&lt;p&gt;In this post, we'll explore how this npm package can be used in your CI/CD processes and how it merges multiple Cobertura reports into one file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Cobertura?
&lt;/h2&gt;

&lt;p&gt;Cobertura is a popular tool used to measure test coverage in software projects. Although it's commonly used for a lot of projects, it can be integrated with various programming languages and platforms. With Cobertura, you can see how much of your code is covered by each test, allowing you to analyze whether your tests sufficiently control your code. After the testing process, the overall test coverage results are stored in a file called cobertura-coverage.xml.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of Merging Cobertura Coverage Files
&lt;/h2&gt;

&lt;p&gt;In CI/CD pipelines, especially in microservice architectures or monorepo projects, tests are often run in parallel. This results in each test group generating its own independent coverage file. When you have multiple Cobertura coverage files, merging them manually into a comprehensive report is time-consuming and error-prone.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://www.npmjs.com/package/@yartasdev/cobertura-collect" rel="noopener noreferrer"&gt;@yartasdev/cobertura-collect&lt;/a&gt; comes in, merging all the Cobertura coverage files into one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;a class="mentioned-user" href="https://dev.to/yartasdev"&gt;@yartasdev&lt;/a&gt;/cobertura-collect?
&lt;/h2&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/yartasdev"&gt;@yartasdev&lt;/a&gt;/cobertura-collect is an npm package that collects all Cobertura coverage files generated after running unit tests in a CI/CD pipeline and merges them into a single cobertura-coverage.xml file. This way, you can easily merge coverage reports from multiple modules into one file and present this combined report to CI/CD tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The package’s primary goals are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To locate multiple cobertura-coverage.xml files.&lt;/li&gt;
&lt;li&gt;To merge these files into one comprehensive coverage report.&lt;/li&gt;
&lt;li&gt;To provide this merged report to CI/CD tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Does the Package Work?&lt;/strong&gt;&lt;br&gt;
The package scans a specific directory or directories for Cobertura reports and merges them into a single file. For example, after running parallel test processes, you can use this package to merge all the cobertura-coverage.xml files into one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install the Package or use without Install&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @yartasdev/cobertura-collect -g&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and run command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@yartasdev/cobertura-collect --print -o coverage/cobertura.xml -t coverage/**/cobertura-coverage.xml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or without install&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx @yartasdev/cobertura-collect --print -o coverage/cobertura.xml -t coverage/**/cobertura-coverage.xml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example CI/CD Configuration&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;Unit-Test:
  stage: test
  image: node:${NODE_LTS}-alpine
  artifacts:
    when: always
    paths:
      - coverage/
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura.xml
  coverage: /Total Line Coverage:\s*(\d+(?:\.\d+)?)/
  before_script:
    - npm ci --cache .npm --prefer-offline --silent
  script:
    - npx nx run-many --target=test --configuration=ci --with-deps=false --projects=${PROJECTS} --parallel=6 --skip-nx-cache=false --verbose
  after_script:
    - npx @yartasdev/cobertura-collect --print -o coverage/cobertura.xml -t coverage/**/cobertura-coverage.xml
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>test</category>
      <category>cobertura</category>
      <category>coverage</category>
      <category>ci</category>
    </item>
  </channel>
</rss>
