Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/command/dev-call/validate-yaml/cmd.ts
3589 views
1
/*
2
* cmd.ts
3
*
4
* Copyright (C) 2025 Posit Software, PBC
5
*/
6
7
import { Command } from "cliffy/command/mod.ts";
8
import { initYamlIntelligenceResourcesFromFilesystem } from "../../../core/schema/utils.ts";
9
import { readAndValidateYamlFromMappedString } from "../../../core/lib/yaml-schema/validated-yaml.ts";
10
import { mappedStringFromFile } from "../../../core/mapped-text.ts";
11
import {
12
getSchemaDefinition,
13
setSchemaDefinition,
14
} from "../../../core/lib/yaml-validation/schema.ts";
15
import { error } from "../../../deno_ral/log.ts";
16
import { tidyverseFormatError } from "../../../core/lib/errors.ts";
17
import {
18
convertFromYaml,
19
getSchemaSchemas,
20
} from "../../../core/lib/yaml-schema/from-yaml.ts";
21
22
const getSchema = async (schemaNameOrFile: string) => {
23
if (schemaNameOrFile.endsWith(".yml")) {
24
getSchemaSchemas();
25
// it's a file, we load it, validate it against the schema schema
26
// and then return it
27
const file = mappedStringFromFile(schemaNameOrFile);
28
const schema = getSchemaDefinition("schema/schema");
29
const result = await readAndValidateYamlFromMappedString(
30
file,
31
schema,
32
);
33
if (result.yamlValidationErrors.length) {
34
error("Schema file is not valid");
35
for (const err of result.yamlValidationErrors) {
36
error(tidyverseFormatError(err.niceError), { colorize: false });
37
}
38
Deno.exit(1);
39
}
40
const schemaName = `user-schema-${schemaNameOrFile}`;
41
const newSchema = convertFromYaml(result.yaml);
42
newSchema.$id = schemaName;
43
setSchemaDefinition(newSchema);
44
return getSchemaDefinition(schemaName);
45
} else {
46
// it's a schema name, we get it from the schema registry
47
// and return it
48
return getSchemaDefinition(schemaNameOrFile);
49
}
50
};
51
52
export const validateYamlCommand = new Command()
53
.name("validate-yaml")
54
.hidden()
55
.arguments("<input:string>")
56
.option(
57
"-s, --schema [schema:string]",
58
"Name of schema in Quarto's definitions.yml. If string ends with .yml, it is treated as a file name for a new schema, which is validated, loaded, and then used.",
59
)
60
.option(
61
"--json",
62
"If set, output error messages in JSON format.",
63
)
64
.description(
65
"Validates a YAML file against Quarto's schemas.\n\n",
66
)
67
.action(async (options: any, input: string) => {
68
await initYamlIntelligenceResourcesFromFilesystem();
69
if (!options.schema) {
70
throw new Error("Schema name or file is required");
71
}
72
const file = mappedStringFromFile(input);
73
const schema = await getSchema(options.schema);
74
const result = await readAndValidateYamlFromMappedString(
75
file,
76
schema,
77
);
78
if (options.json) {
79
console.log(JSON.stringify(result.yamlValidationErrors, null, 2));
80
} else {
81
for (const err of result.yamlValidationErrors) {
82
error(tidyverseFormatError(err.niceError), { colorize: false });
83
}
84
}
85
if (result.yamlValidationErrors.length) {
86
Deno.exit(1);
87
}
88
});
89
90