@@ -9,6 +9,110 @@ const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+))?@)([\w.-]+)(?::(\d+))?\/(.+
9
9
/** Error message */
10
10
const ERROR_MESSAGE = 'Invalid Dsn' ;
11
11
12
+ function isValidProtocol ( protocol ?: string ) : protocol is DsnProtocol {
13
+ return protocol === 'http' || protocol === 'https' ;
14
+ }
15
+
16
+ /**
17
+ * Renders the string representation of this Dsn.
18
+ *
19
+ * By default, this will render the public representation without the password
20
+ * component. To get the deprecated private representation, set `withPassword`
21
+ * to true.
22
+ *
23
+ * @param withPassword When set to true, the password will be included.
24
+ */
25
+ function dsntoString ( dsn : Dsn , withPassword : boolean = false ) : string {
26
+ const { host, path, pass, port, projectId, protocol, publicKey } = dsn ;
27
+ return (
28
+ `${ protocol } ://${ publicKey } ${ withPassword && pass ? `:${ pass } ` : '' } ` +
29
+ `@${ host } ${ port ? `:${ port } ` : '' } /${ path ? `${ path } /` : path } ${ projectId } `
30
+ ) ;
31
+ }
32
+
33
+ function dsnFromString ( str : string ) : Dsn {
34
+ const match = DSN_REGEX . exec ( str ) ;
35
+
36
+ if ( ! match ) {
37
+ throw new SentryError ( ERROR_MESSAGE ) ;
38
+ }
39
+
40
+ const [ protocol , publicKey , pass = '' , host , port = '' , lastPath ] = match . slice ( 1 ) ;
41
+ let path = '' ;
42
+ let projectId = lastPath ;
43
+
44
+ const split = projectId . split ( '/' ) ;
45
+ if ( split . length > 1 ) {
46
+ path = split . slice ( 0 , - 1 ) . join ( '/' ) ;
47
+ projectId = split . pop ( ) as string ;
48
+ }
49
+
50
+ if ( projectId ) {
51
+ const projectMatch = projectId . match ( / ^ \d + / ) ;
52
+ if ( projectMatch ) {
53
+ projectId = projectMatch [ 0 ] ;
54
+ }
55
+ }
56
+
57
+ if ( isValidProtocol ( protocol ) ) {
58
+ return dsnFromComponents ( { host, pass, path, projectId, port, protocol : protocol , publicKey } ) ;
59
+ }
60
+
61
+ throw new SentryError ( ERROR_MESSAGE ) ;
62
+ }
63
+
64
+ function dsnFromComponents ( components : DsnComponents ) : Dsn {
65
+ // TODO this is for backwards compatibility, and can be removed in a future version
66
+ if ( 'user' in components && ! ( 'publicKey' in components ) ) {
67
+ components . publicKey = components . user ;
68
+ }
69
+
70
+ return {
71
+ user : components . publicKey || '' ,
72
+ protocol : components . protocol ,
73
+ publicKey : components . publicKey || '' ,
74
+ pass : components . pass || '' ,
75
+ host : components . host ,
76
+ port : components . port || '' ,
77
+ path : components . path || '' ,
78
+ projectId : components . projectId ,
79
+ } ;
80
+ }
81
+
82
+ function validateDsn ( dsn : Dsn ) : boolean {
83
+ if ( isDebugBuild ( ) ) {
84
+ const { port, projectId, protocol } = dsn ;
85
+
86
+ [ 'protocol' , 'publicKey' , 'host' , 'projectId' ] . forEach ( component => {
87
+ if ( ! dsn [ component ] ) {
88
+ throw new SentryError ( `${ ERROR_MESSAGE } : ${ component } missing` ) ;
89
+ }
90
+ } ) ;
91
+
92
+ if ( ! projectId . match ( / ^ \d + $ / ) ) {
93
+ throw new SentryError ( `${ ERROR_MESSAGE } : Invalid projectId ${ projectId } ` ) ;
94
+ }
95
+
96
+ if ( isValidProtocol ( protocol ) ) {
97
+ throw new SentryError ( `${ ERROR_MESSAGE } : Invalid protocol ${ protocol } ` ) ;
98
+ }
99
+
100
+ if ( port && isNaN ( parseInt ( port , 10 ) ) ) {
101
+ throw new SentryError ( `${ ERROR_MESSAGE } : Invalid port ${ port } ` ) ;
102
+ }
103
+ }
104
+
105
+ return true ;
106
+ }
107
+
108
+ function makeDsn ( from : DsnLike ) : Dsn {
109
+ let dsn = typeof from === 'string' ? dsnFromString ( from ) : dsnFromComponents ( from ) ;
110
+
111
+ return {
112
+ ...dsn ,
113
+ toString : ( ) => dsntoString ( dsn ) ,
114
+ } ;
115
+ }
12
116
/** The Sentry Dsn, identifying a Sentry instance and project. */
13
117
export class Dsn implements DsnComponents {
14
118
/** Protocol used to connect to Sentry. */
@@ -29,99 +133,5 @@ export class Dsn implements DsnComponents {
29
133
public projectId ! : string ;
30
134
31
135
/** Creates a new Dsn component */
32
- public constructor ( from : DsnLike ) {
33
- if ( typeof from === 'string' ) {
34
- this . _fromString ( from ) ;
35
- } else {
36
- this . _fromComponents ( from ) ;
37
- }
38
-
39
- this . _validate ( ) ;
40
- }
41
-
42
- /**
43
- * Renders the string representation of this Dsn.
44
- *
45
- * By default, this will render the public representation without the password
46
- * component. To get the deprecated private representation, set `withPassword`
47
- * to true.
48
- *
49
- * @param withPassword When set to true, the password will be included.
50
- */
51
- public toString ( withPassword : boolean = false ) : string {
52
- const { host, path, pass, port, projectId, protocol, publicKey } = this ;
53
- return (
54
- `${ protocol } ://${ publicKey } ${ withPassword && pass ? `:${ pass } ` : '' } ` +
55
- `@${ host } ${ port ? `:${ port } ` : '' } /${ path ? `${ path } /` : path } ${ projectId } `
56
- ) ;
57
- }
58
-
59
- /** Parses a string into this Dsn. */
60
- private _fromString ( str : string ) : void {
61
- const match = DSN_REGEX . exec ( str ) ;
62
-
63
- if ( ! match ) {
64
- throw new SentryError ( ERROR_MESSAGE ) ;
65
- }
66
-
67
- const [ protocol , publicKey , pass = '' , host , port = '' , lastPath ] = match . slice ( 1 ) ;
68
- let path = '' ;
69
- let projectId = lastPath ;
70
-
71
- const split = projectId . split ( '/' ) ;
72
- if ( split . length > 1 ) {
73
- path = split . slice ( 0 , - 1 ) . join ( '/' ) ;
74
- projectId = split . pop ( ) as string ;
75
- }
76
-
77
- if ( projectId ) {
78
- const projectMatch = projectId . match ( / ^ \d + / ) ;
79
- if ( projectMatch ) {
80
- projectId = projectMatch [ 0 ] ;
81
- }
82
- }
83
-
84
- this . _fromComponents ( { host, pass, path, projectId, port, protocol : protocol as DsnProtocol , publicKey } ) ;
85
- }
86
-
87
- /** Maps Dsn components into this instance. */
88
- private _fromComponents ( components : DsnComponents ) : void {
89
- // TODO this is for backwards compatibility, and can be removed in a future version
90
- if ( 'user' in components && ! ( 'publicKey' in components ) ) {
91
- components . publicKey = components . user ;
92
- }
93
- this . user = components . publicKey || '' ;
94
-
95
- this . protocol = components . protocol ;
96
- this . publicKey = components . publicKey || '' ;
97
- this . pass = components . pass || '' ;
98
- this . host = components . host ;
99
- this . port = components . port || '' ;
100
- this . path = components . path || '' ;
101
- this . projectId = components . projectId ;
102
- }
103
-
104
- /** Validates this Dsn and throws on error. */
105
- private _validate ( ) : void {
106
- // we only validate in debug mode. This will fail later anyways.
107
- if ( isDebugBuild ( ) ) {
108
- [ 'protocol' , 'publicKey' , 'host' , 'projectId' ] . forEach ( component => {
109
- if ( ! this [ component as keyof DsnComponents ] ) {
110
- throw new SentryError ( `${ ERROR_MESSAGE } : ${ component } missing` ) ;
111
- }
112
- } ) ;
113
-
114
- if ( ! this . projectId . match ( / ^ \d + $ / ) ) {
115
- throw new SentryError ( `${ ERROR_MESSAGE } : Invalid projectId ${ this . projectId } ` ) ;
116
- }
117
-
118
- if ( this . protocol !== 'http' && this . protocol !== 'https' ) {
119
- throw new SentryError ( `${ ERROR_MESSAGE } : Invalid protocol ${ this . protocol } ` ) ;
120
- }
121
-
122
- if ( this . port && isNaN ( parseInt ( this . port , 10 ) ) ) {
123
- throw new SentryError ( `${ ERROR_MESSAGE } : Invalid port ${ this . port } ` ) ;
124
- }
125
- }
126
- }
136
+ public constructor ( from : DsnLike ) { }
127
137
}
0 commit comments