Source: core/base-service/errors.js

  1. /**
  2. * Standard exceptions for handling error cases
  3. *
  4. * @module
  5. */
  6. /**
  7. * Base error class
  8. *
  9. * @abstract
  10. */
  11. class ShieldsRuntimeError extends Error {
  12. /**
  13. * Name of the class. Implementations of ShieldsRuntimeError
  14. * should override this method.
  15. *
  16. * @type {string}
  17. */
  18. get name() {
  19. return 'ShieldsRuntimeError'
  20. }
  21. /**
  22. * Default message for this exception if none is specified.
  23. * Implementations of ShieldsRuntimeError should implement this method.
  24. *
  25. * @abstract
  26. * @type {string}
  27. */
  28. get defaultPrettyMessage() {
  29. throw new Error('Must implement abstract method')
  30. }
  31. /**
  32. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  33. * Refer to individual attrs
  34. * @param {string} message Exception message for debug purposes
  35. */
  36. constructor(props = {}, message) {
  37. super(message)
  38. this.prettyMessage = props.prettyMessage || this.defaultPrettyMessage
  39. if (props.underlyingError) {
  40. this.stack = props.underlyingError.stack
  41. }
  42. this.cacheSeconds = props.cacheSeconds
  43. }
  44. }
  45. const defaultNotFoundError = 'not found'
  46. /**
  47. * Throw this to wrap a 404 or other 'not found' response from an upstream API
  48. */
  49. class NotFound extends ShieldsRuntimeError {
  50. get name() {
  51. return 'NotFound'
  52. }
  53. get defaultPrettyMessage() {
  54. return defaultNotFoundError
  55. }
  56. /**
  57. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  58. * Refer to individual attrs
  59. */
  60. constructor(props = {}) {
  61. const prettyMessage = props.prettyMessage || defaultNotFoundError
  62. const message =
  63. prettyMessage === defaultNotFoundError
  64. ? 'Not Found'
  65. : `Not Found: ${prettyMessage}`
  66. super(props, message)
  67. this.response = props.response
  68. }
  69. }
  70. /**
  71. * Throw this to wrap an invalid or unexpected response from an upstream API
  72. */
  73. class InvalidResponse extends ShieldsRuntimeError {
  74. get name() {
  75. return 'InvalidResponse'
  76. }
  77. get defaultPrettyMessage() {
  78. return 'invalid'
  79. }
  80. /**
  81. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  82. * Refer to individual attrs
  83. */
  84. constructor(props = {}) {
  85. const message = props.underlyingError
  86. ? `Invalid Response: ${props.underlyingError.message}`
  87. : 'Invalid Response'
  88. super(props, message)
  89. this.response = props.response
  90. }
  91. }
  92. /**
  93. * Throw this if we can't contact an upstream API
  94. * or to wrap a 5XX response
  95. */
  96. class Inaccessible extends ShieldsRuntimeError {
  97. get name() {
  98. return 'Inaccessible'
  99. }
  100. get defaultPrettyMessage() {
  101. return 'inaccessible'
  102. }
  103. /**
  104. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  105. * Refer to individual attrs
  106. */
  107. constructor(props = {}) {
  108. const message = props.underlyingError
  109. ? `Inaccessible: ${props.underlyingError.message}`
  110. : 'Inaccessible'
  111. super(props, message)
  112. this.response = props.response
  113. }
  114. }
  115. /**
  116. * Throw this error when required credentials are missing
  117. */
  118. class ImproperlyConfigured extends ShieldsRuntimeError {
  119. get name() {
  120. return 'ImproperlyConfigured'
  121. }
  122. get defaultPrettyMessage() {
  123. return 'improperly configured'
  124. }
  125. /**
  126. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  127. * Refer to individual attrs
  128. */
  129. constructor(props = {}) {
  130. const message = props.underlyingError
  131. ? `ImproperlyConfigured: ${props.underlyingError.message}`
  132. : 'ImproperlyConfigured'
  133. super(props, message)
  134. this.response = props.response
  135. }
  136. }
  137. /**
  138. * Throw this error when a user supplied input or parameter
  139. * is invalid or unexpected
  140. */
  141. class InvalidParameter extends ShieldsRuntimeError {
  142. get name() {
  143. return 'InvalidParameter'
  144. }
  145. get defaultPrettyMessage() {
  146. return 'invalid parameter'
  147. }
  148. /**
  149. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  150. * Refer to individual attrs
  151. */
  152. constructor(props = {}) {
  153. const message = props.underlyingError
  154. ? `Invalid Parameter: ${props.underlyingError.message}`
  155. : 'Invalid Parameter'
  156. super(props, message)
  157. this.response = props.response
  158. }
  159. }
  160. /**
  161. * Throw this error to indicate that a service is deprecated or removed
  162. */
  163. class Deprecated extends ShieldsRuntimeError {
  164. get name() {
  165. return 'Deprecated'
  166. }
  167. get defaultPrettyMessage() {
  168. return 'no longer available'
  169. }
  170. /**
  171. * @param {module:core/base-service/errors~RuntimeErrorProps} props
  172. * Refer to individual attrs
  173. */
  174. constructor(props) {
  175. const message = 'Deprecated'
  176. super(props, message)
  177. }
  178. }
  179. /**
  180. * @typedef {object} RuntimeErrorProps
  181. * @property {Error} underlyingError Exception we are wrapping (Optional)
  182. * @property {object} response Response from an upstream API to provide
  183. * context for the error (Optional)
  184. * @property {string} prettyMessage User-facing error message to override the
  185. * value of `defaultPrettyMessage()`. This is the text that will appear on the
  186. * badge when we catch and render the exception (Optional)
  187. * @property {number} cacheSeconds Length of time to cache this error response
  188. * for. Defaults to the cacheLength of the service class throwing the error
  189. * (Optional)
  190. */
  191. export {
  192. ShieldsRuntimeError,
  193. NotFound,
  194. ImproperlyConfigured,
  195. InvalidResponse,
  196. Inaccessible,
  197. InvalidParameter,
  198. Deprecated,
  199. }