@sentry/bundler-plugin-core 0.0.1-alpha.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,38 +1,8 @@
1
1
  import { createUnplugin } from 'unplugin';
2
2
  import MagicString from 'magic-string';
3
- import * as child_process from 'child_process';
4
- import axios, { AxiosError } from 'axios';
5
- import FormData from 'form-data';
6
3
  import { NodeClient, Integrations, defaultStackParser, makeNodeTransport, Hub, makeMain } from '@sentry/node';
7
- import path from 'path';
8
- import fs from 'fs';
9
4
  import '@sentry/tracing';
10
-
11
- function ownKeys(object, enumerableOnly) {
12
- var keys = Object.keys(object);
13
-
14
- if (Object.getOwnPropertySymbols) {
15
- var symbols = Object.getOwnPropertySymbols(object);
16
- enumerableOnly && (symbols = symbols.filter(function (sym) {
17
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
18
- })), keys.push.apply(keys, symbols);
19
- }
20
-
21
- return keys;
22
- }
23
-
24
- function _objectSpread2(target) {
25
- for (var i = 1; i < arguments.length; i++) {
26
- var source = null != arguments[i] ? arguments[i] : {};
27
- i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
28
- _defineProperty(target, key, source[key]);
29
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
30
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
31
- });
32
- }
33
-
34
- return target;
35
- }
5
+ import SentryCli from '@sentry/cli';
36
6
 
37
7
  function _regeneratorRuntime() {
38
8
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
@@ -379,6 +349,16 @@ function _regeneratorRuntime() {
379
349
  }, exports;
380
350
  }
381
351
 
352
+ function _typeof(obj) {
353
+ "@babel/helpers - typeof";
354
+
355
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
356
+ return typeof obj;
357
+ } : function (obj) {
358
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
359
+ }, _typeof(obj);
360
+ }
361
+
382
362
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
383
363
  try {
384
364
  var info = gen[key](arg);
@@ -415,85 +395,565 @@ function _asyncToGenerator(fn) {
415
395
  };
416
396
  }
417
397
 
418
- function _defineProperty(obj, key, value) {
419
- if (key in obj) {
420
- Object.defineProperty(obj, key, {
421
- value: value,
422
- enumerable: true,
423
- configurable: true,
424
- writable: true
398
+ /** Internal global with common properties and Sentry extensions */
399
+
400
+ // The code below for 'isGlobalObj' and 'GLOBAL_OBJ' was copied from core-js before modification
401
+ // https://github.com/zloirock/core-js/blob/1b944df55282cdc99c90db5f49eb0b6eda2cc0a3/packages/core-js/internals/global.js
402
+ // core-js has the following licence:
403
+ //
404
+ // Copyright (c) 2014-2022 Denis Pushkarev
405
+ //
406
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
407
+ // of this software and associated documentation files (the "Software"), to deal
408
+ // in the Software without restriction, including without limitation the rights
409
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
410
+ // copies of the Software, and to permit persons to whom the Software is
411
+ // furnished to do so, subject to the following conditions:
412
+ //
413
+ // The above copyright notice and this permission notice shall be included in
414
+ // all copies or substantial portions of the Software.
415
+ //
416
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
417
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
418
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
419
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
420
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
421
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
422
+ // THE SOFTWARE.
423
+
424
+ /** Returns 'obj' if it's the global object, otherwise returns undefined */
425
+ function isGlobalObj(obj) {
426
+ return obj && obj.Math == Math ? obj : undefined;
427
+ }
428
+
429
+ /** Get's the global object for the current JavaScript runtime */
430
+ const GLOBAL_OBJ =
431
+ (typeof globalThis == 'object' && isGlobalObj(globalThis)) ||
432
+ // eslint-disable-next-line no-restricted-globals
433
+ (typeof window == 'object' && isGlobalObj(window)) ||
434
+ (typeof self == 'object' && isGlobalObj(self)) ||
435
+ (typeof global == 'object' && isGlobalObj(global)) ||
436
+ (function () {
437
+ return this;
438
+ })() ||
439
+ {};
440
+
441
+ /**
442
+ * @deprecated Use GLOBAL_OBJ instead or WINDOW from @sentry/browser. This will be removed in v8
443
+ */
444
+ function getGlobalObject() {
445
+ return GLOBAL_OBJ ;
446
+ }
447
+
448
+ /**
449
+ * Returns a global singleton contained in the global `__SENTRY__` object.
450
+ *
451
+ * If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
452
+ * function and added to the `__SENTRY__` object.
453
+ *
454
+ * @param name name of the global singleton on __SENTRY__
455
+ * @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
456
+ * @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
457
+ * @returns the singleton
458
+ */
459
+ function getGlobalSingleton(name, creator, obj) {
460
+ const gbl = (obj || GLOBAL_OBJ) ;
461
+ const __SENTRY__ = (gbl.__SENTRY__ = gbl.__SENTRY__ || {});
462
+ const singleton = __SENTRY__[name] || (__SENTRY__[name] = creator());
463
+ return singleton;
464
+ }
465
+
466
+ /** Prefix for logging strings */
467
+ const PREFIX = 'Sentry Logger ';
468
+
469
+ const CONSOLE_LEVELS = ['debug', 'info', 'warn', 'error', 'log', 'assert', 'trace'] ;
470
+
471
+ /**
472
+ * Temporarily disable sentry console instrumentations.
473
+ *
474
+ * @param callback The function to run against the original `console` messages
475
+ * @returns The results of the callback
476
+ */
477
+ function consoleSandbox(callback) {
478
+ if (!('console' in GLOBAL_OBJ)) {
479
+ return callback();
480
+ }
481
+
482
+ const originalConsole = GLOBAL_OBJ.console ;
483
+ const wrappedLevels = {};
484
+
485
+ // Restore all wrapped console methods
486
+ CONSOLE_LEVELS.forEach(level => {
487
+ // TODO(v7): Remove this check as it's only needed for Node 6
488
+ const originalWrappedFunc =
489
+ originalConsole[level] && (originalConsole[level] ).__sentry_original__;
490
+ if (level in originalConsole && originalWrappedFunc) {
491
+ wrappedLevels[level] = originalConsole[level] ;
492
+ originalConsole[level] = originalWrappedFunc ;
493
+ }
494
+ });
495
+
496
+ try {
497
+ return callback();
498
+ } finally {
499
+ // Revert restoration to wrapped state
500
+ Object.keys(wrappedLevels).forEach(level => {
501
+ originalConsole[level] = wrappedLevels[level ];
502
+ });
503
+ }
504
+ }
505
+
506
+ function makeLogger() {
507
+ let enabled = false;
508
+ const logger = {
509
+ enable: () => {
510
+ enabled = true;
511
+ },
512
+ disable: () => {
513
+ enabled = false;
514
+ },
515
+ };
516
+
517
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
518
+ CONSOLE_LEVELS.forEach(name => {
519
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
520
+ logger[name] = (...args) => {
521
+ if (enabled) {
522
+ consoleSandbox(() => {
523
+ GLOBAL_OBJ.console[name](`${PREFIX}[${name}]:`, ...args);
524
+ });
525
+ }
526
+ };
425
527
  });
426
528
  } else {
427
- obj[key] = value;
529
+ CONSOLE_LEVELS.forEach(name => {
530
+ logger[name] = () => undefined;
531
+ });
532
+ }
533
+
534
+ return logger ;
535
+ }
536
+
537
+ // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used
538
+ let logger;
539
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
540
+ logger = getGlobalSingleton('logger', makeLogger);
541
+ } else {
542
+ logger = makeLogger();
543
+ }
544
+
545
+ /*
546
+ * This module exists for optimizations in the build process through rollup and terser. We define some global
547
+ * constants, which can be overridden during build. By guarding certain pieces of code with functions that return these
548
+ * constants, we can control whether or not they appear in the final bundle. (Any code guarded by a false condition will
549
+ * never run, and will hence be dropped during treeshaking.) The two primary uses for this are stripping out calls to
550
+ * `logger` and preventing node-related code from appearing in browser bundles.
551
+ *
552
+ * Attention:
553
+ * This file should not be used to define constants/flags that are intended to be used for tree-shaking conducted by
554
+ * users. These fags should live in their respective packages, as we identified user tooling (specifically webpack)
555
+ * having issues tree-shaking these constants across package boundaries.
556
+ * An example for this is the __SENTRY_DEBUG__ constant. It is declared in each package individually because we want
557
+ * users to be able to shake away expressions that it guards.
558
+ */
559
+
560
+ /**
561
+ * Figures out if we're building a browser bundle.
562
+ *
563
+ * @returns true if this is a browser bundle build.
564
+ */
565
+ function isBrowserBundle() {
566
+ return typeof __SENTRY_BROWSER_BUNDLE__ !== 'undefined' && !!__SENTRY_BROWSER_BUNDLE__;
567
+ }
568
+
569
+ /**
570
+ * NOTE: In order to avoid circular dependencies, if you add a function to this module and it needs to print something,
571
+ * you must either a) use `console.log` rather than the logger, or b) put your function elsewhere.
572
+ */
573
+
574
+ /**
575
+ * Checks whether we're in the Node.js or Browser environment
576
+ *
577
+ * @returns Answer to given question
578
+ */
579
+ function isNodeEnv() {
580
+ // explicitly check for browser bundles as those can be optimized statically
581
+ // by terser/rollup.
582
+ return (
583
+ !isBrowserBundle() &&
584
+ Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]'
585
+ );
586
+ }
587
+
588
+ /**
589
+ * Requires a module which is protected against bundler minification.
590
+ *
591
+ * @param request The module path to resolve
592
+ */
593
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
594
+ function dynamicRequire(mod, request) {
595
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
596
+ return mod.require(request);
597
+ }
598
+
599
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
600
+
601
+ /** SyncPromise internal states */
602
+ var States; (function (States) {
603
+ /** Pending */
604
+ const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
605
+ /** Resolved / OK */
606
+ const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
607
+ /** Rejected / Error */
608
+ const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
609
+ })(States || (States = {}));
610
+
611
+ // eslint-disable-next-line deprecation/deprecation
612
+ const WINDOW = getGlobalObject();
613
+
614
+ /**
615
+ * An object that can return the current timestamp in seconds since the UNIX epoch.
616
+ */
617
+
618
+ /**
619
+ * A TimestampSource implementation for environments that do not support the Performance Web API natively.
620
+ *
621
+ * Note that this TimestampSource does not use a monotonic clock. A call to `nowSeconds` may return a timestamp earlier
622
+ * than a previously returned value. We do not try to emulate a monotonic behavior in order to facilitate debugging. It
623
+ * is more obvious to explain "why does my span have negative duration" than "why my spans have zero duration".
624
+ */
625
+ const dateTimestampSource = {
626
+ nowSeconds: () => Date.now() / 1000,
627
+ };
628
+
629
+ /**
630
+ * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
631
+ * for accessing a high-resolution monotonic clock.
632
+ */
633
+
634
+ /**
635
+ * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
636
+ * support the API.
637
+ *
638
+ * Wrapping the native API works around differences in behavior from different browsers.
639
+ */
640
+ function getBrowserPerformance() {
641
+ const { performance } = WINDOW;
642
+ if (!performance || !performance.now) {
643
+ return undefined;
428
644
  }
429
645
 
430
- return obj;
646
+ // Replace performance.timeOrigin with our own timeOrigin based on Date.now().
647
+ //
648
+ // This is a partial workaround for browsers reporting performance.timeOrigin such that performance.timeOrigin +
649
+ // performance.now() gives a date arbitrarily in the past.
650
+ //
651
+ // Additionally, computing timeOrigin in this way fills the gap for browsers where performance.timeOrigin is
652
+ // undefined.
653
+ //
654
+ // The assumption that performance.timeOrigin + performance.now() ~= Date.now() is flawed, but we depend on it to
655
+ // interact with data coming out of performance entries.
656
+ //
657
+ // Note that despite recommendations against it in the spec, browsers implement the Performance API with a clock that
658
+ // might stop when the computer is asleep (and perhaps under other circumstances). Such behavior causes
659
+ // performance.timeOrigin + performance.now() to have an arbitrary skew over Date.now(). In laptop computers, we have
660
+ // observed skews that can be as long as days, weeks or months.
661
+ //
662
+ // See https://github.com/getsentry/sentry-javascript/issues/2590.
663
+ //
664
+ // BUG: despite our best intentions, this workaround has its limitations. It mostly addresses timings of pageload
665
+ // transactions, but ignores the skew built up over time that can aversely affect timestamps of navigation
666
+ // transactions of long-lived web pages.
667
+ const timeOrigin = Date.now() - performance.now();
668
+
669
+ return {
670
+ now: () => performance.now(),
671
+ timeOrigin,
672
+ };
431
673
  }
432
674
 
433
- function getGitBranchHead() {
675
+ /**
676
+ * Returns the native Performance API implementation from Node.js. Returns undefined in old Node.js versions that don't
677
+ * implement the API.
678
+ */
679
+ function getNodePerformance() {
434
680
  try {
435
- return child_process.execSync("git rev-parse HEAD").toString().trim();
436
- } catch (e) {
437
- // no git installed
681
+ const perfHooks = dynamicRequire(module, 'perf_hooks') ;
682
+ return perfHooks.performance;
683
+ } catch (_) {
438
684
  return undefined;
439
685
  }
440
686
  }
441
687
 
442
- function getReleaseName(releaseName) {
443
- if (releaseName) {
444
- return releaseName;
445
- } // Env var SENTRY_RELEASE takes presendace over other env vars listed below
446
- // this is why we are looking for it before proceeding with others
688
+ /**
689
+ * The Performance API implementation for the current platform, if available.
690
+ */
691
+ const platformPerformance = isNodeEnv() ? getNodePerformance() : getBrowserPerformance();
692
+
693
+ const timestampSource =
694
+ platformPerformance === undefined
695
+ ? dateTimestampSource
696
+ : {
697
+ nowSeconds: () => (platformPerformance.timeOrigin + platformPerformance.now()) / 1000,
698
+ };
699
+
700
+ /**
701
+ * Returns a timestamp in seconds since the UNIX epoch using the Date API.
702
+ */
703
+ dateTimestampSource.nowSeconds.bind(dateTimestampSource);
704
+
705
+ /**
706
+ * Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
707
+ * availability of the Performance API.
708
+ *
709
+ * See `usingPerformanceAPI` to test whether the Performance API is used.
710
+ *
711
+ * BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
712
+ * asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
713
+ * skew can grow to arbitrary amounts like days, weeks or months.
714
+ * See https://github.com/getsentry/sentry-javascript/issues/2590.
715
+ */
716
+ timestampSource.nowSeconds.bind(timestampSource);
717
+
718
+ /**
719
+ * The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
720
+ * performance API is available.
721
+ */
722
+ (() => {
723
+ // Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
724
+ // performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
725
+ // data as reliable if they are within a reasonable threshold of the current time.
726
+
727
+ const { performance } = WINDOW;
728
+ if (!performance || !performance.now) {
729
+ return undefined;
730
+ }
731
+
732
+ const threshold = 3600 * 1000;
733
+ const performanceNow = performance.now();
734
+ const dateNow = Date.now();
735
+
736
+ // if timeOrigin isn't available set delta to threshold so it isn't used
737
+ const timeOriginDelta = performance.timeOrigin
738
+ ? Math.abs(performance.timeOrigin + performanceNow - dateNow)
739
+ : threshold;
740
+ const timeOriginIsReliable = timeOriginDelta < threshold;
741
+
742
+ // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
743
+ // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
744
+ // Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
745
+ // a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
746
+ // Date API.
747
+ // eslint-disable-next-line deprecation/deprecation
748
+ const navigationStart = performance.timing && performance.timing.navigationStart;
749
+ const hasNavigationStart = typeof navigationStart === 'number';
750
+ // if navigationStart isn't available set delta to threshold so it isn't used
751
+ const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
752
+ const navigationStartIsReliable = navigationStartDelta < threshold;
753
+
754
+ if (timeOriginIsReliable || navigationStartIsReliable) {
755
+ // Use the more reliable time origin
756
+ if (timeOriginDelta <= navigationStartDelta) {
757
+ return performance.timeOrigin;
758
+ } else {
759
+ return navigationStart;
760
+ }
761
+ }
762
+ return dateNow;
763
+ })();
764
+
765
+ /**
766
+ * Checks whether the given input is already an array, and if it isn't, wraps it in one.
767
+ *
768
+ * @param maybeArray Input to turn into an array, if necessary
769
+ * @returns The input, if already an array, or an array with the input as the only element, if not
770
+ */
771
+ function arrayify(maybeArray) {
772
+ return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
773
+ }
447
774
 
775
+ var SENTRY_SAAS_URL = "https://sentry.io";
776
+ function normalizeUserOptions(userOptions) {
777
+ var _userOptions$org, _userOptions$project, _ref, _userOptions$release, _ref2, _userOptions$url, _userOptions$finalize, _userOptions$cleanArt, _userOptions$dryRun, _userOptions$debug, _userOptions$silent, _userOptions$telemetr, _userOptions$injectRe, _ref3, _userOptions$customHe;
778
+
779
+ var options = {
780
+ // include is the only strictly required option
781
+ // (normalizeInclude needs all userOptions to access top-level include options)
782
+ include: normalizeInclude(userOptions),
783
+ // These options must be set b/c we need them for release injection.
784
+ // They can also be set as environment variables. Technically, they
785
+ // could be set in the config file but this would be too late for
786
+ // release injection because we only pass the config file path
787
+ // to the CLI
788
+ org: (_userOptions$org = userOptions.org) !== null && _userOptions$org !== void 0 ? _userOptions$org : process.env["SENTRY_ORG"],
789
+ project: (_userOptions$project = userOptions.project) !== null && _userOptions$project !== void 0 ? _userOptions$project : process.env["SENTRY_PROJECT"],
790
+ // Falling back to the empty string here b/c at a later point, we use
791
+ // Sentry CLI to determine a release if none was specified via options
792
+ // or env vars. In case we don't find one, we'll bail at that point.
793
+ release: (_ref = (_userOptions$release = userOptions.release) !== null && _userOptions$release !== void 0 ? _userOptions$release : process.env["SENTRY_RELEASE"]) !== null && _ref !== void 0 ? _ref : "",
794
+ // We technically don't need the URL for anything release-specific
795
+ // but we want to make sure that we're only sending Sentry data
796
+ // of SaaS customers. Hence we want to read it anyway.
797
+ url: (_ref2 = (_userOptions$url = userOptions.url) !== null && _userOptions$url !== void 0 ? _userOptions$url : process.env["SENTRY_URL"]) !== null && _ref2 !== void 0 ? _ref2 : SENTRY_SAAS_URL,
798
+ // Options with default values
799
+ finalize: (_userOptions$finalize = userOptions.finalize) !== null && _userOptions$finalize !== void 0 ? _userOptions$finalize : true,
800
+ cleanArtifacts: (_userOptions$cleanArt = userOptions.cleanArtifacts) !== null && _userOptions$cleanArt !== void 0 ? _userOptions$cleanArt : false,
801
+ dryRun: (_userOptions$dryRun = userOptions.dryRun) !== null && _userOptions$dryRun !== void 0 ? _userOptions$dryRun : false,
802
+ debug: (_userOptions$debug = userOptions.debug) !== null && _userOptions$debug !== void 0 ? _userOptions$debug : false,
803
+ silent: (_userOptions$silent = userOptions.silent) !== null && _userOptions$silent !== void 0 ? _userOptions$silent : false,
804
+ telemetry: (_userOptions$telemetr = userOptions.telemetry) !== null && _userOptions$telemetr !== void 0 ? _userOptions$telemetr : true,
805
+ injectReleasesMap: (_userOptions$injectRe = userOptions.injectReleasesMap) !== null && _userOptions$injectRe !== void 0 ? _userOptions$injectRe : false,
806
+ // These options and can also be set via env variables or the config file.
807
+ // If they're set in the options, we simply pass them to the CLI constructor.
808
+ // Sentry CLI will internally query env variables and read its config file if
809
+ // the passed options are undefined.
810
+ authToken: userOptions.authToken,
811
+ // env var: `SENTRY_AUTH_TOKEN`
812
+ // CLI v1 (and the "old" webpack plugin) use `CUSTOM_HEADER`,
813
+ // but CLI v2 uses `SENTRY_HEADER` (which is also better aligned with other naming)
814
+ // In the spirit of maximum compatibility, we allow both here.
815
+ customHeader: (_ref3 = (_userOptions$customHe = userOptions.customHeader) !== null && _userOptions$customHe !== void 0 ? _userOptions$customHe : process.env["SENTRY_HEADER"]) !== null && _ref3 !== void 0 ? _ref3 : process.env["CUSTOM_HEADER"],
816
+ vcsRemote: userOptions.vcsRemote,
817
+ // env var: `SENTRY_VSC_REMOTE`
818
+ // Optional options
819
+ setCommits: userOptions.setCommits,
820
+ deploy: userOptions.deploy,
821
+ entries: normalizeEntries(userOptions.entries),
822
+ dist: userOptions.dist,
823
+ errorHandler: userOptions.errorHandler,
824
+ configFile: userOptions.configFile
825
+ }; // We only want to enable telemetry for SaaS users
826
+ // This is not the final check (we need to call Sentry CLI at a later point)
827
+ // but we can already at this point make a first decision.
828
+ // @see `turnOffTelemetryForSelfHostedSentry` (telemetry.ts) for the second check.
829
+
830
+ options.telemetry = options.telemetry && options.url === SENTRY_SAAS_URL;
831
+ return options;
832
+ }
833
+ /**
834
+ * Converts the user-facing `entries` option to the internal `entries` option
835
+ */
448
836
 
449
- if (process.env["SENTRY_RELEASE"]) {
450
- return process.env["SENTRY_RELEASE"];
837
+ function normalizeEntries(userEntries) {
838
+ if (userEntries === undefined) {
839
+ return undefined;
840
+ } else if (typeof userEntries === "function") {
841
+ return userEntries;
842
+ } else {
843
+ return arrayify(userEntries);
451
844
  }
845
+ }
846
+ /**
847
+ * Converts the user-facing `include` option to the internal `include` option,
848
+ * resulting in an array of `InternalIncludeEntry` objects. This later on lets us
849
+ * work with only one type of include data structure instead of multiple.
850
+ *
851
+ * During the process, we hoist top-level include options (e.g. urlPrefix) into each
852
+ * object if they were not alrady specified in an `IncludeEntry`, making every object
853
+ * fully self-contained. This is also the reason why we pass the entire options
854
+ * object and not just `include`.
855
+ *
856
+ * @param userOptions the entire user-facing `options` object
857
+ *
858
+ * @return an array of `InternalIncludeEntry` objects.
859
+ */
860
+
861
+
862
+ function normalizeInclude(userOptions) {
863
+ return arrayify(userOptions.include).map(function (includeItem) {
864
+ return typeof includeItem === "string" ? {
865
+ paths: [includeItem]
866
+ } : includeItem;
867
+ }).map(function (userIncludeEntry) {
868
+ return normalizeIncludeEntry(userOptions, userIncludeEntry);
869
+ });
870
+ }
871
+ /**
872
+ * Besides array-ifying the `ignore` option, this function hoists top level options into the items of the `include`
873
+ * option. This is to simplify the handling of of the `include` items later on.
874
+ */
875
+
876
+
877
+ function normalizeIncludeEntry(userOptions, includeEntry) {
878
+ var _ref4, _includeEntry$ignore, _ref5, _includeEntry$ext, _includeEntry$ignoreF, _includeEntry$urlPref, _includeEntry$urlSuff, _includeEntry$stripPr, _ref6, _includeEntry$stripCo, _ref7, _includeEntry$sourceM, _ref8, _includeEntry$rewrite, _ref9, _includeEntry$validat;
879
+
880
+ var ignoreOption = (_ref4 = (_includeEntry$ignore = includeEntry.ignore) !== null && _includeEntry$ignore !== void 0 ? _includeEntry$ignore : userOptions.ignore) !== null && _ref4 !== void 0 ? _ref4 : ["node_modules"];
881
+ var ignore = Array.isArray(ignoreOption) ? ignoreOption : [ignoreOption]; // We're prefixing all entries in the `ext` option with a `.` (if it isn't already) to align with Node.js' `path.extname()`
452
882
 
453
- var ENV_VARS = ["SOURCE_VERSION", // Heroku #1 https://devcenter.heroku.com/changelog-items/630
454
- "HEROKU_SLUG_COMMIT", // Heroku #2: https://docs.sentry.io/product/integrations/deployment/heroku/#configure-releases
455
- "CODEBUILD_RESOLVED_SOURCE_VERSION", // AWS CodeBuild: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
456
- "CIRCLE_SHA1", // CircleCI: https://circleci.com/docs/2.0/env-vars/
457
- "VERCEL_GIT_COMMIT_SHA" // Vercel docs: https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables
458
- ];
459
- var releaseFromEnvironmentVar = ENV_VARS.find(function (key) {
460
- return Object.keys(process.env).includes(key);
883
+ var ext = (_ref5 = (_includeEntry$ext = includeEntry.ext) !== null && _includeEntry$ext !== void 0 ? _includeEntry$ext : userOptions.ext) !== null && _ref5 !== void 0 ? _ref5 : ["js", "map", "jsbundle", "bundle"];
884
+ var dotPrefixedExt = ext.map(function (extension) {
885
+ return ".".concat(extension.replace(/^\./, ""));
461
886
  });
887
+ return {
888
+ paths: includeEntry.paths,
889
+ ignore: ignore,
890
+ ignoreFile: (_includeEntry$ignoreF = includeEntry.ignoreFile) !== null && _includeEntry$ignoreF !== void 0 ? _includeEntry$ignoreF : userOptions.ignoreFile,
891
+ ext: dotPrefixedExt,
892
+ urlPrefix: (_includeEntry$urlPref = includeEntry.urlPrefix) !== null && _includeEntry$urlPref !== void 0 ? _includeEntry$urlPref : userOptions.urlPrefix,
893
+ urlSuffix: (_includeEntry$urlSuff = includeEntry.urlSuffix) !== null && _includeEntry$urlSuff !== void 0 ? _includeEntry$urlSuff : userOptions.urlSuffix,
894
+ stripPrefix: (_includeEntry$stripPr = includeEntry.stripPrefix) !== null && _includeEntry$stripPr !== void 0 ? _includeEntry$stripPr : userOptions.stripPrefix,
895
+ stripCommonPrefix: (_ref6 = (_includeEntry$stripCo = includeEntry.stripCommonPrefix) !== null && _includeEntry$stripCo !== void 0 ? _includeEntry$stripCo : userOptions.stripCommonPrefix) !== null && _ref6 !== void 0 ? _ref6 : false,
896
+ sourceMapReference: (_ref7 = (_includeEntry$sourceM = includeEntry.sourceMapReference) !== null && _includeEntry$sourceM !== void 0 ? _includeEntry$sourceM : userOptions.sourceMapReference) !== null && _ref7 !== void 0 ? _ref7 : true,
897
+ rewrite: (_ref8 = (_includeEntry$rewrite = includeEntry.rewrite) !== null && _includeEntry$rewrite !== void 0 ? _includeEntry$rewrite : userOptions.rewrite) !== null && _ref8 !== void 0 ? _ref8 : true,
898
+ validate: (_ref9 = (_includeEntry$validat = includeEntry.validate) !== null && _includeEntry$validat !== void 0 ? _includeEntry$validat : userOptions.validate) !== null && _ref9 !== void 0 ? _ref9 : false
899
+ };
900
+ }
901
+ /**
902
+ * Validates a few combinations of options that are not checked by Sentry CLI.
903
+ *
904
+ * For all other options, we can rely on Sentry CLI to validate them. In fact,
905
+ * we can't validate them in the plugin because Sentry CLI might pick up options from
906
+ * its config file.
907
+ *
908
+ * @param options the internal options
909
+ * @param logger the logger
910
+ *
911
+ * @returns `true` if the options are valid, `false` otherwise
912
+ */
913
+
462
914
 
463
- if (releaseFromEnvironmentVar) {
464
- return process.env[releaseFromEnvironmentVar];
915
+ function validateOptions(options, logger) {
916
+ if (options.injectReleasesMap && !options.org) {
917
+ logger.error("The `injectReleasesMap` option was set but it is only supported when the `org` option is also specified.", "Please set the `org` option (you can also set the SENTRY_ORG environment variable) or disable the `injectReleasesMap` option.");
918
+ return false;
465
919
  }
466
920
 
467
- var gitBranchHead = getGitBranchHead();
921
+ var setCommits = options.setCommits;
468
922
 
469
- if (gitBranchHead) {
470
- return gitBranchHead;
471
- } else {
472
- throw new Error("Could not return a release name");
923
+ if (setCommits) {
924
+ if (!setCommits.auto && !(setCommits.repo && setCommits.commit)) {
925
+ logger.error("The `setCommits` option was specified but is missing required properties.", "Please set either `auto` or both, `repo` and `commit`.");
926
+ return false;
927
+ }
928
+
929
+ if (setCommits.auto && setCommits.repo && setCommits) {
930
+ logger.warn("The `setCommits` options includes `auto` but also `repo` and `commit`.", "Ignoring `repo` and `commit`.", "Please only set either `auto` or both, `repo` and `commit`.");
931
+ }
932
+ }
933
+
934
+ if (options.deploy && !options.deploy.env) {
935
+ logger.error("The `deploy` option was specified but is missing the required `env` property.", "Please set the `env` property.");
936
+ return false;
473
937
  }
938
+
939
+ return true;
474
940
  }
475
941
 
476
- function makeSentryClient(dsn, telemetryEnabled, org) {
942
+ function makeSentryClient(dsn, telemetryEnabled) {
477
943
  var client = new NodeClient({
478
944
  dsn: dsn,
479
945
  enabled: telemetryEnabled,
480
946
  tracesSampleRate: telemetryEnabled ? 1.0 : 0.0,
481
947
  sampleRate: telemetryEnabled ? 1.0 : 0.0,
482
- release: "0.0.1-alpha.0",
948
+ release: "0.1.0",
483
949
  integrations: [new Integrations.Http({
484
950
  tracing: true
485
951
  })],
486
952
  tracePropagationTargets: ["sentry.io/api"],
487
953
  stackParser: defaultStackParser,
488
- transport: makeNodeTransport,
489
- debug: true
954
+ transport: makeNodeTransport
490
955
  });
491
- var hub = new Hub(client);
492
- hub.configureScope(function (scope) {
493
- if (org) {
494
- scope.setTag("org", org);
495
- }
496
- }); //TODO: This call is problematic because as soon as we set our hub as the current hub
956
+ var hub = new Hub(client); //TODO: This call is problematic because as soon as we set our hub as the current hub
497
957
  // we might interfere with other plugins that use Sentry. However, for now, we'll
498
958
  // leave it in because without it, we can't get distributed traces (which are pretty nice)
499
959
  // Let's keep it until someone complains about interference.
@@ -525,319 +985,135 @@ function addSpanToTransaction(ctx, op, description) {
525
985
  return span;
526
986
  }
527
987
  function captureMinimalError(error, hub) {
528
- var isAxiosError = error instanceof AxiosError;
529
- var sentryError = error instanceof Error ? {
530
- name: "".concat(isAxiosError && error.status ? error.status : "", ": ").concat(error.name),
531
- message: error.message,
532
- stack: error.stack
533
- } : {};
988
+ var sentryError;
989
+
990
+ if (error && _typeof(error) === "object") {
991
+ var e = error;
992
+ sentryError = {
993
+ name: e.name,
994
+ message: e.message,
995
+ stack: e.stack
996
+ };
997
+ } else {
998
+ sentryError = {
999
+ name: "Error",
1000
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
1001
+ message: "".concat(error)
1002
+ };
1003
+ }
1004
+
534
1005
  hub.captureException(sentryError);
535
1006
  }
1007
+ function addPluginOptionTags(options, hub) {
1008
+ var cleanArtifacts = options.cleanArtifacts,
1009
+ finalize = options.finalize,
1010
+ setCommits = options.setCommits,
1011
+ injectReleasesMap = options.injectReleasesMap,
1012
+ dryRun = options.dryRun,
1013
+ errorHandler = options.errorHandler,
1014
+ deploy = options.deploy,
1015
+ include = options.include;
1016
+ hub.setTag("include", include.length > 1 ? "multiple-entries" : "single-entry"); // Optional release pipeline steps
1017
+
1018
+ if (cleanArtifacts) {
1019
+ hub.setTag("clean-artifacts", true);
1020
+ }
536
1021
 
537
- var API_PATH = "/api/0";
538
- var USER_AGENT = "sentry-bundler-plugin/".concat("0.0.1-alpha.0");
539
-
540
- var sentryApiAxiosInstance = function sentryApiAxiosInstance(_ref) {
541
- var authToken = _ref.authToken,
542
- customHeaders = _ref.customHeaders;
543
- return axios.create({
544
- headers: _objectSpread2(_objectSpread2({}, customHeaders), {}, {
545
- "User-Agent": USER_AGENT,
546
- Authorization: "Bearer ".concat(authToken)
547
- })
548
- });
549
- };
1022
+ if (setCommits) {
1023
+ hub.setTag("set-commits", setCommits.auto === true ? "auto" : "manual");
1024
+ }
550
1025
 
551
- function createRelease(_x) {
552
- return _createRelease.apply(this, arguments);
553
- }
1026
+ if (finalize) {
1027
+ hub.setTag("finalize-release", true);
1028
+ }
554
1029
 
555
- function _createRelease() {
556
- _createRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref2) {
557
- var org, project, release, authToken, sentryUrl, sentryHub, customHeaders, requestUrl, releasePayload;
558
- return _regeneratorRuntime().wrap(function _callee$(_context) {
559
- while (1) {
560
- switch (_context.prev = _context.next) {
561
- case 0:
562
- org = _ref2.org, project = _ref2.project, release = _ref2.release, authToken = _ref2.authToken, sentryUrl = _ref2.sentryUrl, sentryHub = _ref2.sentryHub, customHeaders = _ref2.customHeaders;
563
- requestUrl = "".concat(sentryUrl).concat(API_PATH, "/organizations/").concat(org, "/releases/");
564
- releasePayload = {
565
- version: release,
566
- projects: [project],
567
- // we currently only support creating releases for a single project
568
- dateStarted: new Date(),
569
- dateReleased: new Date() //TODO: figure out if these dates are set correctly
1030
+ if (deploy) {
1031
+ hub.setTag("add-deploy", true);
1032
+ } // Miscelaneous options
570
1033
 
571
- };
572
- _context.prev = 3;
573
- _context.next = 6;
574
- return sentryApiAxiosInstance({
575
- authToken: authToken,
576
- customHeaders: customHeaders
577
- }).post(requestUrl, releasePayload, {
578
- headers: {
579
- Authorization: "Bearer ".concat(authToken)
580
- }
581
- });
582
1034
 
583
- case 6:
584
- _context.next = 12;
585
- break;
1035
+ if (dryRun) {
1036
+ hub.setTag("dry-run", true);
1037
+ }
586
1038
 
587
- case 8:
588
- _context.prev = 8;
589
- _context.t0 = _context["catch"](3);
590
- captureMinimalError(_context.t0, sentryHub);
591
- throw _context.t0;
1039
+ if (injectReleasesMap) {
1040
+ hub.setTag("inject-releases-map", true);
1041
+ }
592
1042
 
593
- case 12:
594
- case "end":
595
- return _context.stop();
596
- }
597
- }
598
- }, _callee, null, [[3, 8]]);
599
- }));
600
- return _createRelease.apply(this, arguments);
601
- }
1043
+ if (errorHandler) {
1044
+ hub.setTag("error-handler", "custom");
1045
+ }
602
1046
 
603
- function deleteAllReleaseArtifacts(_x2) {
604
- return _deleteAllReleaseArtifacts.apply(this, arguments);
1047
+ hub.setTag("node", process.version);
605
1048
  }
1049
+ /**
1050
+ * Makes a call to SentryCLI to get the Sentry server URL the CLI uses.
1051
+ *
1052
+ * We need to check and decide to use telemetry based on the CLI's respone to this call
1053
+ * because only at this time we checked a possibly existing .sentryclirc file. This file
1054
+ * could point to another URL than the default URL.
1055
+ */
606
1056
 
607
- function _deleteAllReleaseArtifacts() {
608
- _deleteAllReleaseArtifacts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref3) {
609
- var org, project, release, authToken, sentryUrl, sentryHub, customHeaders, requestUrl;
610
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
611
- while (1) {
612
- switch (_context2.prev = _context2.next) {
613
- case 0:
614
- org = _ref3.org, project = _ref3.project, release = _ref3.release, authToken = _ref3.authToken, sentryUrl = _ref3.sentryUrl, sentryHub = _ref3.sentryHub, customHeaders = _ref3.customHeaders;
615
- requestUrl = "".concat(sentryUrl).concat(API_PATH, "/projects/").concat(org, "/").concat(project, "/files/source-maps/?name=").concat(release);
616
- _context2.prev = 2;
617
- _context2.next = 5;
618
- return sentryApiAxiosInstance({
619
- authToken: authToken,
620
- customHeaders: customHeaders
621
- })["delete"](requestUrl, {
622
- headers: {
623
- Authorization: "Bearer ".concat(authToken)
624
- }
625
- });
626
-
627
- case 5:
628
- _context2.next = 11;
629
- break;
630
-
631
- case 7:
632
- _context2.prev = 7;
633
- _context2.t0 = _context2["catch"](2);
634
- captureMinimalError(_context2.t0, sentryHub);
635
- throw _context2.t0;
636
-
637
- case 11:
638
- case "end":
639
- return _context2.stop();
640
- }
641
- }
642
- }, _callee2, null, [[2, 7]]);
643
- }));
644
- return _deleteAllReleaseArtifacts.apply(this, arguments);
1057
+ function turnOffTelemetryForSelfHostedSentry(_x, _x2) {
1058
+ return _turnOffTelemetryForSelfHostedSentry.apply(this, arguments);
645
1059
  }
646
1060
 
647
- function updateRelease(_x3) {
648
- return _updateRelease.apply(this, arguments);
649
- }
1061
+ function _turnOffTelemetryForSelfHostedSentry() {
1062
+ _turnOffTelemetryForSelfHostedSentry = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(cli, hub) {
1063
+ var _cliInfo$split$, _cliInfo$split$$repla;
650
1064
 
651
- function _updateRelease() {
652
- _updateRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_ref4) {
653
- var release, org, authToken, sentryUrl, project, sentryHub, customHeaders, requestUrl, releasePayload;
654
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
1065
+ var cliInfo, url, client;
1066
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
655
1067
  while (1) {
656
- switch (_context3.prev = _context3.next) {
1068
+ switch (_context.prev = _context.next) {
657
1069
  case 0:
658
- release = _ref4.release, org = _ref4.org, authToken = _ref4.authToken, sentryUrl = _ref4.sentryUrl, project = _ref4.project, sentryHub = _ref4.sentryHub, customHeaders = _ref4.customHeaders;
659
- requestUrl = "".concat(sentryUrl).concat(API_PATH, "/projects/").concat(org, "/").concat(project, "/releases/").concat(release, "/");
660
- releasePayload = {
661
- dateReleased: new Date().toISOString()
662
- };
663
- _context3.prev = 3;
664
- _context3.next = 6;
665
- return sentryApiAxiosInstance({
666
- authToken: authToken,
667
- customHeaders: customHeaders
668
- }).put(requestUrl, releasePayload, {
669
- headers: {
670
- Authorization: "Bearer ".concat(authToken)
671
- }
672
- });
673
-
674
- case 6:
675
- _context3.next = 12;
676
- break;
677
-
678
- case 8:
679
- _context3.prev = 8;
680
- _context3.t0 = _context3["catch"](3);
681
- captureMinimalError(_context3.t0, sentryHub);
682
- throw _context3.t0;
1070
+ _context.next = 2;
1071
+ return cli.execute(["info"], false);
683
1072
 
684
- case 12:
685
- case "end":
686
- return _context3.stop();
687
- }
688
- }
689
- }, _callee3, null, [[3, 8]]);
690
- }));
691
- return _updateRelease.apply(this, arguments);
692
- }
1073
+ case 2:
1074
+ cliInfo = _context.sent;
1075
+ url = cliInfo === null || cliInfo === void 0 ? void 0 : (_cliInfo$split$ = cliInfo.split(/(\r\n|\n|\r)/)[0]) === null || _cliInfo$split$ === void 0 ? void 0 : (_cliInfo$split$$repla = _cliInfo$split$.replace(/^Sentry Server: /, "")) === null || _cliInfo$split$$repla === void 0 ? void 0 : _cliInfo$split$$repla.trim();
693
1076
 
694
- function uploadReleaseFile(_x4) {
695
- return _uploadReleaseFile.apply(this, arguments);
696
- }
1077
+ if (url !== SENTRY_SAAS_URL) {
1078
+ client = hub.getClient();
697
1079
 
698
- function _uploadReleaseFile() {
699
- _uploadReleaseFile = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(_ref5) {
700
- var org, project, release, authToken, sentryUrl, filename, fileContent, sentryHub, customHeaders, requestUrl, form;
701
- return _regeneratorRuntime().wrap(function _callee4$(_context4) {
702
- while (1) {
703
- switch (_context4.prev = _context4.next) {
704
- case 0:
705
- org = _ref5.org, project = _ref5.project, release = _ref5.release, authToken = _ref5.authToken, sentryUrl = _ref5.sentryUrl, filename = _ref5.filename, fileContent = _ref5.fileContent, sentryHub = _ref5.sentryHub, customHeaders = _ref5.customHeaders;
706
- requestUrl = "".concat(sentryUrl).concat(API_PATH, "/projects/").concat(org, "/").concat(project, "/releases/").concat(release, "/files/");
707
- form = new FormData();
708
- form.append("name", filename);
709
- form.append("file", Buffer.from(fileContent, "utf-8"), {
710
- filename: filename
711
- });
712
- _context4.prev = 5;
713
- _context4.next = 8;
714
- return sentryApiAxiosInstance({
715
- authToken: authToken,
716
- customHeaders: customHeaders
717
- }).post(requestUrl, form, {
718
- headers: {
719
- Authorization: "Bearer ".concat(authToken),
720
- "Content-Type": "multipart/form-data"
1080
+ if (client) {
1081
+ client.getOptions().enabled = false;
1082
+ client.getOptions().tracesSampleRate = 0;
1083
+ client.getOptions().sampleRate = 0;
721
1084
  }
722
- });
723
-
724
- case 8:
725
- _context4.next = 14;
726
- break;
727
-
728
- case 10:
729
- _context4.prev = 10;
730
- _context4.t0 = _context4["catch"](5);
731
- captureMinimalError(_context4.t0, sentryHub);
732
- throw _context4.t0;
1085
+ }
733
1086
 
734
- case 14:
1087
+ case 5:
735
1088
  case "end":
736
- return _context4.stop();
1089
+ return _context.stop();
737
1090
  }
738
1091
  }
739
- }, _callee4, null, [[5, 10]]);
1092
+ }, _callee);
740
1093
  }));
741
- return _uploadReleaseFile.apply(this, arguments);
742
- }
743
-
744
- function getFiles(path, allowedExtensions) {
745
- var includedFiles = getAllIncludedFileNames(path, allowedExtensions, []);
746
- return includedFiles.map(function (filename) {
747
- var content = fs.readFileSync(filename, {
748
- encoding: "utf-8"
749
- });
750
- return {
751
- name: "~" + filename.replace(new RegExp("^".concat(path)), ""),
752
- content: content
753
- };
754
- });
1094
+ return _turnOffTelemetryForSelfHostedSentry.apply(this, arguments);
755
1095
  }
756
1096
 
757
- function getAllIncludedFileNames(dirPath, allowedExtensions, accFiles) {
758
- var files = fs.readdirSync(dirPath);
759
- files.map(function (file) {
760
- return path.join(dirPath, "/", file);
761
- }).forEach(function (file) {
762
- if (fs.statSync(file).isDirectory()) {
763
- accFiles = accFiles.concat(getAllIncludedFileNames(file, allowedExtensions, accFiles));
764
- } else {
765
- if (allowedExtensions.some(function (e) {
766
- return file.endsWith(e);
767
- })) {
768
- accFiles.push(file);
769
- }
770
- }
771
- });
772
- return accFiles;
773
- }
774
-
775
- function createNewRelease(_x, _x2, _x3) {
1097
+ function createNewRelease(_x, _x2) {
776
1098
  return _createNewRelease.apply(this, arguments);
777
1099
  }
778
1100
 
779
1101
  function _createNewRelease() {
780
- _createNewRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(release, options, ctx) {
1102
+ _createNewRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(options, ctx) {
781
1103
  var span;
782
1104
  return _regeneratorRuntime().wrap(function _callee$(_context) {
783
1105
  while (1) {
784
1106
  switch (_context.prev = _context.next) {
785
1107
  case 0:
786
- span = addSpanToTransaction(ctx, "function.plugin.create_release"); // TODO: pull these checks out of here and simplify them
787
-
788
- if (!(options.authToken === undefined)) {
789
- _context.next = 6;
790
- break;
791
- }
792
-
793
- ctx.logger.warn('Missing "authToken" option. Will not create release.');
794
- return _context.abrupt("return", Promise.resolve("nothing to do here"));
795
-
796
- case 6:
797
- if (!(options.org === undefined)) {
798
- _context.next = 11;
799
- break;
800
- }
1108
+ span = addSpanToTransaction(ctx, "function.plugin.create_release");
1109
+ _context.next = 3;
1110
+ return ctx.cli.releases["new"](options.release);
801
1111
 
802
- ctx.logger.warn('Missing "org" option. Will not create release.');
803
- return _context.abrupt("return", Promise.resolve("nothing to do here"));
804
-
805
- case 11:
806
- if (!(options.url === undefined)) {
807
- _context.next = 16;
808
- break;
809
- }
810
-
811
- ctx.logger.warn('Missing "url" option. Will not create release.');
812
- return _context.abrupt("return", Promise.resolve("nothing to do here"));
813
-
814
- case 16:
815
- if (!(options.project === undefined)) {
816
- _context.next = 19;
817
- break;
818
- }
819
-
820
- ctx.logger.warn('Missing "project" option. Will not create release.');
821
- return _context.abrupt("return", Promise.resolve("nothing to do here"));
822
-
823
- case 19:
824
- _context.next = 21;
825
- return createRelease({
826
- release: release,
827
- authToken: options.authToken,
828
- org: options.org,
829
- project: options.project,
830
- sentryUrl: options.url,
831
- sentryHub: ctx.hub,
832
- customHeaders: options.customHeaders
833
- });
834
-
835
- case 21:
1112
+ case 3:
836
1113
  ctx.logger.info("Successfully created release.");
837
1114
  span === null || span === void 0 ? void 0 : span.finish();
838
- return _context.abrupt("return", Promise.resolve("nothing to do here"));
839
1115
 
840
- case 24:
1116
+ case 5:
841
1117
  case "end":
842
1118
  return _context.stop();
843
1119
  }
@@ -847,288 +1123,201 @@ function _createNewRelease() {
847
1123
  return _createNewRelease.apply(this, arguments);
848
1124
  }
849
1125
 
850
- function uploadSourceMaps(_x4, _x5, _x6) {
851
- return _uploadSourceMaps.apply(this, arguments);
1126
+ function cleanArtifacts(_x3, _x4) {
1127
+ return _cleanArtifacts.apply(this, arguments);
852
1128
  }
853
1129
 
854
- function _uploadSourceMaps() {
855
- _uploadSourceMaps = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(release, options, ctx) {
856
- var span, include, ext, org, project, authToken, url, fileExtensions, files;
1130
+ function _cleanArtifacts() {
1131
+ _cleanArtifacts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(options, ctx) {
1132
+ var span;
857
1133
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
858
1134
  while (1) {
859
1135
  switch (_context2.prev = _context2.next) {
860
1136
  case 0:
861
- span = addSpanToTransaction(ctx, "function.plugin.upload_sourcemaps"); // This is what Sentry CLI does:
862
- // TODO: 0. Preprocess source maps
863
- // - (Out of scope for now)
864
- // - For rewriting source maps see https://github.com/getsentry/rust-sourcemap/blob/master/src/types.rs#L763
865
- // TODO: 1. Creates a new release to make sure it exists
866
- // - can we assume that the release will exist b/c we don't give unplugin users the
867
- // option to skip this step?
868
- // TODO: 2. download already uploaded files and get their checksums
869
- // TODO: 3. identify new or changed files (by comparing checksums)
870
- // TODO: 4. upload new and changed files
871
- // - CLI asks API for chunk options https://github.com/getsentry/sentry-cli/blob/7b8466885d9cfd51aee6fdc041eca9f645026303/src/utils/file_upload.rs#L106-L112
872
- // - WTF?
873
- // - don't upload more than 20k files
874
- // - upload files concurrently
875
- // - 2 options: chunked upload (multiple files per chunk) or single file upload
876
-
877
- include = options.include, ext = options.ext, org = options.org, project = options.project, authToken = options.authToken, url = options.url; // TODO: pull these checks out of here and simplify them
878
-
879
- if (!(authToken === undefined)) {
880
- _context2.next = 7;
881
- break;
882
- }
883
-
884
- ctx.logger.warn('Missing "authToken" option. Will not create release.');
885
- return _context2.abrupt("return", Promise.resolve("nothing to do here"));
886
-
887
- case 7:
888
- if (!(org === undefined)) {
889
- _context2.next = 12;
1137
+ if (options.cleanArtifacts) {
1138
+ _context2.next = 3;
890
1139
  break;
891
1140
  }
892
1141
 
893
- ctx.logger.warn('Missing "org" option. Will not create release.');
894
- return _context2.abrupt("return", Promise.resolve("nothing to do here"));
895
-
896
- case 12:
897
- if (!(url === undefined)) {
898
- _context2.next = 17;
899
- break;
900
- }
1142
+ logger.debug("Skipping artifact cleanup.");
1143
+ return _context2.abrupt("return");
901
1144
 
902
- ctx.logger.warn('Missing "url" option. Will not create release.');
903
- return _context2.abrupt("return", Promise.resolve("nothing to do here"));
1145
+ case 3:
1146
+ span = addSpanToTransaction(ctx, "function.plugin.clean_artifacts");
1147
+ _context2.next = 6;
1148
+ return ctx.cli.releases.execute(["releases", "files", options.release, "delete", "--all"], true);
904
1149
 
905
- case 17:
906
- if (!(project === undefined)) {
907
- _context2.next = 20;
908
- break;
909
- }
1150
+ case 6:
1151
+ ctx.logger.info("Successfully cleaned previous artifacts.");
1152
+ span === null || span === void 0 ? void 0 : span.finish();
910
1153
 
911
- ctx.logger.warn('Missing "project" option. Will not create release.');
912
- return _context2.abrupt("return", Promise.resolve("nothing to do here"));
913
-
914
- case 20:
915
- ctx.logger.info("Uploading Sourcemaps."); //TODO: Remove this once we have internal options. this property must always be present
916
-
917
- fileExtensions = ext || [];
918
- files = getFiles(include, fileExtensions);
919
- ctx.logger.info("Found ".concat(files.length, " files to upload."));
920
- return _context2.abrupt("return", Promise.all(files.map(function (file) {
921
- return uploadReleaseFile({
922
- org: org,
923
- project: project,
924
- release: release,
925
- authToken: authToken,
926
- sentryUrl: url,
927
- filename: file.name,
928
- fileContent: file.content,
929
- sentryHub: ctx.hub,
930
- customHeaders: options.customHeaders
931
- });
932
- })).then(function () {
933
- ctx.logger.info("Successfully uploaded sourcemaps.");
934
- span === null || span === void 0 ? void 0 : span.finish();
935
- return "done";
936
- }));
937
-
938
- case 25:
1154
+ case 8:
939
1155
  case "end":
940
1156
  return _context2.stop();
941
1157
  }
942
1158
  }
943
1159
  }, _callee2);
944
1160
  }));
945
- return _uploadSourceMaps.apply(this, arguments);
1161
+ return _cleanArtifacts.apply(this, arguments);
946
1162
  }
947
1163
 
948
- function finalizeRelease(_x7, _x8, _x9) {
949
- return _finalizeRelease.apply(this, arguments);
1164
+ function uploadSourceMaps(_x5, _x6) {
1165
+ return _uploadSourceMaps.apply(this, arguments);
950
1166
  }
951
1167
 
952
- function _finalizeRelease() {
953
- _finalizeRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(release, options, ctx) {
954
- var span, authToken, org, url, project;
1168
+ function _uploadSourceMaps() {
1169
+ _uploadSourceMaps = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(options, ctx) {
1170
+ var span;
955
1171
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
956
1172
  while (1) {
957
1173
  switch (_context3.prev = _context3.next) {
958
1174
  case 0:
959
- span = addSpanToTransaction(ctx, "function.plugin.finalize_release");
960
-
961
- if (!options.finalize) {
962
- _context3.next = 9;
963
- break;
964
- }
965
-
966
- authToken = options.authToken, org = options.org, url = options.url, project = options.project;
967
-
968
- if (!(!authToken || !org || !url || !project)) {
969
- _context3.next = 6;
970
- break;
971
- }
972
-
973
- ctx.logger.warn("Missing required option. Will not clean existing artifacts.");
974
- return _context3.abrupt("return", Promise.resolve("nothing to do here"));
1175
+ span = addSpanToTransaction(ctx, "function.plugin.upload_sourcemaps");
1176
+ ctx.logger.info("Uploading Sourcemaps."); // Since our internal include entries contain all top-level sourcemaps options,
1177
+ // we only need to pass the include option here.
975
1178
 
976
- case 6:
977
- _context3.next = 8;
978
- return updateRelease({
979
- authToken: authToken,
980
- org: org,
981
- release: release,
982
- sentryUrl: url,
983
- project: project,
984
- sentryHub: ctx.hub,
985
- customHeaders: options.customHeaders
1179
+ _context3.next = 4;
1180
+ return ctx.cli.releases.uploadSourceMaps(options.release, {
1181
+ include: options.include
986
1182
  });
987
1183
 
988
- case 8:
989
- ctx.logger.info("Successfully finalized release.");
990
-
991
- case 9:
1184
+ case 4:
1185
+ ctx.logger.info("Successfully uploaded Sourcemaps.");
992
1186
  span === null || span === void 0 ? void 0 : span.finish();
993
- return _context3.abrupt("return", Promise.resolve("nothing to do here"));
994
1187
 
995
- case 11:
1188
+ case 6:
996
1189
  case "end":
997
1190
  return _context3.stop();
998
1191
  }
999
1192
  }
1000
1193
  }, _callee3);
1001
1194
  }));
1002
- return _finalizeRelease.apply(this, arguments);
1195
+ return _uploadSourceMaps.apply(this, arguments);
1003
1196
  }
1004
1197
 
1005
- function cleanArtifacts(_x10, _x11, _x12) {
1006
- return _cleanArtifacts.apply(this, arguments);
1007
- } // TODO: Stuff we worry about later:
1198
+ function setCommits(_x7, _x8) {
1199
+ return _setCommits.apply(this, arguments);
1200
+ }
1201
+
1202
+ function _setCommits() {
1203
+ _setCommits = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(options, ctx) {
1204
+ var span, _options$setCommits, auto, repo, commit, previousCommit, ignoreMissing, ignoreEmpty;
1008
1205
 
1009
- function _cleanArtifacts() {
1010
- _cleanArtifacts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(release, options, ctx) {
1011
- var span;
1012
1206
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
1013
1207
  while (1) {
1014
1208
  switch (_context4.prev = _context4.next) {
1015
1209
  case 0:
1016
- span = addSpanToTransaction(ctx, "function.plugin.clean_artifacts");
1017
-
1018
- if (!options.cleanArtifacts) {
1019
- _context4.next = 23;
1020
- break;
1021
- }
1022
-
1023
- if (!(options.authToken === undefined)) {
1024
- _context4.next = 7;
1025
- break;
1026
- }
1027
-
1028
- ctx.logger.warn('Missing "authToken" option. Will not clean existing artifacts.');
1029
- return _context4.abrupt("return", Promise.resolve("nothing to do here"));
1030
-
1031
- case 7:
1032
- if (!(options.org === undefined)) {
1033
- _context4.next = 12;
1034
- break;
1035
- }
1036
-
1037
- ctx.logger.warn('Missing "org" option. Will not clean existing artifacts.');
1038
- return _context4.abrupt("return", Promise.resolve("nothing to do here"));
1039
-
1040
- case 12:
1041
- if (!(options.url === undefined)) {
1042
- _context4.next = 17;
1210
+ if (options.setCommits) {
1211
+ _context4.next = 3;
1043
1212
  break;
1044
1213
  }
1045
1214
 
1046
- ctx.logger.warn('Missing "url" option. Will not clean existing artifacts.');
1047
- return _context4.abrupt("return", Promise.resolve("nothing to do here"));
1048
-
1049
- case 17:
1050
- if (!(options.project === undefined)) {
1051
- _context4.next = 20;
1052
- break;
1053
- }
1215
+ logger.debug("Skipping setting commits to release.");
1216
+ return _context4.abrupt("return");
1054
1217
 
1055
- ctx.logger.warn('Missing "project" option. Will not clean existing artifacts.');
1056
- return _context4.abrupt("return", Promise.resolve("nothing to do here"));
1057
-
1058
- case 20:
1059
- _context4.next = 22;
1060
- return deleteAllReleaseArtifacts({
1061
- authToken: options.authToken,
1062
- org: options.org,
1063
- release: release,
1064
- sentryUrl: options.url,
1065
- project: options.project,
1066
- sentryHub: ctx.hub,
1067
- customHeaders: options.customHeaders
1218
+ case 3:
1219
+ span = addSpanToTransaction(ctx, "function.plugin.set_commits");
1220
+ _options$setCommits = options.setCommits, auto = _options$setCommits.auto, repo = _options$setCommits.repo, commit = _options$setCommits.commit, previousCommit = _options$setCommits.previousCommit, ignoreMissing = _options$setCommits.ignoreMissing, ignoreEmpty = _options$setCommits.ignoreEmpty;
1221
+ _context4.next = 7;
1222
+ return ctx.cli.releases.setCommits(options.release, {
1223
+ commit: commit,
1224
+ previousCommit: previousCommit,
1225
+ repo: repo,
1226
+ auto: auto,
1227
+ ignoreMissing: ignoreMissing,
1228
+ ignoreEmpty: ignoreEmpty
1068
1229
  });
1069
1230
 
1070
- case 22:
1071
- ctx.logger.info("Successfully cleaned previous artifacts.");
1072
-
1073
- case 23:
1231
+ case 7:
1232
+ ctx.logger.info("Successfully set commits.");
1074
1233
  span === null || span === void 0 ? void 0 : span.finish();
1075
- return _context4.abrupt("return", Promise.resolve("nothing to do here"));
1076
1234
 
1077
- case 25:
1235
+ case 9:
1078
1236
  case "end":
1079
1237
  return _context4.stop();
1080
1238
  }
1081
1239
  }
1082
1240
  }, _callee4);
1083
1241
  }));
1084
- return _cleanArtifacts.apply(this, arguments);
1242
+ return _setCommits.apply(this, arguments);
1085
1243
  }
1086
1244
 
1087
- function setCommits(_x13) {
1088
- return _setCommits.apply(this, arguments);
1245
+ function finalizeRelease(_x9, _x10) {
1246
+ return _finalizeRelease.apply(this, arguments);
1089
1247
  }
1090
1248
 
1091
- function _setCommits() {
1092
- _setCommits = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(
1093
- /* version: string, */
1094
- ctx) {
1249
+ function _finalizeRelease() {
1250
+ _finalizeRelease = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(options, ctx) {
1095
1251
  var span;
1096
1252
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
1097
1253
  while (1) {
1098
1254
  switch (_context5.prev = _context5.next) {
1099
1255
  case 0:
1100
- span = addSpanToTransaction(ctx, "function.plugin.set_commits");
1101
- span === null || span === void 0 ? void 0 : span.finish();
1102
- return _context5.abrupt("return", Promise.resolve("Noop"));
1256
+ if (options.finalize) {
1257
+ _context5.next = 3;
1258
+ break;
1259
+ }
1260
+
1261
+ logger.debug("Skipping release finalization.");
1262
+ return _context5.abrupt("return");
1103
1263
 
1104
1264
  case 3:
1265
+ span = addSpanToTransaction(ctx, "function.plugin.finalize_release");
1266
+ _context5.next = 6;
1267
+ return ctx.cli.releases.finalize(options.release);
1268
+
1269
+ case 6:
1270
+ ctx.logger.info("Successfully finalized release.");
1271
+ span === null || span === void 0 ? void 0 : span.finish();
1272
+
1273
+ case 8:
1105
1274
  case "end":
1106
1275
  return _context5.stop();
1107
1276
  }
1108
1277
  }
1109
1278
  }, _callee5);
1110
1279
  }));
1111
- return _setCommits.apply(this, arguments);
1280
+ return _finalizeRelease.apply(this, arguments);
1112
1281
  }
1113
1282
 
1114
- function addDeploy(_x14) {
1283
+ function addDeploy(_x11, _x12) {
1115
1284
  return _addDeploy.apply(this, arguments);
1116
1285
  }
1117
1286
 
1118
1287
  function _addDeploy() {
1119
- _addDeploy = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(
1120
- /* version: string, */
1121
- ctx) {
1122
- var span;
1288
+ _addDeploy = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(options, ctx) {
1289
+ var span, _options$deploy, env, started, finished, time, name, url;
1290
+
1123
1291
  return _regeneratorRuntime().wrap(function _callee6$(_context6) {
1124
1292
  while (1) {
1125
1293
  switch (_context6.prev = _context6.next) {
1126
1294
  case 0:
1127
- span = addSpanToTransaction(ctx, "function.plugin.add_deploy");
1128
- span === null || span === void 0 ? void 0 : span.finish();
1129
- return _context6.abrupt("return", Promise.resolve("Noop"));
1295
+ if (options.deploy) {
1296
+ _context6.next = 3;
1297
+ break;
1298
+ }
1299
+
1300
+ logger.debug("Skipping adding deploy info to release.");
1301
+ return _context6.abrupt("return");
1130
1302
 
1131
1303
  case 3:
1304
+ span = addSpanToTransaction(ctx, "function.plugin.deploy");
1305
+ _options$deploy = options.deploy, env = _options$deploy.env, started = _options$deploy.started, finished = _options$deploy.finished, time = _options$deploy.time, name = _options$deploy.name, url = _options$deploy.url;
1306
+ _context6.next = 7;
1307
+ return ctx.cli.releases.newDeploy(options.release, {
1308
+ env: env,
1309
+ started: started,
1310
+ finished: finished,
1311
+ time: time,
1312
+ name: name,
1313
+ url: url
1314
+ });
1315
+
1316
+ case 7:
1317
+ ctx.logger.info("Successfully added deploy.");
1318
+ span === null || span === void 0 ? void 0 : span.finish();
1319
+
1320
+ case 9:
1132
1321
  case "end":
1133
1322
  return _context6.stop();
1134
1323
  }
@@ -1149,69 +1338,166 @@ function createLogger(options) {
1149
1338
 
1150
1339
  return {
1151
1340
  info: function info(message) {
1152
- if (!(options !== null && options !== void 0 && options.silent)) {
1341
+ if (!options.silent) {
1342
+ var _console;
1343
+
1344
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1345
+ params[_key - 1] = arguments[_key];
1346
+ }
1347
+
1153
1348
  // eslint-disable-next-line no-console
1154
- console.log("".concat(options.prefix, " ").concat(message));
1349
+ (_console = console).log.apply(_console, ["".concat(options.prefix, " Info: ").concat(message)].concat(params));
1155
1350
  }
1156
1351
 
1157
1352
  addBreadcrumb("info", message);
1158
1353
  },
1159
1354
  warn: function warn(message) {
1160
- if (!(options !== null && options !== void 0 && options.silent)) {
1355
+ if (!options.silent) {
1356
+ var _console2;
1357
+
1358
+ for (var _len2 = arguments.length, params = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1359
+ params[_key2 - 1] = arguments[_key2];
1360
+ }
1361
+
1161
1362
  // eslint-disable-next-line no-console
1162
- console.log("".concat(options.prefix, " Warning! ").concat(message));
1363
+ (_console2 = console).log.apply(_console2, ["".concat(options.prefix, " Warning: ").concat(message)].concat(params));
1163
1364
  }
1164
1365
 
1165
1366
  addBreadcrumb("warning", message);
1166
1367
  },
1167
1368
  error: function error(message) {
1168
- if (!(options !== null && options !== void 0 && options.silent)) {
1369
+ if (!options.silent) {
1370
+ var _console3;
1371
+
1372
+ for (var _len3 = arguments.length, params = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
1373
+ params[_key3 - 1] = arguments[_key3];
1374
+ }
1375
+
1169
1376
  // eslint-disable-next-line no-console
1170
- console.log("".concat(options.prefix, " Error: ").concat(message));
1377
+ (_console3 = console).log.apply(_console3, ["".concat(options.prefix, " Error: ").concat(message)].concat(params));
1171
1378
  }
1172
1379
 
1173
1380
  addBreadcrumb("error", message);
1381
+ },
1382
+ debug: function debug(message) {
1383
+ if (!options.silent && options.debug) {
1384
+ var _console4;
1385
+
1386
+ for (var _len4 = arguments.length, params = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
1387
+ params[_key4 - 1] = arguments[_key4];
1388
+ }
1389
+
1390
+ // eslint-disable-next-line no-console
1391
+ (_console4 = console).log.apply(_console4, ["".concat(options.prefix, " Debug: ").concat(message)].concat(params));
1392
+ }
1393
+
1394
+ addBreadcrumb("debug", message);
1395
+ }
1396
+ };
1397
+ }
1398
+
1399
+ /**
1400
+ * Creates a new Sentry CLI instance.
1401
+ *
1402
+ * In case, users selected the `dryRun` options, this returns a stub
1403
+ * that makes no-ops out of most CLI operations
1404
+ */
1405
+ function getSentryCli(internalOptions, logger) {
1406
+ var silent = internalOptions.silent,
1407
+ org = internalOptions.org,
1408
+ project = internalOptions.project,
1409
+ authToken = internalOptions.authToken,
1410
+ url = internalOptions.url,
1411
+ vcsRemote = internalOptions.vcsRemote,
1412
+ customHeader = internalOptions.customHeader,
1413
+ dist = internalOptions.dist;
1414
+ var cli = new SentryCli(internalOptions.configFile, {
1415
+ url: url,
1416
+ authToken: authToken,
1417
+ org: org,
1418
+ project: project,
1419
+ vcsRemote: vcsRemote,
1420
+ dist: dist,
1421
+ silent: silent,
1422
+ customHeader: customHeader
1423
+ });
1424
+
1425
+ if (internalOptions.dryRun) {
1426
+ logger.info("In DRY RUN Mode");
1427
+ return getDryRunCLI(cli, logger);
1428
+ }
1429
+
1430
+ return cli;
1431
+ }
1432
+
1433
+ function getDryRunCLI(cli, logger) {
1434
+ return {
1435
+ releases: {
1436
+ proposeVersion: function proposeVersion() {
1437
+ return cli.releases.proposeVersion().then(function (version) {
1438
+ logger.info("Proposed version:\n", version);
1439
+ return version;
1440
+ });
1441
+ },
1442
+ "new": function _new(release) {
1443
+ logger.info("Creating new release:\n", release);
1444
+ return Promise.resolve(release);
1445
+ },
1446
+ uploadSourceMaps: function uploadSourceMaps(release, config) {
1447
+ logger.info("Calling upload-sourcemaps with:\n", config);
1448
+ return Promise.resolve(release);
1449
+ },
1450
+ finalize: function finalize(release) {
1451
+ logger.info("Finalizing release:\n", release);
1452
+ return Promise.resolve(release);
1453
+ },
1454
+ setCommits: function setCommits(release, config) {
1455
+ logger.info("Calling set-commits with:\n", config);
1456
+ return Promise.resolve(release);
1457
+ },
1458
+ newDeploy: function newDeploy(release, config) {
1459
+ logger.info("Calling deploy with:\n", config);
1460
+ return Promise.resolve(release);
1461
+ },
1462
+ execute: function execute(args, live) {
1463
+ logger.info("Executing", args, "live:", live);
1464
+ return Promise.resolve("");
1465
+ }
1466
+ },
1467
+ execute: function execute(args, live) {
1468
+ logger.info("Executing", args, "live:", live);
1469
+ return Promise.resolve("Executed");
1174
1470
  }
1175
1471
  };
1176
1472
  }
1177
1473
 
1178
- var defaultOptions = {
1179
- //TODO: add default options here as we port over options from the webpack plugin
1180
- // validate: false
1181
- debug: false,
1182
- cleanArtifacts: false,
1183
- finalize: true,
1184
- url: "https://sentry.io",
1185
- ext: ["js", "map", "jsbundle", "bundle"],
1186
- telemetry: true
1187
- }; // We prefix the polyfill id with \0 to tell other plugins not to try to load or transform it.
1474
+ // We prefix the polyfill id with \0 to tell other plugins not to try to load or transform it.
1188
1475
  // This hack is taken straight from https://rollupjs.org/guide/en/#resolveid.
1189
1476
  // This probably doesn't work for all bundlers but for rollup it does.
1190
-
1191
1477
  var RELEASE_INJECTOR_ID = "\0sentry-release-injector";
1192
1478
  /**
1193
- * The sentry-unplugin concerns itself with two things:
1479
+ * The sentry bundler plugin concerns itself with two things:
1194
1480
  * - Release injection
1195
1481
  * - Sourcemaps upload
1196
1482
  *
1197
1483
  * Release injection:
1198
1484
  *
1199
- * Per default the sentry-unpugin will inject a global `SENTRY_RELEASE` variable into the entrypoint of all bundles. On
1200
- * a technical level this is done by appending an import (`import "sentry-release-injector;"`) to all entrypoint files
1201
- * of the user code (see `transformInclude` and `transform` hooks). This import is then resolved by the sentry-unplugin
1485
+ * Per default the sentry bundler plugin will inject a global `SENTRY_RELEASE` variable into the entrypoint of all bundles.
1486
+ * On a technical level this is done by appending an import (`import "sentry-release-injector;"`) to all entrypoint files
1487
+ * of the user code (see `transformInclude` and `transform` hooks). This import is then resolved by the sentry plugin
1202
1488
  * to a virtual module that sets the global variable (see `resolveId` and `load` hooks).
1203
1489
  *
1204
1490
  * The resulting output approximately looks like this:
1205
1491
  *
1206
1492
  * ```text
1207
1493
  * entrypoint1.js (user file)
1208
- * ┌───────────────────┐ ┌─────────────────────────────────────────────────┐
1209
- * │ │ import { myFunction } from "./my-library.js"; │
1210
- * │ sentry-unplugin │ │
1211
- * │ │ const myResult = myFunction(); │
1212
- * └---------│---------┘ │ export { myResult }; │
1494
+ * ┌─────────────────────────┐ ┌─────────────────────────────────────────────────┐
1495
+ * │ │ import { myFunction } from "./my-library.js"; │
1496
+ * │ sentry-bundler-plugin │ │
1497
+ * │ │ const myResult = myFunction(); │
1498
+ * └---------│--------------- │ export { myResult }; │
1213
1499
  * │ │ │
1214
- * │ injects │ // injected by sentry-unplugin
1500
+ * │ injects │ // injected by sentry plugin
1215
1501
  * ├───────────────────► import "sentry-release-injector"; ─────────────────────┐
1216
1502
  * │ └─────────────────────────────────────────────────┘ │
1217
1503
  * │ │
@@ -1222,7 +1508,7 @@ var RELEASE_INJECTOR_ID = "\0sentry-release-injector";
1222
1508
  * │ │ return "Hello world!"; │ │
1223
1509
  * │ │ } │ │
1224
1510
  * │ │ │ │
1225
- * │ injects │ // injected by sentry-unplugin │ │
1511
+ * │ injects │ // injected by sentry plugin │ │
1226
1512
  * └───────────────────► import "sentry-release-injector"; ─────────────────────┤
1227
1513
  * └─────────────────────────────────────────────────┘ │
1228
1514
  * │
@@ -1230,7 +1516,7 @@ var RELEASE_INJECTOR_ID = "\0sentry-release-injector";
1230
1516
  * sentry-release-injector │
1231
1517
  * ┌──────────────────────────────────┐ │
1232
1518
  * │ │ is resolved │
1233
- * │ global.SENTRY_RELEASE = { ... } │ by unplugin
1519
+ * │ global.SENTRY_RELEASE = { ... } │ by plugin
1234
1520
  * │ // + a little more logic │<─────────────────────┘
1235
1521
  * │ │ (only once)
1236
1522
  * └──────────────────────────────────┘
@@ -1238,37 +1524,51 @@ var RELEASE_INJECTOR_ID = "\0sentry-release-injector";
1238
1524
  *
1239
1525
  * Source maps upload:
1240
1526
  *
1241
- * The sentry-unplugin will also take care of uploading source maps to Sentry. This is all done in the `buildEnd` hook.
1242
- * TODO: elaborate a bit on how sourcemaps upload works
1527
+ * The sentry bundler plugin will also take care of uploading source maps to Sentry. This is all done in the
1528
+ * `writeBundle` hook. In this hook the sentry plugin will execute the release creation pipeline:
1529
+ *
1530
+ * 1. Create a new release
1531
+ * 2. Delete already uploaded artifacts for this release (if `cleanArtifacts` is enabled)
1532
+ * 3. Upload sourcemaps based on `include` and source-map-specific options
1533
+ * 4. Associate a range of commits with the release (if `setCommits` is specified)
1534
+ * 5. Finalize the release (unless `finalize` is disabled)
1535
+ * 6. Add deploy information to the release (if `deploy` is specified)
1536
+ *
1537
+ * This release creation pipeline relies on Sentry CLI to execute the different steps.
1243
1538
  */
1244
1539
 
1245
- var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1246
- var options = _objectSpread2(_objectSpread2({}, defaultOptions), originalOptions); //TODO: We can get rid of this variable once we have internal plugin options
1247
-
1540
+ var unplugin = createUnplugin(function (options, unpluginMetaContext) {
1541
+ var internalOptions = normalizeUserOptions(options);
1248
1542
 
1249
- var telemetryEnabled = options.telemetry === true;
1250
-
1251
- var _makeSentryClient = makeSentryClient("https://4c2bae7d9fbc413e8f7385f55c515d51@o1.ingest.sentry.io/6690737", telemetryEnabled, options.org),
1543
+ var _makeSentryClient = makeSentryClient("https://4c2bae7d9fbc413e8f7385f55c515d51@o1.ingest.sentry.io/6690737", internalOptions.telemetry),
1252
1544
  sentryHub = _makeSentryClient.hub;
1253
1545
 
1546
+ addPluginOptionTags(internalOptions, sentryHub);
1254
1547
  var logger = createLogger({
1255
1548
  hub: sentryHub,
1256
1549
  prefix: "[sentry-".concat(unpluginMetaContext.framework, "-plugin]"),
1257
- silent: options.silent
1550
+ silent: internalOptions.silent,
1551
+ debug: internalOptions.debug
1258
1552
  });
1259
1553
 
1260
- if (telemetryEnabled) {
1554
+ if (!validateOptions(internalOptions, logger)) {
1555
+ handleError(new Error("Options were not set correctly. See output above for more details."), logger, internalOptions.errorHandler);
1556
+ }
1557
+
1558
+ var cli = getSentryCli(internalOptions, logger);
1559
+
1560
+ if (internalOptions.telemetry) {
1261
1561
  logger.info("Sending error and performance telemetry data to Sentry.");
1262
1562
  logger.info("To disable telemetry, set `options.telemetry` to `false`.");
1263
1563
  }
1264
1564
 
1265
1565
  sentryHub.setTags({
1266
- organization: options.org,
1267
- project: options.project,
1566
+ organization: internalOptions.org,
1567
+ project: internalOptions.project,
1268
1568
  bundler: unpluginMetaContext.framework
1269
1569
  });
1270
1570
  sentryHub.setUser({
1271
- id: options.org
1571
+ id: internalOptions.org
1272
1572
  }); // This is `nonEntrypointSet` instead of `entrypointSet` because this set is filled in the `resolveId` hook and there
1273
1573
  // we don't have guaranteed access to *absolute* paths of files if they're entrypoints. For non-entrypoints we're
1274
1574
  // guaranteed to have absolute paths - we're then using the paths in later hooks to make decisions about whether a
@@ -1286,15 +1586,50 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1286
1586
  * Responsible for starting the plugin execution transaction and the release injection span
1287
1587
  */
1288
1588
  buildStart: function buildStart() {
1289
- transaction = sentryHub.startTransaction({
1290
- op: "function.plugin",
1291
- name: "Sentry Bundler Plugin execution"
1292
- });
1293
- releaseInjectionSpan = addSpanToTransaction({
1294
- hub: sentryHub,
1295
- parentSpan: transaction,
1296
- logger: logger
1297
- }, "function.plugin.inject_release", "Release injection");
1589
+ return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
1590
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
1591
+ while (1) {
1592
+ switch (_context.prev = _context.next) {
1593
+ case 0:
1594
+ _context.next = 2;
1595
+ return turnOffTelemetryForSelfHostedSentry(cli, sentryHub);
1596
+
1597
+ case 2:
1598
+ if (internalOptions.release) {
1599
+ _context.next = 6;
1600
+ break;
1601
+ }
1602
+
1603
+ _context.next = 5;
1604
+ return cli.releases.proposeVersion();
1605
+
1606
+ case 5:
1607
+ internalOptions.release = _context.sent;
1608
+
1609
+ case 6:
1610
+ // At this point, we either have determined a release or we have to bail
1611
+ if (!internalOptions.release) {
1612
+ handleError(new Error("Unable to determine a release name. Make sure to set the `release` option or use an environment that supports auto-detection https://docs.sentry.io/cli/releases/#creating-releases`"), logger, internalOptions.errorHandler, sentryHub);
1613
+ }
1614
+
1615
+ transaction = sentryHub.startTransaction({
1616
+ op: "function.plugin",
1617
+ name: "Sentry Bundler Plugin execution"
1618
+ });
1619
+ releaseInjectionSpan = addSpanToTransaction({
1620
+ hub: sentryHub,
1621
+ parentSpan: transaction,
1622
+ logger: logger,
1623
+ cli: cli
1624
+ }, "function.plugin.inject_release", "Release injection");
1625
+
1626
+ case 9:
1627
+ case "end":
1628
+ return _context.stop();
1629
+ }
1630
+ }
1631
+ }, _callee);
1632
+ }))();
1298
1633
  },
1299
1634
 
1300
1635
  /**
@@ -1348,7 +1683,10 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1348
1683
 
1349
1684
  if (id === RELEASE_INJECTOR_ID) {
1350
1685
  return generateGlobalInjectorCode({
1351
- release: getReleaseName(options.release)
1686
+ release: internalOptions.release,
1687
+ injectReleasesMap: internalOptions.injectReleasesMap,
1688
+ org: internalOptions.org,
1689
+ project: internalOptions.project
1352
1690
  });
1353
1691
  } else {
1354
1692
  return undefined;
@@ -1356,11 +1694,11 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1356
1694
  },
1357
1695
 
1358
1696
  /**
1359
- * This hook determines whether we want to transform a module. In the unplugin we want to transform every entrypoint
1697
+ * This hook determines whether we want to transform a module. In the sentry bundler plugin we want to transform every entrypoint
1360
1698
  * unless configured otherwise with the `entries` option.
1361
1699
  *
1362
1700
  * @param id Always the absolute (fully resolved) path to the module.
1363
- * @returns `true` or `false` depending on whether we want to transform the module. For the sentry-unplugin we only
1701
+ * @returns `true` or `false` depending on whether we want to transform the module. For the sentry bundler plugin we only
1364
1702
  * want to transform the release injector file.
1365
1703
  */
1366
1704
  transformInclude: function transformInclude(id) {
@@ -1369,14 +1707,13 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1369
1707
  level: "info"
1370
1708
  });
1371
1709
 
1372
- if (options.entries) {
1710
+ if (internalOptions.entries) {
1373
1711
  // If there's an `entries` option transform (ie. inject the release varible) when the file path matches the option.
1374
- if (typeof options.entries === "function") {
1375
- return options.entries(id);
1712
+ if (typeof internalOptions.entries === "function") {
1713
+ return internalOptions.entries(id);
1376
1714
  }
1377
1715
 
1378
- var arrayifiedEntriesOption = Array.isArray(options.entries) ? options.entries : [options.entries];
1379
- return arrayifiedEntriesOption.some(function (entry) {
1716
+ return internalOptions.entries.some(function (entry) {
1380
1717
  if (entry instanceof RegExp) {
1381
1718
  return entry.test(id);
1382
1719
  } else {
@@ -1426,63 +1763,50 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1426
1763
  * Responsible for executing the sentry release creation pipeline (i.e. creating a release on
1427
1764
  * Sentry.io, uploading sourcemaps, associating commits and deploys and finalizing the release)
1428
1765
  */
1429
- buildEnd: function buildEnd() {
1766
+ writeBundle: function writeBundle() {
1430
1767
  var _releaseInjectionSpan;
1431
1768
 
1432
1769
  (_releaseInjectionSpan = releaseInjectionSpan) === null || _releaseInjectionSpan === void 0 ? void 0 : _releaseInjectionSpan.finish();
1433
1770
  var releasePipelineSpan = transaction && addSpanToTransaction({
1434
1771
  hub: sentryHub,
1435
1772
  parentSpan: transaction,
1436
- logger: logger
1773
+ logger: logger,
1774
+ cli: cli
1437
1775
  }, "function.plugin.release", "Release pipeline");
1438
- var release = getReleaseName(options.release);
1439
1776
  sentryHub.addBreadcrumb({
1440
- category: "buildEnd:start",
1777
+ category: "writeBundle:start",
1441
1778
  level: "info"
1442
- }); //TODO:
1443
- // 1. validate options to see if we get a valid include property, release name, etc.
1444
- // 2. normalize the include property: Users can pass string | string [] | IncludeEntry[].
1445
- // That's good for them but a hassle for us. Let's try to normalize this into one data type
1446
- // (I vote IncludeEntry[]) and continue with that down the line
1447
-
1779
+ });
1448
1780
  var ctx = {
1449
1781
  hub: sentryHub,
1450
1782
  parentSpan: releasePipelineSpan,
1451
- logger: logger
1783
+ logger: logger,
1784
+ cli: cli
1452
1785
  };
1453
- createNewRelease(release, options, ctx).then(function () {
1454
- return cleanArtifacts(release, options, ctx);
1786
+ createNewRelease(internalOptions, ctx).then(function () {
1787
+ return cleanArtifacts(internalOptions, ctx);
1788
+ }).then(function () {
1789
+ return uploadSourceMaps(internalOptions, ctx);
1455
1790
  }).then(function () {
1456
- return uploadSourceMaps(release, options, ctx);
1791
+ return setCommits(internalOptions, ctx);
1457
1792
  }).then(function () {
1458
- return setCommits(ctx);
1459
- }) // this is a noop for now
1460
- .then(function () {
1461
- return finalizeRelease(release, options, ctx);
1793
+ return finalizeRelease(internalOptions, ctx);
1794
+ }).then(function () {
1795
+ return addDeploy(internalOptions, ctx);
1462
1796
  }).then(function () {
1463
- return addDeploy(ctx);
1464
- }) // this is a noop for now
1465
- .then(function () {
1466
1797
  var _transaction;
1467
1798
 
1468
- (_transaction = transaction) === null || _transaction === void 0 ? void 0 : _transaction.setStatus("ok");
1799
+ return (_transaction = transaction) === null || _transaction === void 0 ? void 0 : _transaction.setStatus("ok");
1469
1800
  })["catch"](function (e) {
1470
1801
  var _transaction2;
1471
1802
 
1472
- captureMinimalError(e, sentryHub);
1473
1803
  (_transaction2 = transaction) === null || _transaction2 === void 0 ? void 0 : _transaction2.setStatus("cancelled");
1474
- logger.error(e.message);
1475
-
1476
- if (options.errorHandler) {
1477
- options.errorHandler(e);
1478
- } else {
1479
- throw e;
1480
- }
1804
+ handleError(e, logger, internalOptions.errorHandler, sentryHub);
1481
1805
  })["finally"](function () {
1482
1806
  var _transaction3;
1483
1807
 
1484
1808
  sentryHub.addBreadcrumb({
1485
- category: "buildEnd:finish",
1809
+ category: "writeBundle:finish",
1486
1810
  level: "info"
1487
1811
  });
1488
1812
  releasePipelineSpan === null || releasePipelineSpan === void 0 ? void 0 : releasePipelineSpan.finish();
@@ -1491,16 +1815,41 @@ var unplugin = createUnplugin(function (originalOptions, unpluginMetaContext) {
1491
1815
  }
1492
1816
  };
1493
1817
  });
1818
+
1819
+ function handleError(error, logger, errorHandler, sentryHub) {
1820
+ logger.error(error.message);
1821
+
1822
+ if (sentryHub) {
1823
+ captureMinimalError(error, sentryHub);
1824
+ }
1825
+
1826
+ if (errorHandler) {
1827
+ errorHandler(error);
1828
+ } else {
1829
+ throw error;
1830
+ }
1831
+ }
1494
1832
  /**
1495
1833
  * Generates code for the "sentry-release-injector" which is responsible for setting the global `SENTRY_RELEASE`
1496
1834
  * variable.
1497
1835
  */
1498
1836
 
1837
+
1499
1838
  function generateGlobalInjectorCode(_ref2) {
1500
- var release = _ref2.release;
1839
+ var release = _ref2.release,
1840
+ injectReleasesMap = _ref2.injectReleasesMap,
1841
+ org = _ref2.org,
1842
+ project = _ref2.project;
1501
1843
  // The code below is mostly ternary operators because it saves bundle size.
1502
1844
  // The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
1503
- return "\n var _global =\n typeof window !== 'undefined' ?\n window :\n typeof global !== 'undefined' ?\n global :\n typeof self !== 'undefined' ?\n self :\n {};\n\n _global.SENTRY_RELEASE={id:\"".concat(release, "\"};");
1845
+ var code = "\n var _global =\n typeof window !== 'undefined' ?\n window :\n typeof global !== 'undefined' ?\n global :\n typeof self !== 'undefined' ?\n self :\n {};\n\n _global.SENTRY_RELEASE={id:\"".concat(release, "\"};");
1846
+
1847
+ if (injectReleasesMap && project) {
1848
+ var key = org ? "".concat(project, "@").concat(org) : project;
1849
+ code += "\n _global.SENTRY_RELEASES=_global.SENTRY_RELEASES || {};\n _global.SENTRY_RELEASES[\"".concat(key, "\"]={id:\"").concat(release, "\"};\n ");
1850
+ }
1851
+
1852
+ return code;
1504
1853
  } // eslint-disable-next-line @typescript-eslint/no-explicit-any
1505
1854
 
1506
1855