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

DanielXMoore / Civet / 17922990240

22 Sep 2025 05:14PM UTC coverage: 91.589% (-0.02%) from 91.607%
17922990240

Pull #1799

github

web-flow
Merge 25770f64b into cc949c4b0
Pull Request #1799: Global configuration of operators via `operators`

3691 of 4019 branches covered (91.84%)

Branch coverage included in aggregate %.

48 of 52 new or added lines in 2 files covered. (92.31%)

45 existing lines in 3 files now uncovered.

18925 of 20674 relevant lines covered (91.54%)

16484.76 hits per line

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

35.4
/source/cli.civet
1
{ compile, generate, parse, lib, isCompileError, SourceMap } from ./main.civet
1✔
2
type { ASTError, BlockStatement, ParseError, ParseErrors } from ./main.civet
1✔
3
{ findConfig, loadConfig } from ./config.civet
1✔
4

1✔
5
// unplugin ends up getting installed in the same dist directory
1✔
6
{rawPlugin} from ./unplugin/unplugin.civet
1✔
7
let unplugin:
1✔
8
  buildStart: () => Promise<void>
1✔
9
  buildEnd: (this: {emitFile: (data: {source: string, fileName: string, type: string}) => void}, useConfigFileNames?: boolean) => Promise<void>
1✔
10
  load: (this: {addWatchFile: (filename: string) => void}, filename: string) => Promise<{code: string, map: unknown}>
1✔
11

1✔
12
export function version: Promise<string>
×
13
  // Once import assertions (with form) are universal, we can switch to this:
×
14
  //import package from "../package.json" with type: "json"
×
15
  //package.version
×
16
  if import.meta.url  // ESM mode (e.g. testing)
×
17
    { createRequire } from node:module
×
18
    createRequire(import.meta.url)('../package.json').version
×
19
  else
×
20
    require('../package.json').version
×
21

1✔
22
encoding .= "utf8" as BufferEncoding
1✔
23

1✔
24
fs from node:fs/promises
1✔
25
type { Stats } from node:fs
1✔
26
path from node:path
1✔
27

1✔
28
// TODO: Once the types are exported within the Civet source code,
1✔
29
// we should import them directly here, instead of looking at an old release.
1✔
30
type { CompileOptions } from @danielx/civet
1✔
31

1✔
32
export interface Options extends CompileOptions
1✔
33
  version?: boolean
1✔
34
  help?: boolean
1✔
35
  run?: boolean
1✔
36
  compile?: boolean
1✔
37
  output?: string
1✔
38
  outputDir?: string
1✔
39
  outputExt?: string
1✔
40
  outputPath?: path.ParsedPath
1✔
41
  eval?: string
1✔
42
  config?: string | false | undefined
1✔
43
  ast?: boolean | "raw"
1✔
44
  repl?: boolean
1✔
45
  typecheck?: boolean
1✔
46
  emitDeclaration?: boolean
1✔
47
  typescript?: boolean
1✔
48

1✔
49
export interface ParsedArgs
1✔
50
  filenames: string[]
1✔
51
  scriptArgs: string[]
1✔
52
  options: Options
1✔
53

1✔
54
export function parseArgs(args: string[], isTTY = process.stdin.isTTY): Promise<ParsedArgs>
54✔
55
  options: Options := {}
54✔
56
  isRun := => not (or)
54✔
57
    options.ast
60✔
58
    options.compile
59✔
59
    options.typecheck
42✔
60
    options.emitDeclaration
39✔
61
  filenames: string[] .= []
54✔
62
  scriptArgs: string[] .= []
54✔
63

54✔
64
  options.version = true if args.includes '-version'
54✔
65
  options.help = true if args.includes '-help'
54✔
66
  return {filenames, scriptArgs, options} if options.version or options.help
54✔
67

52✔
68
  i .= 0
52✔
69
  errors .= 0
52✔
70
  function endOfArgs(j: number): void
52✔
71
    i = args.length  // trigger end of loop
×
72
    return if j >= args.length  // no more args
×
73
    if options.run
×
74
      filenames.push args[j]
×
75
      scriptArgs = args[j+1..]
×
76
    else
×
77
      filenames.push ...args[j..]
×
78
  while i < args.length
52✔
79
    arg := args[i]
66✔
80
    // Split -ab into -a -b
66✔
81
    if /^-\w{2,}$/.test arg
66✔
82
      args[i..i] =
1✔
83
        for each char of arg[1..]
1✔
84
          `-${char}`
2✔
85
      continue
1✔
86
    // Main argument handling
65✔
87
    switch arg
65✔
88
      when '-v', '--version'
2✔
89
        options.version = true
2✔
90
      when '-h', '--help'
3✔
91
        options.help = true
3✔
92
      when '-c', '--compile'
8✔
93
        options.compile = true
8✔
94
      when '-o', '--output'
16✔
95
        options.output = args[++i]
16✔
96
      when '-e', '--eval'
66✔
97
        options.eval = args[++i]
2✔
98
      when '--config'
66✔
99
        options.config = args[++i]
1✔
100
      when '--no-config'
66✔
101
        options.config = false
1✔
102
      when '--civet'
66✔
103
        Object.assign options.parseOptions ??= {},
5✔
104
          parse `civet ${args[++i]}`,
5✔
105
            startRule: 'CivetPrologueContent'
5✔
106
            filename: '--civet argument'
5✔
107
          |> .config
5✔
108
      when '--comptime'
66✔
109
        (options.parseOptions ??= {}).comptime = true
3✔
110
      when '--no-comptime'
66✔
111
        (options.parseOptions ??= {}).comptime = false
3✔
112
      when '--ast'
66✔
113
        options.ast = true
1✔
114
      when '--no-cache'
66✔
115
        options.noCache = true
1✔
116
      when '--inline-map'
66✔
117
        options.inlineMap = true
1✔
118
      when '--js'
66✔
119
        options.js = true
1✔
120
      when '--hits'
66✔
121
        options.hits = args[++i]
1✔
122
      when '--trace'
66✔
123
        options.trace = args[++i]
1✔
124
      when '--typecheck'
66✔
125
        options.typecheck = true
3✔
126
      when '--emit-declaration', '--emitDeclaration'
4✔
127
        options.emitDeclaration = true
4✔
128
      when '--'
66!
129
        endOfArgs ++i  // remaining arguments are filename and/or arguments
66✔
130
      else
66✔
131
        if arg.startsWith('-') and arg is not '-'
8!
132
          console.error `Invalid command-line argument: ${arg}`
×
133
          errors++
×
134
        else if (options.run = isRun())
8✔
135
          endOfArgs i  // remaining arguments are arguments to the script
8!
136
        else
8✔
137
          filenames.push arg
8✔
138
    i++
65✔
139

52✔
140
  options.typescript = true if options.typecheck or options.emitDeclaration
54✔
141

52✔
142
  unless filenames.length or options.typescript or options.eval
54✔
143
    if isTTY
41✔
144
      options.repl = true
40✔
145
    else
1✔
146
      // When piped, default to old behavior of transpiling stdin to stdout
1✔
147
      options.compile = true
1✔
148
      options.run = false
1✔
149
      filenames = ['-']
1✔
150

52✔
151
  // Parse `output` option into forced directory, extension, and/or full path
52✔
152
  if options.output and options.output is not '-'
54✔
153
    optionsPath := path.parse options.output
14✔
154
    let stat: Stats | null
14✔
155
    try
14✔
156
      stat = await fs.stat options.output
2✔
157
    catch
14✔
158
      stat = null
12✔
159
    if stat?.isDirectory() or options.output.endsWith(path.sep) or
14✔
160
                              options.output.endsWith('/')
10✔
161
      // -o dir writes outputs into that directory with default name
4✔
162
      options.outputDir = options.output
4✔
163
    else if /^(\.[^]+)+$/.test optionsPath.base
10✔
164
      // -o .js or .ts or .civet.js or .civet.ts etc. to control extension
6✔
165
      options.outputExt = optionsPath.base
6✔
166
      // Can also be prefixed by a directory name
6✔
167
      options.outputDir = optionsPath.dir if optionsPath.dir
6✔
168
    else
4✔
169
      // -o filename fully specifies the output filename
4✔
170
      // (don't use this with multiple input files)
4✔
171
      options.outputPath = optionsPath
4✔
172
      options.outputExt = optionsPath.ext
4✔
173
  // For CLI compilations, default to rewriting imports to output extension,
54✔
174
  // with .jsx instead of .tsx to satisfy TypeScript.
54✔
175
  (options.parseOptions ??= {}).rewriteCivetImports ??=
54✔
176
    options.outputExt ?? '.civet.jsx'
54✔
177

54✔
178
  process.exit Math.min 255, errors if errors
54!
179
  options.run = isRun()
52✔
180
  {filenames, scriptArgs, options}
52✔
181

1✔
182
type ReadFile = (
1✔
183
  filename: string
1✔
184
  stdin: boolean
1✔
185
  content?: string
1✔
186
  error?: unknown
1✔
187
) & ((content: string) | (error: unknown))
1✔
188

1✔
189
function readFiles(filenames: string[], evalString?: string): AsyncGenerator<ReadFile>
×
190
  if evalString?
×
191
    yield
×
192
      filename: '<eval>'
×
193
      content: evalString + '\n'
×
194
      stdin: true
×
195

×
196
  for each let filename of filenames
×
197
    stdin := filename is '-'
×
198
    try
×
199
      let content: string
×
200
      if stdin
×
201
        process.stdin.setEncoding encoding
×
202

×
203
        // Try to guess filename for stdin, such as /dev/fd/filename
×
204
        filename = "<stdin>"
×
205
        try
×
206
          filename = await fs.realpath '/dev/stdin'
×
207

×
208
        if process.stdin.isTTY
×
209
          // In interactive stdin, `readline` lets user end the file via ^D.
×
210
          lines: string[] := []
×
211
          rl := import('node:readline') |> await |> .createInterface process.stdin, process.stdout
×
212
          rl.on 'line', (buffer: string) => lines.push buffer + '\n'
×
213
          content = await new Promise (resolve, reject) =>
×
214
            rl.on 'SIGINT', =>
×
215
              reject '^C'
×
216
            rl.on 'close', =>
×
217
              resolve lines.join ''
×
218
        else
×
219
          // For piped stdin, read stdin directly to avoid potential echo.
×
220
          content = (chunk for await chunk of process.stdin).join ''
×
221
      else
×
222
        content = await fs.readFile filename
×
223
      yield {filename, content, stdin}
×
224
    catch error
×
225
      yield {filename, error, stdin}
×
226

1✔
227
declare global
1✔
228
  var quit: () => void, exit: () => void
1✔
229
  var v8debug: unknown
1✔
230

1✔
231
export function repl(args: string[], options: Options)
×
232
  * as vm from 'node:vm'
×
233
  // Node 21.7.0+ supports dynamic import() in vm calls via this constant:
×
234
  importModuleDynamically .= vm.constants?.USE_MAIN_CONTEXT_DEFAULT_LOADER
×
235
  unless importModuleDynamically
×
236
    // For older Node, we need to provide our own dynamic import function,
×
237
    // which requires `--experimental-vm-modules`.  Check if we did it already:
×
238
    if vm.SourceTextModule?
×
239
      { pathToFileURL } from node:url
×
240
      importModuleDynamically = (specifier: string) =>
×
241
        if /^\.\.?[/\\]/.test specifier
×
242
          import pathToFileURL(path.join process.cwd(), specifier).href
×
243
        else
×
244
          import specifier
×
245
    else
×
246
      // If not, run this script with `--experimental-vm-modules`.
×
247
      execArgv := [ '--experimental-vm-modules' ]
×
248
      /* This doesn't work; --loader seems to force ESM mode which breaks CLI.
×
249
      { register } from node:module
×
250
      unless register
×
251
        // On Node <20.6.0, we need to use `--loader` for the ESM loader.
×
252
        execArgv.push '--loader', '@danielx/civet/esm'
×
253
      */
×
254
      { fork } from node:child_process
×
255
      fork __filename, args, {
×
256
        execArgv
×
257
        stdio: 'inherit'
×
258
      }
×
259
      return
×
260

×
261
  await import '../register.js'
×
262
  console.log `Civet ${await version()} REPL.  Enter a blank line to ${
×
263
    switch
×
264
      when options.ast then 'parse'
×
265
      when options.compile then 'transpile'
×
266
      else 'execute'
×
267
  } code.`
×
268
  global.quit = global.exit = => process.exit 0
×
269
  import * as nodeRepl from node:repl
×
270
  r := nodeRepl.start
×
271
    prompt:
×
272
      switch
×
273
        when options.ast then '🌲> '
×
274
        when options.compile then '🐈> '
×
275
        else '🐱> '
×
276
    writer:
×
277
      if options.ast
×
278
        (obj: unknown) =>
×
279
          try
×
280
            JSON.stringify obj, null, 2
×
281
          catch e
×
282
            console.log `Failed to stringify: ${e}`
×
283
            ''
×
284
      else if options.compile
×
285
        (obj: unknown) =>
×
286
          if obj <? 'string'
×
287
            obj?.replace /\n*$/, ''
×
288
          else
×
289
            ''
×
290
    eval: (input: string, context, filename: string, callback) ->
×
291
      // Newer Node versions use \r for intermediate line endings
×
292
      input = input.replace /\r/g, '\n'
×
293
      if input is '\n'  // blank input
×
294
        callback null, undefined
×
295
      else if input in ['quit\n', 'exit\n', 'quit()\n', 'exit()\n']
×
296
        process.exit 0
×
297
      else if input.endsWith '\n\n'  // finished input with blank line
×
298
        function showError(error: ???)
×
299
          console.error "Error while parsing Civet code:"
×
300
          if isCompileError error
×
301
            // Unwrap ParseErrors to first error
×
302
            if (error as ParseErrors).errors?
×
303
              error = (error as ParseErrors).errors[0]
×
304
            console.log ```
×
305
              ${input.split('\n')[0...(error as ParseError).line].join '\n'}
×
306
              ${' '.repeat (error as ParseError).column - 1}^ ${(error as ParseError).header}
×
307
            ```
×
308
          else
×
309
            console.error error
×
310

×
311
        let output: string
×
312
        if options.compile or options.ast
×
313
          try
×
314
            output = await compile input, {...options, filename}
×
315
          catch error
×
316
            showError error
×
317
            return callback null, undefined
×
318
          return callback null, output
×
319

×
320
        parseOptions := {...options.parseOptions,
×
321
          repl: true
×
322
        }
×
323

×
324
        let ast: BlockStatement
×
325
        try
×
326
          ast = await compile input, {...options, parseOptions, filename, ast: true}
×
327
        catch error
×
328
          showError error
×
329
          return callback null, undefined
×
330

×
331
        errors: ASTError[] .= []
×
332
        try
×
333
          output = generate ast, { ...options, errors, sourceMap: undefined }
×
334
        catch error
×
335
          //console.error "Failed to transpile Civet:"
×
336
          console.error error
×
337
          return callback null, undefined
×
338
        if errors#
×
339
          // Rerun with sourceMap
×
340
          errors = []
×
341
          generate ast, { ...options, errors, sourceMap: new SourceMap input }
×
342
          showError errors[0]
×
343
          return callback null, undefined
×
344

×
345
        let result: string
×
346
        try
×
347
          result = vm.runInContext output, context, {
×
348
            filename
×
349
            importModuleDynamically
×
350
          }
×
351
        catch error
×
352
          return callback error as Error, undefined
×
353

×
354
        if ast.topLevelAwait
×
355
          // If there was a top-level await, the result is a promise
×
356
          // that we need to await before returning it.
×
357
          try
×
358
            result = await result
×
359
          catch error
×
360
            callback error as Error, undefined
×
361
          else
×
362
            callback null, result
×
363
        else
×
364
          callback null, result
×
365
      else  // still reading
×
366
        callback (new nodeRepl.Recoverable new Error "Enter a blank line to execute code."), null
×
367

1✔
368
export function cli(args = process.argv[2..])
×
369
  // process.argv gets overridden when running scripts, but gets saved here
×
370

×
371
  {filenames, scriptArgs, options} .= await parseArgs args
×
372

×
373
  if options.version
×
374
    console.log await version()
×
375
    process.exit(0)
×
376

×
377
  if options.help
×
378
    process.stderr.write """
×
379
       ▄▄· ▪   ▌ ▐·▄▄▄ .▄▄▄▄▄
×
380
      ▐█ ▌▪██ ▪█·█▌▀▄.▀·•██       _._     _,-'""`-._
×
381
      ██ ▄▄▐█·▐█▐█•▐▀▀▪▄ ▐█.▪    (,-.`._,'(       |\\`-/|
×
382
      ▐███▌▐█▌ ███ ▐█▄▄▌ ▐█▌·        `-.-' \\ )-`( , o o)
×
383
      ·▀▀▀ ▀▀▀. ▀   ▀▀▀  ▀▀▀               `-    \\`_`"'-
×
384

×
385

×
386
Usage:
×
387

×
388
    civet                                        # REPL for executing code
×
389
    civet -c                                     # REPL for transpiling code
×
390
    civet --ast                                  # REPL for parsing code
×
391
    civet [options] input.civet                  # run input.civet
×
392
    civet [options] -c input.civet               # -> input.civet.tsx
×
393
    civet [options] -c input.civet -o .ts        # -> input.ts
×
394
    civet [options] -c input.civet -o dir        # -> dir/input.civet.tsx
×
395
    civet [options] -c input.civet -o dir/.ts    # -> dir/input.ts
×
396
    civet [options] -c input.civet -o output.ts  # -> output.ts
×
397
    civet [options] < input.civet > output.ts    # pipe form
×
398

×
399
Options:
×
400
  --help           Show this help message
×
401
  --version        Show the version number
×
402
  -o / --output XX Specify output directory and/or extension, or filename
×
403
  -c / --compile   Compile input files to TypeScript (or JavaScript)
×
404
  -e / --eval XX   Evaluate specified code (or compile it with -c)
×
405
  --config XX      Specify a config file (default scans for a config.civet, civet.json, civetconfig.civet or civetconfig.json file, optionally in a .config directory, or starting with a .)
×
406
  --civet XX       Specify civet compiler flag, as in "civet XX" prologue
×
407
  --comptime       Enable execution of code during compilation via comptime
×
408
  --no-config      Don't scan for a config file
×
409
  --js             Strip out all type annotations; default to .jsx extension
×
410
  --ast            Print the AST instead of the compiled code
×
411
  --inline-map     Generate a sourcemap
×
412
  --no-cache       Disable compiler caching (slow, for debugging)
×
413
  --typecheck      Run TypeScript and output diagnostics
×
414
  --emit-declaration  Run TypeScript and emit .d.ts files (if no errors)
×
415
  --trace XX       Log detailed parsing notes to a file, for parser debugging
×
416

×
417
You can use - to read from stdin or (prefixed by -o) write to stdout.
×
418

×
419
By default, .civet imports get rewritten to use the output extension.
×
420
You can override this behavior via: --civet rewriteCivetImports=.ext
×
421

×
422

×
423
    """
×
424
    process.exit(0)
×
425

×
426
  if options.config is undefined
×
427
    options.config = await findConfig process.cwd()
×
428
  if options.config
×
429
    parsed := await loadConfig options.config as string
×
430
    options = {
×
431
      ...parsed
×
432
      ...options
×
433
    }
×
434
    // Deep merge
×
435
    if parsed.parseOptions and options.parseOptions
×
436
      options.parseOptions = {
×
437
        ...parsed.parseOptions
×
438
        ...options.parseOptions
×
439
      }
×
440

×
441
  if options.typescript
×
442
    unpluginOptions := {
×
443
      ...options
×
444
      ts: if options.js then 'civet' else 'preserve'
×
445
      outputExtension: '.tsx'
×
446
      declarationExtension:
×
447
        options.outputExt?.replace /\.[jt]sx?$/i, '.d.ts'
×
448
    }
×
449
    // TypeScript wants .civet.tsx files imported as .civet.jsx
×
450
    (unpluginOptions.parseOptions ??= {}).rewriteCivetImports = '.civet.jsx'
×
451
    unplugin = rawPlugin unpluginOptions, framework: 'civet-cli'
×
452
    await unplugin.buildStart()
×
453

×
454
  // In run mode, compile to JS with source maps
×
455
  if options.run
×
456
    options.js = true
×
457
    options.inlineMap = true
×
458

×
459
  return repl args, options if options.repl
×
460

×
461
  // Ignore EPIPE errors, e.g. when piping to `head`
×
462
  process.stdout.on "error", (e) =>
×
463
    if e.code is in ['EPIPE', 'EOF']
×
464
      process.exit 0
×
465
    else
×
466
      console.error e
×
467
      process.exit 1
×
468

×
469
  errors .= 0
×
470
  for await let {filename, error, content, stdin} of readFiles filenames, options.eval
×
471
    if error
×
472
      console.error `${filename} failed to load:`
×
473
      console.error error
×
474
      errors++
×
475
      continue
×
476

×
477
    // Transpile
×
478
    let output: string
×
479
    try
×
480
      if unplugin?
×
481
        output = unplugin.load.call {
×
482
          addWatchFile();
×
483
        }, `${filename}.tsx`
×
484
        |> await
×
485
        |> .code
×
486
      else
×
487
        output = await compile content!, {...options, filename}
×
488
    catch error
×
489
      //console.error `${filename} failed to transpile:`
×
490
      console.error error
×
491
      errors++
×
492
      continue
×
493

×
494
    if options.ast
×
495
      process.stdout.write JSON.stringify(output, null, 2)
×
496
    else if options.compile
×
497
      if (stdin and not options.output) or options.output is '-'
×
498
        process.stdout.write output
×
499
      else
×
500
        targetPath: path.FormatInputPathObject .= path.parse filename
×
501
        delete targetPath.base  // use name and ext
×
502
        // Default extension
×
503
        if options.js
×
504
          targetPath.ext += ".jsx"
×
505
        else
×
506
          targetPath.ext += ".tsx"
×
507
        // `output` option overrides
×
508
        targetPath.dir = options.outputDir if options.outputDir?
×
509
        targetPath.ext = options.outputExt if options.outputExt?
×
510
        targetPath = options.outputPath if options.outputPath?
×
511
        // Make output directory in case it doesn't already exist
×
512
        await fs.mkdir targetPath.dir, recursive: true if targetPath.dir
×
513
        targetFilename := path.format targetPath
×
514
        try
×
515
          await fs.writeFile targetFilename, output
×
516
        catch error
×
517
          console.error `${targetFilename} failed to write:`
×
518
          console.error error
×
519
          errors++
×
520
    else if options.run
×
521
      esm := do
×
522
        if output is like /\b(await|import|export)\b/  // potentially ESM
×
523
          ast := await compile content!, {...options, ast: true, filename}
×
524
          (or)
×
525
            lib.hasAwait ast
×
526
            lib.hasImportDeclaration ast
×
527
            lib.hasExportDeclaration ast
×
528
      if esm
×
529
        // Run ESM code via `node --import @danielx/civet/register` subprocess
×
530
        if stdin
×
531
          // If code was read on stdin via command-line argument "-", try to
×
532
          // save it in a temporary file in same directory so paths are correct.
×
533
          filename = `.stdin-${process.pid}.civet`
×
534
          try
×
535
            await fs.writeFile filename, content!, {encoding}
×
536
          catch e
×
537
            console.error `Could not write ${filename} for Civet ESM mode:`
×
538
            console.error e
×
539
            process.exit 1
×
540
        { fork } from node:child_process
×
541

×
542
        { register } from node:module
×
543
        let execArgv
×
544
        if register
×
545
          // On Node 20.6.0+, module.register does the work for us;
×
546
          // we just need to `--import` ESM/CJS registration.
×
547
          { join } from path
×
548
          { pathToFileURL } from node:url
×
549
          execArgv = [
×
550
            '--import'
×
551
            pathToFileURL(join __dirname, '../register.js').href
×
552
          ]
×
553
        else
×
554
          // On Node <20.6.0, we need to use `--loader` for the ESM loader.
×
555
          execArgv = [
×
556
            '--loader', '@danielx/civet/esm' // ESM
×
557
            '--require', '@danielx/civet/register' // CJS
×
558
          ]
×
559

×
560
        debugRe := /--debug|--inspect/
×
561
        isDebug := v8debug <? "object" or debugRe.test(process.execArgv.join(' ')) or debugRe.test(process.env.NODE_OPTIONS ?? '')
×
562
        if isDebug
×
563
          execArgv.push "--inspect=" + (process.debugPort + 1)
×
564
        child := fork filename, [
×
565
          ...scriptArgs
×
566
        ], {
×
567
          execArgv
×
568
          stdio: 'inherit'
×
569
        }
×
570
        child.on 'exit', (code) =>
×
571
          if stdin
×
572
            // Delete temporary file
×
573
            await fs.unlink filename
×
574

×
575
          process.exit code ?? 1
×
576
        // Instead of default behavior of exiting, pass on signals to
×
577
        // child process and let it decide whether to exit
×
578
        for signal of ['SIGINT', 'SIGTERM', 'SIGHUP']
×
579
          process.on signal, => child.kill signal
×
580

×
581
      else
×
582
        await import '../register.js'
×
583
        try
×
584
          module.filename = await fs.realpath filename
×
585
        catch
×
586
          module.filename = filename
×
587
        process.argv = ["civet", module.filename, ...scriptArgs]
×
588
        module.paths =
×
589
          import 'node:module' |> await |> ._nodeModulePaths path.dirname module.filename
×
590
        try
×
591
          module._compile output, module.filename
×
592
        catch error
×
593
          console.error `${filename} crashed while running in CJS mode:`
×
594
          console.error error
×
595
          process.exit 1
×
596

×
597
  process.exitCode = Math.min 255, errors
×
598
  if unplugin?
×
599
    try
×
600
      await unplugin.buildEnd.call {
×
601
        emitFile({source, fileName})
×
602
          fs.writeFile fileName, source
×
603
      }, not filenames.length
×
604
    catch error
×
605
      if match := (error as Error).message.match /Aborting build because of (\d+) TypeScript diagnostic/
×
UNCOV
606
        process.exitCode = Math.min 255, errors + +match[1]
×
UNCOV
607
      else
×
UNCOV
608
        process.exitCode = 1
×
UNCOV
609
        throw error
×
610

1✔
611
// build/build.sh adds a call to cli() at the end here
1✔
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