1414
1515import { InstanceConnectionInfo } from './instance-connection-info' ;
1616import { CloudSQLConnectorError } from './errors' ;
17+ import { resolveTxtRecord } from './dns-lookup' ;
1718
18- export function parseInstanceConnectionName (
19- instanceConnectionName : string | undefined
20- ) : InstanceConnectionInfo {
21- if ( ! instanceConnectionName ) {
19+ export async function resolveInstanceName (
20+ name : string | undefined
21+ ) : Promise < InstanceConnectionInfo > {
22+ if ( ! name ) {
2223 throw new CloudSQLConnectorError ( {
2324 message :
2425 'Missing instance connection name, expected: "PROJECT:REGION:INSTANCE"' ,
2526 code : 'ENOCONNECTIONNAME' ,
2627 } ) ;
28+ } else if ( isInstanceConnectionName ( name ) ) {
29+ return parseInstanceConnectionName ( name ) ;
30+ } else if ( isValidDomainName ( name ) ) {
31+ return await resolveDomainName ( name ) ;
32+ } else {
33+ throw new CloudSQLConnectorError ( {
34+ message :
35+ 'Malformed Instance connection name, expected an instance connection name in the form "PROJECT:REGION:INSTANCE" or a valid domain name' ,
36+ code : 'EBADCONNECTIONNAME' ,
37+ } ) ;
2738 }
39+ }
2840
29- const connectionNameRegex =
30- / (?< projectId > [ ^ : ] + ( : [ ^ : ] + ) ? ) : (?< regionId > [ ^ : ] + ) : (?< instanceId > [ ^ : ] + ) / ;
31- const matches = String ( instanceConnectionName ) . match ( connectionNameRegex ) ;
32- if ( ! matches ) {
41+ const connectionNameRegex =
42+ / ^ (?< projectId > [ ^ : ] + ( : [ ^ : ] + ) ? ) : (?< regionId > [ ^ : ] + ) : (?< instanceId > [ ^ : ] + ) $ / ;
43+
44+ // The domain name pattern in accordance with RFC 1035, RFC 1123 and RFC 2181.
45+ // From Go Connector:
46+ const domainNameRegex =
47+ / ^ (?: [ _ a - z 0 - 9 ] (?: [ _ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? \. ) + (?: [ a - z ] (?: [ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? ) ? $ / ;
48+
49+ export function isValidDomainName ( name : string ) : boolean {
50+ const matches = String ( name ) . match ( domainNameRegex ) ;
51+ return Boolean ( matches ) ;
52+ }
53+
54+ export function isInstanceConnectionName ( name : string ) : boolean {
55+ const matches = String ( name ) . match ( connectionNameRegex ) ;
56+ return Boolean ( matches ) ;
57+ }
58+
59+ export async function resolveDomainName (
60+ name : string
61+ ) : Promise < InstanceConnectionInfo > {
62+ const icn = await resolveTxtRecord ( name ) ;
63+ if ( ! isInstanceConnectionName ( icn ) ) {
3364 throw new CloudSQLConnectorError ( {
3465 message :
35- 'Malformed instance connection name provided: expected format ' +
36- `of "PROJECT:REGION:INSTANCE", got ${ instanceConnectionName } ` ,
37- code : 'EBADCONNECTIONNAME' ,
66+ 'Malformed instance connection name returned for domain ' +
67+ name +
68+ ' : ' +
69+ icn ,
70+ code : 'EBADDOMAINCONNECTIONNAME' ,
71+ } ) ;
72+ }
73+
74+ const info = parseInstanceConnectionName ( icn ) ;
75+ info . domainName = name ;
76+ return info ;
77+ }
78+
79+ export function parseInstanceConnectionName (
80+ instanceConnectionName : string | undefined
81+ ) : InstanceConnectionInfo {
82+ if ( ! instanceConnectionName ) {
83+ throw new CloudSQLConnectorError ( {
84+ message :
85+ 'Missing instance connection name, expected: "PROJECT:REGION:INSTANCE"' ,
86+ code : 'ENOCONNECTIONNAME' ,
3887 } ) ;
3988 }
4089
41- const unmatchedItems = matches [ 0 ] !== matches . input ;
42- if ( unmatchedItems || ! matches . groups ) {
90+ const matches = String ( instanceConnectionName ) . match ( connectionNameRegex ) ;
91+ if ( ! matches || ! matches . groups ) {
4392 throw new CloudSQLConnectorError ( {
4493 message :
4594 'Malformed instance connection name provided: expected format ' +
@@ -52,5 +101,6 @@ export function parseInstanceConnectionName(
52101 projectId : matches . groups . projectId ,
53102 regionId : matches . groups . regionId ,
54103 instanceId : matches . groups . instanceId ,
104+ domainName : undefined ,
55105 } ;
56106}
0 commit comments