• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

teaxyz / lib / 5256840863

pending completion
5256840863

push

github

mxcl
Download to `.incomplete` before atomic rename

496 of 646 branches covered (76.78%)

Branch coverage included in aggregate %.

9 of 9 new or added lines in 1 file covered. (100.0%)

119 existing lines in 9 files now uncovered.

2111 of 2447 relevant lines covered (86.27%)

20988.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.88
/src/utils/error.ts
1
import { is_what, outdent, PlainObject } from "../deps.ts"
24✔
2
const { isPlainObject, isRegExp, isString } = is_what
24✔
3
const undent = outdent.default
24✔
4
import * as pkg from "./pkg.ts"
24✔
5

6
type ID =
7
  'not-found: tea -X: arg0' |
8
  'not-found: exe/md: default target' |
9
  'not-found: exe/md: region' |
10
  'not-found: pkg.version' |
11
  'http' |
12
  'not-found: pantry' |
13
  'not-found: pantry: package.yml' |
14
  'parser: pantry: package.yml' |
15
  'not-found: dev-env' |
16
  // 'not-found: srcroot' |
17
  'not-found: arg' |
18
  '#helpwanted' |
19
  'confused: interpreter'
20

21
export default class TeaError extends Error {
24✔
22
  id: ID
38✔
23
  ctx: PlainObject
38✔
24

25
  code() {
38✔
26
    // starting at 3 ∵ https://tldp.org/LDP/abs/html/exitcodes.html
46✔
27
    // https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6/+/refs/heads/tools_r20/sysroot/usr/include/sysexits.h
46✔
28
    switch (this.id) {
46✔
29
      case 'not-found: tea -X: arg0': return 'spilt-tea-003'
94✔
30
      case 'not-found: exe/md: default target': return 'spilt-tea-004'
×
UNCOV
31
      case 'not-found: exe/md: region': return 'spilt-tea-005'
×
32
      case 'not-found: pkg.version': return 'spilt-tea-006'
94✔
33
      case 'not-found: pantry: package.yml': return 'spilt-tea-007'
94✔
34
      case 'not-found: dev-env': return 'spilt-tea-008'
×
35
      case 'not-found: pantry': return 'spilt-tea-009'
×
36
      case 'not-found: arg': return 'spilt-tea-010'
×
37
      case 'parser: pantry: package.yml': return 'spilt-tea-011'
×
UNCOV
38
      case '#helpwanted': return 'spilt-tea-012'
×
39
      case 'http': return 'spilt-tea-013'
94✔
40
      case 'confused: interpreter': return 'spilt-tea-14'
×
41
    default: {
×
42
      const exhaustiveness_check: never = this.id
×
UNCOV
43
      throw new Error(`unhandled id: ${exhaustiveness_check}`)
×
44
    }}
46✔
45
  }
46✔
46

47
  title() {
38✔
48
    switch (this.id) {
42✔
49
    case 'not-found: pantry: package.yml':
42✔
50
      return `not found in pantry: ${this.ctx.project}`
44✔
51
    default:
42✔
52
      return this.id
44✔
53
    }
42✔
54
  }
42✔
55

56
  constructor(id: ID, ctx: PlainObject) {
38✔
57
    let msg = ''
52✔
58
    switch (id) {
52✔
59
    case 'not-found: tea -X: arg0':
52✔
60
      msg = undent`
54✔
61
        couldn’t find a pkg to provide: \`${ctx.arg0}\`
54✔
62

63
            https://github.com/teaxyz/pantry#contributing
64

65
        `
54✔
66
        break
54✔
67
    case 'not-found: exe/md: region':
×
68
      msg = `markdown section for \`${ctx.script}\` has no \`\`\`sh code block`
×
69
      break
×
70
    case 'not-found: exe/md: default target':
×
71
      if (ctx.requirementsFile) {
×
72
        msg = `markdown section \`# Getting Started\` not found in \`${ctx.requirementsFile}\``
×
73
      } else {
×
UNCOV
74
        msg = undent`
×
75
          no \`README.md\` or \`package.json\` found.
76
          `
×
77
      }
×
UNCOV
78
      break
×
79
    case 'not-found: pantry':
52✔
80
      if (ctx.path) {
56✔
81
        msg = `no pantry at path: ${ctx.path}, try \`tea --sync\``
56✔
82
      } else {
×
83
        msg = 'no pantry: run `tea --sync`'
×
UNCOV
84
      }
×
85
      break
56✔
86
    case 'http':
52✔
UNCOV
87
      msg = ctx.cause?.message ?? "unknown HTTP error"
×
88
      break
54✔
89
    case 'not-found: pantry: package.yml':
52✔
90
      msg = undent`
54✔
91
        Not in pantry: ${ctx.project}
54✔
92

93
        https://github.com/teaxyz/pantry#contributing
94
        `
54✔
95
      break
54✔
96
    case 'parser: pantry: package.yml':
×
UNCOV
97
      msg = undent`
×
98
        pantry entry invalid. please report this bug!
99

100
            https://github.com/teaxyz/pantry/issues/new
101

102
        ----------------------------------------------------->> attachment begin
UNCOV
103
        ${ctx.project}: ${ctx.cause?.message}
×
104
        <<------------------------------------------------------- attachment end
105
        `
×
106
      break
×
107
    case 'not-found: dev-env':
×
108
      msg = undent`
×
UNCOV
109
        \`${ctx.cwd}\` is not a developer environment.
×
110

111
        a developer environment requires the presence of a file or directory
112
        that uniquely identifies package requirements, eg. \`package.json\`.
113
        `
×
114
    break
×
115
    case 'not-found: arg':
×
116
      msg = undent`
×
UNCOV
117
       \`${ctx.arg}\` isn't a valid flag.
×
118

119
       see: \`tea --help\`
120
       `
×
121
      break
×
122
    case '#helpwanted':
×
123
      msg = ctx.details
×
UNCOV
124
      break
×
125
    case 'not-found: pkg.version': {
108✔
UNCOV
126
      const str = ctx.pkg ? pkg.str(ctx.pkg) : 'this version'
×
127
      msg = undent`
56✔
128
        we haven’t packaged ${str}. but we will… *if* you open a ticket:
56✔
129

130
            https://github.com/teaxyz/pantry/issues/new
131
        `
56✔
132
    } break
112✔
133
    case 'confused: interpreter':
×
UNCOV
134
      msg = undent`
×
135
        we’re not sure what to do with this file ¯\\_(ツ)_/¯
136
        `
×
137
      break
×
138
    default: {
×
139
      const exhaustiveness_check: never = id
×
UNCOV
140
      throw new Error(`unhandled id: ${exhaustiveness_check}`)
×
141
    }}
52✔
142

143
    const opts: {cause: unknown} = {cause: ctx.cause}
156✔
144

145
    super(msg)
52✔
146
    //super(msg, opts) //FIXME this should be fine but `dnt` complains
52✔
147

148
    this.cause = opts.cause
52✔
149
    //^^ FIXME shouldn't need to do this step
52✔
150

UNCOV
151
    this.id = id ?? msg
×
152
    this.ctx = ctx
52✔
153
  }
52✔
154
}
38✔
155

156
export function panic(message?: string): never {
24✔
157
  throw new Error(message)
26✔
158
}
26✔
159

160
export const wrap = <T extends Array<unknown>, U>(fn: (...args: T) => U, id: ID) => {
24✔
161
  return (...args: T): U => {
58✔
162
    try {
264✔
163
      let foo = fn(...args)
264✔
164
      if (foo instanceof Promise) {
264✔
165
        foo = foo.catch(converter) as U
466✔
166
      }
466✔
167
      return foo
466✔
168
    } catch (cause) {
264✔
169
      converter(cause)
268✔
170
    }
268✔
171

172
    function converter(cause: unknown): never {
264✔
173
      if (cause instanceof TeaError) {
268✔
174
        throw cause
270✔
175
      } else {
270✔
176
        throw new TeaError(id, {...args, cause})
1,080✔
177
      }
270✔
178
    }
268✔
179
  }
58✔
180
}
24✔
181

182

183
declare global {
184
  interface Promise<T> {
185
    swallow(err?: unknown): Promise<T | undefined>
186
  }
187
}
188

189
Promise.prototype.swallow = function(gristle?: unknown) {
24✔
190
  return this.catch((err: unknown) => {
6,888✔
191
    if (gristle === undefined) {
×
192
      return
×
UNCOV
193
    }
×
194

195
    if (err instanceof TeaError) {
×
196
      err = err.id
×
UNCOV
197
    } else if (err instanceof Error) {
×
198
      err = err.message
7,504✔
199
    } else if (isPlainObject(err) && isString(err.code)) {
×
200
      err = err.code
×
201
    } else if (isRegExp(gristle) && isString(err)) {
×
202
      if (!err.match(gristle)) throw err
×
203
    } else if (err !== gristle) {
×
204
      throw err
×
UNCOV
205
    }
×
206
    return undefined
7,504✔
207
  })
6,888✔
208
}
24✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc