11import { IncludeEntry as UserIncludeEntry , Options as UserOptions } from "./types" ;
2+ import { arrayify } from "./utils" ;
23
34type RequiredInternalOptions = Required <
45 Pick <
56 UserOptions ,
6- | "org"
7- | "project"
8- | "authToken"
9- | "url"
107 | "release"
118 | "finalize"
12- | "vcsRemote"
139 | "dryRun"
1410 | "debug"
1511 | "silent"
@@ -22,7 +18,17 @@ type RequiredInternalOptions = Required<
2218type OptionalInternalOptions = Partial <
2319 Pick <
2420 UserOptions ,
25- "dist" | "errorHandler" | "setCommits" | "deploy" | "configFile" | "customHeader"
21+ | "org"
22+ | "project"
23+ | "authToken"
24+ | "url"
25+ | "vcsRemote"
26+ | "dist"
27+ | "errorHandler"
28+ | "setCommits"
29+ | "deploy"
30+ | "configFile"
31+ | "customHeader"
2632 >
2733> ;
2834
@@ -52,59 +58,88 @@ export type InternalIncludeEntry = RequiredInternalIncludeEntry &
5258 } ;
5359
5460export function normalizeUserOptions ( userOptions : UserOptions ) : InternalOptions {
55- let entries : ( string | RegExp ) [ ] | ( ( filePath : string ) => boolean ) | undefined ;
56- if ( userOptions . entries === undefined ) {
57- entries = undefined ;
58- } else if ( typeof userOptions . entries === "function" || Array . isArray ( userOptions . entries ) ) {
59- entries = userOptions . entries ;
60- } else {
61- entries = [ userOptions . entries ] ;
62- }
63-
64- let userInclude : UserIncludeEntry [ ] ;
65- if ( typeof userOptions . include === "string" ) {
66- userInclude = [ convertIncludePathToIncludeEntry ( userOptions . include ) ] ;
67- } else if ( Array . isArray ( userOptions . include ) ) {
68- userInclude = userOptions . include . map ( ( potentialIncludeEntry ) => {
69- if ( typeof potentialIncludeEntry === "string" ) {
70- return convertIncludePathToIncludeEntry ( potentialIncludeEntry ) ;
71- } else {
72- return potentialIncludeEntry ;
73- }
74- } ) ;
75- } else {
76- userInclude = [ userOptions . include ] ;
77- }
61+ return {
62+ // include is the only strictly required option
63+ // (normalizeInclude needs all userOptions to access top-level include options)
64+ include : normalizeInclude ( userOptions ) ,
7865
79- const include = userInclude . map ( ( userIncludeEntry ) =>
80- normalizeIncludeEntry ( userOptions , userIncludeEntry )
81- ) ;
66+ // These options must be set b/c we need them for release injection.
67+ // They can also be set as environment variables. Technically, they
68+ // could be set in the config file but this would be too late for
69+ // release injection because we only pass the config file path
70+ // to the CLI
71+ org : userOptions . org ?? process . env [ "SENTRY_ORG" ] ,
72+ project : userOptions . project ?? process . env [ "SENTRY_PROJECT" ] ,
73+ // Falling back to the empty string here b/c at a later point, we use
74+ // Sentry CLI to determine a release if none was specified via options
75+ // or env vars. In case we don't find one, we'll bail at that point.
76+ release : userOptions . release ?? process . env [ "SENTRY_RELEASE" ] ?? "" ,
8277
83- return {
84- org : userOptions . org ,
85- project : userOptions . project ,
86- authToken : userOptions . authToken ,
87- url : userOptions . url ?? "https://sentry.io/" ,
88- release : userOptions . release ?? "" ,
78+ // Options with default values
8979 finalize : userOptions . finalize ?? true ,
90- vcsRemote : userOptions . vcsRemote ?? "origin" ,
91- customHeader : userOptions . customHeader ,
80+ cleanArtifacts : userOptions . cleanArtifacts ?? false ,
9281 dryRun : userOptions . dryRun ?? false ,
9382 debug : userOptions . debug ?? false ,
9483 silent : userOptions . silent ?? false ,
95- cleanArtifacts : userOptions . cleanArtifacts ?? false ,
9684 telemetry : userOptions . telemetry ?? true ,
97- dist : userOptions . dist ,
98- errorHandler : userOptions . errorHandler ,
85+ injectReleasesMap : userOptions . injectReleasesMap ?? false ,
86+
87+ // These options and can also be set via env variables or the config file.
88+ // If they're set in the options, we simply pass them to the CLI constructor.
89+ // Sentry CLI will internally query env variables and read its config file if
90+ // the passed options are undefined.
91+ authToken : userOptions . authToken , // env var: `SENTRY_AUTH_TOKEN`
92+ customHeader : userOptions . customHeader , // env var: `CUSTOM_HEADER`
93+ url : userOptions . url , // env var: `SENTRY_URL`
94+ vcsRemote : userOptions . vcsRemote , // env var: `SENTRY_VSC_REMOTE`
95+
96+ // Optional options
9997 setCommits : userOptions . setCommits ,
10098 deploy : userOptions . deploy ,
101- entries,
102- include,
99+ entries : normalizeEntries ( userOptions . entries ) ,
100+ dist : userOptions . dist ,
101+ errorHandler : userOptions . errorHandler ,
103102 configFile : userOptions . configFile ,
104- injectReleasesMap : userOptions . injectReleasesMap ?? false ,
105103 } ;
106104}
107105
106+ /**
107+ * Converts the user-facing `entries` option to the internal `entries` option
108+ */
109+ function normalizeEntries (
110+ userEntries : UserOptions [ "entries" ]
111+ ) : ( string | RegExp ) [ ] | ( ( filePath : string ) => boolean ) | undefined {
112+ if ( userEntries === undefined ) {
113+ return undefined ;
114+ } else if ( typeof userEntries === "function" ) {
115+ return userEntries ;
116+ } else {
117+ return arrayify ( userEntries ) ;
118+ }
119+ }
120+
121+ /**
122+ * Converts the user-facing `include` option to the internal `include` option,
123+ * resulting in an array of `InternalIncludeEntry` objects. This later on lets us
124+ * work with only one type of include data structure instead of multiple.
125+ *
126+ * During the process, we hoist top-level include options (e.g. urlPrefix) into each
127+ * object if they were not alrady specified in an `IncludeEntry`, making every object
128+ * fully self-contained. This is also the reason why we pass the entire options
129+ * object and not just `include`.
130+ *
131+ * @param userOptions the entire user-facing `options` object
132+ *
133+ * @return an array of `InternalIncludeEntry` objects.
134+ */
135+ function normalizeInclude ( userOptions : UserOptions ) : InternalIncludeEntry [ ] {
136+ return arrayify ( userOptions . include )
137+ . map ( ( includeItem ) =>
138+ typeof includeItem === "string" ? convertIncludePathToIncludeEntry ( includeItem ) : includeItem
139+ )
140+ . map ( ( userIncludeEntry ) => normalizeIncludeEntry ( userOptions , userIncludeEntry ) ) ;
141+ }
142+
108143function convertIncludePathToIncludeEntry ( includePath : string ) : UserIncludeEntry {
109144 return {
110145 paths : [ includePath ] ,
0 commit comments