Skip to content

Commit 000904a

Browse files
committed
add semantic parsing and normalization support
1 parent de64257 commit 000904a

29 files changed

Lines changed: 1846 additions & 95 deletions

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ Returns a `ConnparseAddress` or throws an `Error`.
174174

175175
Returns a `ParseResult`, but `value` is a stable normalized object instead of a
176176
faithful raw parse object. Equivalent inputs produce the same normalized JSON.
177+
It also includes an optional `semantic` block with provider-normalized field
178+
values that consumers can map onto forms without re-implementing provider
179+
aliases.
177180

178181
Use `parse()` when you need to preserve the exact original input in `raw`. Use
179182
`parseNormalize()` when you need dedupe keys, config comparison, cache keys, or
@@ -208,7 +211,16 @@ Both return the same normalized `value`:
208211
"options": {},
209212
"raw": "postgres://localhost/app?application_name=myapp&sslmode=require",
210213
"safe": "postgres://localhost/app?application_name=myapp&sslmode=require",
211-
"canonical": "postgres://localhost/app?application_name=myapp&sslmode=require"
214+
"canonical": "postgres://localhost/app?application_name=myapp&sslmode=require",
215+
"semantic": {
216+
"provider": "postgres",
217+
"fields": {
218+
"ssl_mode": "required"
219+
},
220+
"consumed": {
221+
"query": ["sslmode"]
222+
}
223+
}
212224
}
213225
```
214226

packages/go/builtin_definitions.go

Lines changed: 32 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/java/src/main/java/com/clidey/connparse/BuiltInDefinitions.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static List<Definition> builtInDefinitions() {
231231
new Definition.Rule("database", false),
232232
new Definition.Rule("object_path", false),
233233
map(entry("password", true), entry("username", true)),
234-
queryRules(queryRule("createDatabaseIfNotExist", new Definition.QueryRule("boolean", List.of())), queryRule("database", new Definition.QueryRule("string", List.of())), queryRule("debug", new Definition.QueryRule("boolean", List.of())), queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("readonly", new Definition.QueryRule("number", List.of())), queryRule("ssl", new Definition.QueryRule("boolean", List.of())), queryRule("sslmode", new Definition.QueryRule("string", List.of())), queryRule("user", new Definition.QueryRule("string", List.of()))),
234+
queryRules(queryRule("createDatabaseIfNotExist", new Definition.QueryRule("boolean", List.of())), queryRule("database", new Definition.QueryRule("string", List.of())), queryRule("debug", new Definition.QueryRule("boolean", List.of())), queryRule("httpProtocol", new Definition.QueryRule("string", List.of("http", "https"))), queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("readonly", new Definition.QueryRule("number", List.of())), queryRule("ssl", new Definition.QueryRule("boolean", List.of())), queryRule("sslmode", new Definition.QueryRule("string", List.of("disable", "require", "verify-ca", "verify-full"))), queryRule("user", new Definition.QueryRule("string", List.of()))),
235235
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
236236
map(),
237237
new Definition.RedactionRule(List.of("username"), List.of("password"))
@@ -407,7 +407,7 @@ static List<Definition> builtInDefinitions() {
407407
new Definition.Rule("index", false),
408408
new Definition.Rule("api_path", false),
409409
map(entry("api_key", true), entry("password", true), entry("token", true), entry("username", true)),
410-
queryRules(queryRule("api_key", new Definition.QueryRule("string", List.of())), queryRule("apiKey", new Definition.QueryRule("string", List.of())), queryRule("token", new Definition.QueryRule("string", List.of()))),
410+
queryRules(queryRule("api_key", new Definition.QueryRule("string", List.of())), queryRule("token", new Definition.QueryRule("string", List.of()))),
411411
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
412412
map(),
413413
new Definition.RedactionRule(List.of("username"), List.of("password", "api_key", "apiKey", "token"))
@@ -519,7 +519,7 @@ static List<Definition> builtInDefinitions() {
519519
new Definition.Rule("database", false),
520520
new Definition.Rule("object_path", false),
521521
map(entry("password", true), entry("username", true)),
522-
queryRules(queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("sslMode", new Definition.QueryRule("string", List.of("disable", "trust", "verify-ca", "verify-full"))), queryRule("user", new Definition.QueryRule("string", List.of()))),
522+
queryRules(queryRule("allowCleartextPasswords", new Definition.QueryRule("boolean", List.of())), queryRule("loc", new Definition.QueryRule("string", List.of())), queryRule("parseTime", new Definition.QueryRule("boolean", List.of())), queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("sslMode", new Definition.QueryRule("string", List.of("disable", "trust", "verify-ca", "verify-full"))), queryRule("user", new Definition.QueryRule("string", List.of()))),
523523
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
524524
map(),
525525
new Definition.RedactionRule(List.of("username"), List.of("password"))
@@ -631,7 +631,7 @@ static List<Definition> builtInDefinitions() {
631631
new Definition.Rule("database", false),
632632
new Definition.Rule("object_path", false),
633633
map(entry("password", true), entry("username", true)),
634-
queryRules(queryRule("auth-method", new Definition.QueryRule("string", List.of("AUTO", "MYSQL41", "SHA256_MEMORY", "FROM_CAPABILITIES", "FALLBACK", "PLAIN"))), queryRule("charset", new Definition.QueryRule("string", List.of())), queryRule("get-server-public-key", new Definition.QueryRule("boolean", List.of())), queryRule("schema", new Definition.QueryRule("string", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("ssl-ca", new Definition.QueryRule("string", List.of())), queryRule("ssl-capath", new Definition.QueryRule("string", List.of())), queryRule("ssl-cert", new Definition.QueryRule("string", List.of())), queryRule("ssl-cipher", new Definition.QueryRule("string", List.of())), queryRule("ssl-crl", new Definition.QueryRule("string", List.of())), queryRule("ssl-crlpath", new Definition.QueryRule("string", List.of())), queryRule("ssl-key", new Definition.QueryRule("string", List.of())), queryRule("ssl-mode", new Definition.QueryRule("string", List.of("DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY"))), queryRule("tls-version", new Definition.QueryRule("string", List.of())), queryRule("tls-versions", new Definition.QueryRule("string", List.of()))),
634+
queryRules(queryRule("allowCleartextPasswords", new Definition.QueryRule("boolean", List.of())), queryRule("auth-method", new Definition.QueryRule("string", List.of("AUTO", "MYSQL41", "SHA256_MEMORY", "FROM_CAPABILITIES", "FALLBACK", "PLAIN"))), queryRule("charset", new Definition.QueryRule("string", List.of())), queryRule("get-server-public-key", new Definition.QueryRule("boolean", List.of())), queryRule("loc", new Definition.QueryRule("string", List.of())), queryRule("parseTime", new Definition.QueryRule("boolean", List.of())), queryRule("schema", new Definition.QueryRule("string", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("ssl-ca", new Definition.QueryRule("string", List.of())), queryRule("ssl-capath", new Definition.QueryRule("string", List.of())), queryRule("ssl-cert", new Definition.QueryRule("string", List.of())), queryRule("ssl-cipher", new Definition.QueryRule("string", List.of())), queryRule("ssl-crl", new Definition.QueryRule("string", List.of())), queryRule("ssl-crlpath", new Definition.QueryRule("string", List.of())), queryRule("ssl-key", new Definition.QueryRule("string", List.of())), queryRule("ssl-mode", new Definition.QueryRule("string", List.of("DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY"))), queryRule("tls-version", new Definition.QueryRule("string", List.of())), queryRule("tls-versions", new Definition.QueryRule("string", List.of()))),
635635
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
636636
map(),
637637
new Definition.RedactionRule(List.of("username"), List.of("password", "ssl-ca", "ssl-capath", "ssl-cert", "ssl-cipher", "ssl-crl", "ssl-crlpath", "ssl-key"))
@@ -695,7 +695,7 @@ static List<Definition> builtInDefinitions() {
695695
new Definition.Rule("index", false),
696696
new Definition.Rule("api_path", false),
697697
map(entry("api_key", true), entry("password", true), entry("token", true), entry("username", true)),
698-
queryRules(queryRule("api_key", new Definition.QueryRule("string", List.of())), queryRule("apiKey", new Definition.QueryRule("string", List.of())), queryRule("token", new Definition.QueryRule("string", List.of()))),
698+
queryRules(queryRule("api_key", new Definition.QueryRule("string", List.of())), queryRule("token", new Definition.QueryRule("string", List.of()))),
699699
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
700700
map(entry("compatible_with", "elasticsearch")),
701701
new Definition.RedactionRule(List.of("username"), List.of("password", "api_key", "apiKey", "token"))
@@ -727,7 +727,7 @@ static List<Definition> builtInDefinitions() {
727727
new Definition.Rule("database", true),
728728
new Definition.Rule("object_path", false),
729729
map(entry("password", true), entry("username", true)),
730-
queryRules(queryRule("application_name", new Definition.QueryRule("string", List.of())), queryRule("connect_timeout", new Definition.QueryRule("number", List.of())), queryRule("host", new Definition.QueryRule("string", List.of())), queryRule("hostaddr", new Definition.QueryRule("string", List.of())), queryRule("options", new Definition.QueryRule("string", List.of())), queryRule("passfile", new Definition.QueryRule("string", List.of())), queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("port", new Definition.QueryRule("string", List.of())), queryRule("require_auth", new Definition.QueryRule("string", List.of())), queryRule("service", new Definition.QueryRule("string", List.of())), queryRule("sslcert", new Definition.QueryRule("string", List.of())), queryRule("sslkey", new Definition.QueryRule("string", List.of())), queryRule("sslmode", new Definition.QueryRule("string", List.of("disable", "allow", "prefer", "require", "verify-ca", "verify-full"))), queryRule("sslrootcert", new Definition.QueryRule("string", List.of())), queryRule("target_session_attrs", new Definition.QueryRule("string", List.of("any", "read-write", "read-only", "primary", "standby", "prefer-standby")))),
730+
queryRules(queryRule("application_name", new Definition.QueryRule("string", List.of())), queryRule("connect_timeout", new Definition.QueryRule("number", List.of())), queryRule("host", new Definition.QueryRule("string", List.of())), queryRule("hostaddr", new Definition.QueryRule("string", List.of())), queryRule("options", new Definition.QueryRule("string", List.of())), queryRule("passfile", new Definition.QueryRule("string", List.of())), queryRule("password", new Definition.QueryRule("string", List.of())), queryRule("port", new Definition.QueryRule("string", List.of())), queryRule("require_auth", new Definition.QueryRule("string", List.of())), queryRule("search_path", new Definition.QueryRule("string", List.of())), queryRule("service", new Definition.QueryRule("string", List.of())), queryRule("sslcert", new Definition.QueryRule("string", List.of())), queryRule("sslkey", new Definition.QueryRule("string", List.of())), queryRule("sslmode", new Definition.QueryRule("string", List.of("disable", "allow", "prefer", "require", "verify-ca", "verify-full"))), queryRule("sslrootcert", new Definition.QueryRule("string", List.of())), queryRule("target_session_attrs", new Definition.QueryRule("string", List.of("any", "read-write", "read-only", "primary", "standby", "prefer-standby")))),
731731
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
732732
map(),
733733
new Definition.RedactionRule(List.of("username"), List.of("password", "passfile", "sslcert", "sslkey", "sslrootcert"))
@@ -935,7 +935,7 @@ static List<Definition> builtInDefinitions() {
935935
new Definition.Rule("database", false),
936936
new Definition.Rule("object_path", false),
937937
map(entry("password", true), entry("username", true)),
938-
queryRules(queryRule("charset", new Definition.QueryRule("string", List.of())), queryRule("loc", new Definition.QueryRule("string", List.of())), queryRule("parseTime", new Definition.QueryRule("boolean", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("ssl-mode", new Definition.QueryRule("string", List.of()))),
938+
queryRules(queryRule("allowCleartextPasswords", new Definition.QueryRule("boolean", List.of())), queryRule("charset", new Definition.QueryRule("string", List.of())), queryRule("loc", new Definition.QueryRule("string", List.of())), queryRule("parseTime", new Definition.QueryRule("boolean", List.of())), queryRule("ssl", new Definition.QueryRule("string", List.of())), queryRule("ssl-mode", new Definition.QueryRule("string", List.of("DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY")))),
939939
new Definition.ValidationRule(true, new Definition.PortRange(1L, 65535L)),
940940
map(entry("compatible_with", "mysql")),
941941
new Definition.RedactionRule(List.of("username"), List.of("password"))

packages/js/README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,23 @@ logger.info({ connection: result.value.safe });
9191
```
9292

9393
Use `parseNormalize()` when you need a stable identity for dedupe, cache keys,
94-
or config comparison.
94+
or config comparison. It also returns provider-normalized semantic fields for
95+
consumers that want stable form values instead of provider-specific query keys.
9596

9697
```ts
9798
import { parseNormalize } from '@clidey/connparse';
9899

99-
parseNormalize('postgresql://LOCALHOST:5432/app?sslmode=require').value.canonical;
100-
// "postgres://localhost/app?sslmode=require"
100+
const result = parseNormalize('postgresql://LOCALHOST:5432/app?sslmode=require&search_path=tenant_a');
101+
102+
result.value.canonical;
103+
// "postgres://localhost/app?search_path=tenant_a&sslmode=require"
104+
105+
result.value.semantic;
106+
// {
107+
// provider: 'postgres',
108+
// fields: { ssl_mode: 'required', search_path: 'tenant_a' },
109+
// consumed: { query: ['search_path', 'sslmode'] }
110+
// }
101111
```
102112

103113
Use `provider` when the string does not clearly identify the source type.

0 commit comments

Comments
 (0)