Skip to content

Commit e376a57

Browse files
committed
Add Spring Boot properties to YAML converter
1 parent 670f735 commit e376a57

File tree

6 files changed

+168
-0
lines changed

6 files changed

+168
-0
lines changed

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { tool as base64FileConverter } from './base64-file-converter';
22
import { tool as base64StringConverter } from './base64-string-converter';
33
import { tool as basicAuthGenerator } from './basic-auth-generator';
4+
import { tool as propertiesToYaml } from './properties-to-yaml';
45
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
56
import { tool as numeronymGenerator } from './numeronym-generator';
67
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -100,6 +101,7 @@ export const toolsByCategory: ToolCategory[] = [
100101
listConverter,
101102
tomlToJson,
102103
tomlToYaml,
104+
propertiesToYaml,
103105
],
104106
},
105107
{

src/tools/properties-to-yaml/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { AlignJustified } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Properties to YAML',
6+
path: '/properties-to-yaml',
7+
description: '',
8+
keywords: ['properties', 'yaml', 'convert', 'spring', 'spring-boot', 'parse'],
9+
component: () => import('./properties-to-yaml.vue'),
10+
icon: AlignJustified,
11+
createdAt: new Date('2023-12-24'),
12+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test.describe('Tool - Properties to YAML', () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto('/properties-to-yaml');
6+
});
7+
8+
test('Has correct title', async ({ page }) => {
9+
await expect(page).toHaveTitle('Properties to YAML - IT Tools');
10+
});
11+
12+
test('', async ({ page }) => {
13+
await page.getByTestId('input').fill(`
14+
spring.mvc.async.request-timeout=-1
15+
spring.output.ansi.enabled=NEVER
16+
spring.config.import=optional:file:.env[.properties]
17+
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
18+
spring.datasource.url=\${DATABASE_URI}
19+
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
20+
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
21+
spring.jpa.open-in-view=false
22+
management.endpoints.web.base-path=/internal
23+
management.endpoints.web.exposure.include[0]=health
24+
management.endpoints.web.exposure.include[1]=info
25+
management.endpoint.info.enabled=true
26+
management.endpoint.health=
27+
`.trim());
28+
29+
const generatedJson = await page.getByTestId('area-content').innerText();
30+
31+
expect(generatedJson.trim()).toEqual(`
32+
spring:
33+
mvc:
34+
async:
35+
request-timeout: "-1"
36+
output:
37+
ansi:
38+
enabled: NEVER
39+
config:
40+
import: optional:file:.env[.properties]
41+
datasource:
42+
driverClassName: com.mysql.cj.jdbc.Driver
43+
url: \${DATABASE_URI}
44+
jpa:
45+
hibernate:
46+
naming:
47+
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
48+
database-platform: org.hibernate.dialect.MySQLDialect
49+
open-in-view: "false"
50+
management:
51+
endpoints:
52+
web:
53+
base-path: /internal
54+
exposure:
55+
include:
56+
- health
57+
- info
58+
endpoint:
59+
info:
60+
enabled: "true"
61+
health: ""
62+
`.trim(),
63+
);
64+
});
65+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { isValidProperties } from './properties-to-yaml.service';
3+
4+
describe('isValidProperties', () => {
5+
it('should return true for valid properties', () => {
6+
const properties = 'key1=value1\nkey2=value2';
7+
expect(isValidProperties(properties)).toBe(true);
8+
});
9+
10+
it('should return false for properties with duplicate keys', () => {
11+
const properties = 'key1=value1\nkey1=value2';
12+
expect(isValidProperties(properties)).toBe(false);
13+
});
14+
15+
it('should return false for properties with incorrect format', () => {
16+
const properties = 'key1\nkey2=value2';
17+
expect(isValidProperties(properties)).toBe(false);
18+
});
19+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import _ from 'lodash';
2+
3+
export { isValidProperties, parseProperties };
4+
5+
function isValidProperties(properties: string): boolean {
6+
const lines = properties.split('\n');
7+
const keys: Set<string> = new Set();
8+
9+
for (const line of lines) {
10+
if (line.trim().startsWith('#') || line.trim() === '') {
11+
continue;
12+
}
13+
14+
if (!line.includes('=')) {
15+
return false;
16+
}
17+
18+
const [key, _value] = line.split('=');
19+
20+
if (!key) {
21+
return false;
22+
}
23+
24+
if (keys.has(key.trim())) {
25+
return false;
26+
}
27+
28+
keys.add(key.trim());
29+
}
30+
31+
return true;
32+
}
33+
34+
// Thanks to https://github.com/sdoxsee/env-gen
35+
function parseProperties(properties: string): Record<string, string> {
36+
const result = properties
37+
.split('\n')
38+
.filter(Boolean) // removes empty lines
39+
.reduce((acc, line) => {
40+
const pair = line.split('=');
41+
_.set(acc, pair[0], pair[1]);
42+
return acc;
43+
}, {});
44+
return result;
45+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup lang="ts">
2+
import { stringify as stringifyToYaml } from 'yaml';
3+
import { withDefaultOnError } from '../../utils/defaults';
4+
import { isValidProperties, parseProperties } from './properties-to-yaml.service';
5+
import type { UseValidationRule } from '@/composable/validation';
6+
7+
const transformer = (value: string) => value.trim() === '' ? '' : withDefaultOnError(() => stringifyToYaml(parseProperties(value)), '');
8+
const rules: UseValidationRule<string>[] = [
9+
{
10+
validator: isValidProperties,
11+
message: 'Invalid .properties given.',
12+
},
13+
];
14+
</script>
15+
16+
<template>
17+
<format-transformer
18+
input-label="Your Properties"
19+
input-placeholder="Paste your Properties here..."
20+
output-label="YAML from your Properties"
21+
output-language="yaml"
22+
:input-validation-rules="rules"
23+
:transformer="transformer"
24+
/>
25+
</template>

0 commit comments

Comments
 (0)