Repository navigation
Expand file tree
/
Copy pathutils.ts
More file actions
97 lines (84 loc) · 2.62 KB
/
Copy pathutils.ts
File metadata and controls
97 lines (84 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
* @adonisjs/ace
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { Validator } from 'jsonschema'
import { RuntimeException } from '@poppinss/utils/exception'
import { schema } from '../schemas/main.ts'
import type { AbstractBaseCommand, CommandMetaData, UIPrimitives } from './types.ts'
/**
* Helper to sort array of strings alphabetically.
*/
export function sortAlphabetically(prev: string, curr: string) {
if (curr > prev) {
return -1
}
if (curr < prev) {
return 1
}
return 0
}
/**
* Renders an error message and lists suggestions.
*/
export function renderErrorWithSuggestions(
ui: UIPrimitives,
message: string,
suggestions: string[]
) {
const instructions = ui
.sticker()
.fullScreen()
.drawBorder((borderChar, colors) => colors.red(borderChar))
instructions.add(ui.colors.red(message))
if (suggestions.length) {
instructions.add('')
instructions.add(`${ui.colors.dim('Did you mean?')} ${suggestions.slice(0, 4).join(', ')}`)
}
instructions.getRenderer().logError(instructions.prepare())
}
/**
* Validates the metadata of a command to ensure it has all the neccessary
* properties
*/
export function validateCommandMetaData(
command: unknown,
exportPath: string
): asserts command is CommandMetaData {
if (!command || typeof command !== 'object') {
throw new RuntimeException(`Invalid command metadata exported from ${exportPath}`)
}
try {
new Validator().validate(command, schema, { throwError: true })
} catch (error) {
if (error && typeof error === 'object' && 'message' in error) {
throw new RuntimeException(`Invalid command exported from ${exportPath}. ${error.message}`)
}
}
}
/**
* Validates the command class. We do not check it against the "BaseCommand"
* class, because the ace version mis-match could make the validation
* fail.
*/
export function validateCommand<Command extends AbstractBaseCommand>(
command: unknown,
exportPath: string
): asserts command is Command {
if (typeof command !== 'function' || !command.toString().startsWith('class ')) {
throw new RuntimeException(
`Invalid command exported from ${exportPath}. Expected command to be a class`
)
}
const commandConstructor = command as Function & { serialize: () => unknown }
if (typeof commandConstructor.serialize !== 'function') {
throw new RuntimeException(
`Invalid command exported from ${exportPath}. Expected command to extend the "BaseCommand"`
)
}
validateCommandMetaData(commandConstructor.serialize(), exportPath)
}