dsn.js
  1  import { logger } from './logger.js';
  2  
  3  /** Regular expression used to parse a Dsn. */
  4  const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/;
  5  
  6  function isValidProtocol(protocol) {
  7    return protocol === 'http' || protocol === 'https';
  8  }
  9  
 10  /**
 11   * Renders the string representation of this Dsn.
 12   *
 13   * By default, this will render the public representation without the password
 14   * component. To get the deprecated private representation, set `withPassword`
 15   * to true.
 16   *
 17   * @param withPassword When set to true, the password will be included.
 18   */
 19  function dsnToString(dsn, withPassword = false) {
 20    const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
 21    return (
 22      `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
 23      `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`
 24    );
 25  }
 26  
 27  /**
 28   * Parses a Dsn from a given string.
 29   *
 30   * @param str A Dsn as string
 31   * @returns Dsn as DsnComponents or undefined if @param str is not a valid DSN string
 32   */
 33  function dsnFromString(str) {
 34    const match = DSN_REGEX.exec(str);
 35  
 36    if (!match) {
 37      // This should be logged to the console
 38      // eslint-disable-next-line no-console
 39      console.error(`Invalid Sentry Dsn: ${str}`);
 40      return undefined;
 41    }
 42  
 43    const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
 44    let path = '';
 45    let projectId = lastPath;
 46  
 47    const split = projectId.split('/');
 48    if (split.length > 1) {
 49      path = split.slice(0, -1).join('/');
 50      projectId = split.pop() ;
 51    }
 52  
 53    if (projectId) {
 54      const projectMatch = projectId.match(/^\d+/);
 55      if (projectMatch) {
 56        projectId = projectMatch[0];
 57      }
 58    }
 59  
 60    return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol , publicKey });
 61  }
 62  
 63  function dsnFromComponents(components) {
 64    return {
 65      protocol: components.protocol,
 66      publicKey: components.publicKey || '',
 67      pass: components.pass || '',
 68      host: components.host,
 69      port: components.port || '',
 70      path: components.path || '',
 71      projectId: components.projectId,
 72    };
 73  }
 74  
 75  function validateDsn(dsn) {
 76    if (!(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
 77      return true;
 78    }
 79  
 80    const { port, projectId, protocol } = dsn;
 81  
 82    const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId'];
 83    const hasMissingRequiredComponent = requiredComponents.find(component => {
 84      if (!dsn[component]) {
 85        logger.error(`Invalid Sentry Dsn: ${component} missing`);
 86        return true;
 87      }
 88      return false;
 89    });
 90  
 91    if (hasMissingRequiredComponent) {
 92      return false;
 93    }
 94  
 95    if (!projectId.match(/^\d+$/)) {
 96      logger.error(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
 97      return false;
 98    }
 99  
100    if (!isValidProtocol(protocol)) {
101      logger.error(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
102      return false;
103    }
104  
105    if (port && isNaN(parseInt(port, 10))) {
106      logger.error(`Invalid Sentry Dsn: Invalid port ${port}`);
107      return false;
108    }
109  
110    return true;
111  }
112  
113  /**
114   * Creates a valid Sentry Dsn object, identifying a Sentry instance and project.
115   * @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source
116   */
117  function makeDsn(from) {
118    const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
119    if (!components || !validateDsn(components)) {
120      return undefined;
121    }
122    return components;
123  }
124  
125  export { dsnFromString, dsnToString, makeDsn };
126  //# sourceMappingURL=dsn.js.map