@schalkneethling/miyagi-core 4.3.1 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -1
- package/bin/miyagi.js +9 -1
- package/index.js +2 -2
- package/lib/cli/component.js +23 -5
- package/lib/cli/doctor.js +153 -0
- package/lib/cli/drupal-assets.js +44 -7
- package/lib/cli/index.js +2 -0
- package/lib/cli/lint.js +71 -27
- package/lib/cli/run.js +281 -0
- package/lib/config.js +10 -0
- package/lib/errors.js +31 -0
- package/lib/index.js +7 -151
- package/lib/init/args.js +161 -93
- package/lib/init/engines.js +13 -4
- package/lib/init/index.js +26 -10
- package/lib/state/helpers.js +14 -9
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -22,7 +22,52 @@ _miyagi_ is a component development tool for JavaScript templating engines.
|
|
|
22
22
|
|
|
23
23
|
## Requirements
|
|
24
24
|
|
|
25
|
-
- NodeJS `
|
|
25
|
+
- NodeJS `24` or higher
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
Twig example:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm add -D @schalkneethling/miyagi-core twing
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Create `.miyagi.mjs`:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { createSynchronousEnvironment, createSynchronousFilesystemLoader } from "twing";
|
|
39
|
+
import fs from "node:fs";
|
|
40
|
+
|
|
41
|
+
const twing = createSynchronousEnvironment(createSynchronousFilesystemLoader(fs));
|
|
42
|
+
|
|
43
|
+
export default {
|
|
44
|
+
components: {
|
|
45
|
+
folder: "src/components",
|
|
46
|
+
},
|
|
47
|
+
docs: {
|
|
48
|
+
folder: "docs",
|
|
49
|
+
},
|
|
50
|
+
engine: {
|
|
51
|
+
async render({ name, context, cb }) {
|
|
52
|
+
try {
|
|
53
|
+
return cb(null, await twing.render(name, context));
|
|
54
|
+
} catch (err) {
|
|
55
|
+
return cb(err.toString());
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then start miyagi:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm exec miyagi start
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Open `http://localhost:5000`.
|
|
69
|
+
|
|
70
|
+
If you use a different template engine, swap the `engine.render` implementation for that engine.
|
|
26
71
|
|
|
27
72
|
## Demos
|
|
28
73
|
|
|
@@ -38,6 +83,8 @@ _miyagi_ is a component development tool for JavaScript templating engines.
|
|
|
38
83
|
|
|
39
84
|
[https://docs.miyagi.dev](https://docs.miyagi.dev)
|
|
40
85
|
|
|
86
|
+
CLI quickstart: [https://docs.miyagi.dev/cli-commands/starting-miyagi/](https://docs.miyagi.dev/cli-commands/starting-miyagi/)
|
|
87
|
+
|
|
41
88
|
## Sponsor
|
|
42
89
|
|
|
43
90
|
<a href="https://factorial.io"><img src="https://logo.factorial.io/color.png" width="40" height="56" alt="Factorial"></a>
|
package/bin/miyagi.js
CHANGED
package/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { runCli } from "./lib/cli/run.js";
|
|
2
2
|
|
|
3
|
-
export default
|
|
3
|
+
export default runCli;
|
package/lib/cli/component.js
CHANGED
|
@@ -2,18 +2,24 @@ import generateComponent from "../generator/component.js";
|
|
|
2
2
|
import log from "../logger.js";
|
|
3
3
|
import appConfig from "../default-config.js";
|
|
4
4
|
import { t } from "../i18n/index.js";
|
|
5
|
+
import { EXIT_CODES } from "../errors.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @param {object} cliParams
|
|
8
|
-
* @returns {Promise<
|
|
9
|
+
* @returns {Promise<object>}
|
|
9
10
|
*/
|
|
10
11
|
export default async function createComponentViaCli(cliParams) {
|
|
11
|
-
const commands = cliParams.
|
|
12
|
+
const commands = [cliParams.component].filter(Boolean);
|
|
12
13
|
|
|
13
14
|
if (commands.length === 0) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return
|
|
15
|
+
const message = t("generator.noComponentNameDefined");
|
|
16
|
+
log("error", message);
|
|
17
|
+
return {
|
|
18
|
+
success: false,
|
|
19
|
+
code: EXIT_CODES.CLI_USAGE_ERROR,
|
|
20
|
+
shouldExit: true,
|
|
21
|
+
message,
|
|
22
|
+
};
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
const [component] = commands;
|
|
@@ -25,8 +31,20 @@ export default async function createComponentViaCli(cliParams) {
|
|
|
25
31
|
try {
|
|
26
32
|
const result = await generateComponent({ component, fileTypes });
|
|
27
33
|
log("success", result);
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
code: EXIT_CODES.SUCCESS,
|
|
37
|
+
shouldExit: true,
|
|
38
|
+
message: result,
|
|
39
|
+
};
|
|
28
40
|
} catch (message) {
|
|
29
41
|
log("error", message);
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
code: EXIT_CODES.GENERAL_ERROR,
|
|
45
|
+
shouldExit: true,
|
|
46
|
+
message: String(message),
|
|
47
|
+
};
|
|
30
48
|
}
|
|
31
49
|
}
|
|
32
50
|
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import log from "../logger.js";
|
|
4
|
+
import { EXIT_CODES } from "../errors.js";
|
|
5
|
+
import pkgJson from "../../package.json" with { type: "json" };
|
|
6
|
+
|
|
7
|
+
const CONFIG_FILES = [".miyagi.js", ".miyagi.mjs"];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @returns {Promise<object>}
|
|
11
|
+
*/
|
|
12
|
+
export default async function doctor() {
|
|
13
|
+
let success = true;
|
|
14
|
+
|
|
15
|
+
if (checkNodeVersion()) {
|
|
16
|
+
log("success", `Node.js ${process.versions.node} satisfies ${pkgJson.engines.node}.`);
|
|
17
|
+
} else {
|
|
18
|
+
success = false;
|
|
19
|
+
log(
|
|
20
|
+
"error",
|
|
21
|
+
`Node.js ${process.versions.node} does not satisfy ${pkgJson.engines.node}.`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const configResult = await loadUserConfig();
|
|
26
|
+
|
|
27
|
+
if (!configResult.userFileName) {
|
|
28
|
+
success = false;
|
|
29
|
+
log(
|
|
30
|
+
"error",
|
|
31
|
+
"No miyagi config found. Create .miyagi.js or .miyagi.mjs in your project root.",
|
|
32
|
+
);
|
|
33
|
+
return {
|
|
34
|
+
success,
|
|
35
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
36
|
+
shouldExit: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (configResult.error) {
|
|
41
|
+
success = false;
|
|
42
|
+
log(
|
|
43
|
+
"error",
|
|
44
|
+
`Could not parse ${configResult.userFileName}. Check its syntax and exports.`,
|
|
45
|
+
);
|
|
46
|
+
log("error", configResult.error.message, configResult.error);
|
|
47
|
+
return {
|
|
48
|
+
success,
|
|
49
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
50
|
+
shouldExit: true,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
log("success", `Loaded config from ${configResult.userFileName}.`);
|
|
55
|
+
|
|
56
|
+
const config = configResult.config || {};
|
|
57
|
+
|
|
58
|
+
if (typeof config.engine?.render === "function") {
|
|
59
|
+
log("success", "engine.render is defined.");
|
|
60
|
+
} else {
|
|
61
|
+
success = false;
|
|
62
|
+
log("error", "engine.render is missing.");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (config.components?.folder || config.docs?.folder) {
|
|
66
|
+
log("success", "At least one source folder is configured.");
|
|
67
|
+
} else {
|
|
68
|
+
success = false;
|
|
69
|
+
log(
|
|
70
|
+
"error",
|
|
71
|
+
"Set at least one of components.folder or docs.folder in your miyagi config.",
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (config.components?.folder) {
|
|
76
|
+
if (await pathExists(config.components.folder)) {
|
|
77
|
+
log("success", `components.folder exists: ${config.components.folder}`);
|
|
78
|
+
} else {
|
|
79
|
+
success = false;
|
|
80
|
+
log("error", `components.folder does not exist: ${config.components.folder}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (config.docs?.folder) {
|
|
85
|
+
if (await pathExists(config.docs.folder)) {
|
|
86
|
+
log("success", `docs.folder exists: ${config.docs.folder}`);
|
|
87
|
+
} else {
|
|
88
|
+
success = false;
|
|
89
|
+
log("error", `docs.folder does not exist: ${config.docs.folder}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
log(success ? "success" : "error", success ? "Doctor checks passed." : "Doctor found issues.");
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
success,
|
|
97
|
+
code: success ? EXIT_CODES.SUCCESS : EXIT_CODES.CONFIG_ERROR,
|
|
98
|
+
shouldExit: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @returns {boolean}
|
|
104
|
+
*/
|
|
105
|
+
function checkNodeVersion() {
|
|
106
|
+
const minimumMajor = Number(pkgJson.engines.node.match(/\d+/)?.[0] || 0);
|
|
107
|
+
const currentMajor = Number(process.versions.node.split(".")[0]);
|
|
108
|
+
return currentMajor >= minimumMajor;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {string} relativePath
|
|
113
|
+
* @returns {Promise<boolean>}
|
|
114
|
+
*/
|
|
115
|
+
async function pathExists(relativePath) {
|
|
116
|
+
try {
|
|
117
|
+
await stat(path.resolve(process.cwd(), relativePath));
|
|
118
|
+
return true;
|
|
119
|
+
} catch {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @returns {Promise<object>}
|
|
126
|
+
*/
|
|
127
|
+
async function loadUserConfig() {
|
|
128
|
+
for (const fileName of CONFIG_FILES) {
|
|
129
|
+
const fullPath = path.resolve(process.cwd(), fileName);
|
|
130
|
+
|
|
131
|
+
if (!(await pathExists(fileName))) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const module = await import(`${fullPath}?time=${Date.now()}`);
|
|
137
|
+
return {
|
|
138
|
+
userFileName: fileName,
|
|
139
|
+
config: module.default || {},
|
|
140
|
+
};
|
|
141
|
+
} catch (error) {
|
|
142
|
+
return {
|
|
143
|
+
userFileName: fileName,
|
|
144
|
+
error: /** @type {Error} */ (error),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
userFileName: null,
|
|
151
|
+
config: null,
|
|
152
|
+
};
|
|
153
|
+
}
|
package/lib/cli/drupal-assets.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readFile, writeFile } from "node:fs/promises";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import yaml from "js-yaml";
|
|
6
6
|
import log from "../logger.js";
|
|
7
|
+
import { EXIT_CODES } from "../errors.js";
|
|
7
8
|
import { loadAssetsConfig } from "../drupal/load-assets-config.js";
|
|
8
9
|
import {
|
|
9
10
|
parseLibrariesYaml,
|
|
@@ -18,27 +19,47 @@ import {
|
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* @param {object} args - CLI arguments from yargs
|
|
22
|
+
* @returns {Promise<object>}
|
|
21
23
|
*/
|
|
22
24
|
export default async function drupalAssets(args) {
|
|
23
25
|
let config;
|
|
24
26
|
try {
|
|
25
27
|
config = await loadAssetsConfig(args);
|
|
26
28
|
} catch (err) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
const message = /** @type {Error} */ (err).message;
|
|
30
|
+
log("error", message);
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
34
|
+
shouldExit: true,
|
|
35
|
+
message,
|
|
36
|
+
};
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
if (!config.libraries) {
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
const message =
|
|
41
|
+
"No libraries file specified. Use --libraries or configure it in .miyagi-assets.js.";
|
|
42
|
+
log("error", message);
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
code: EXIT_CODES.CLI_USAGE_ERROR,
|
|
46
|
+
shouldExit: true,
|
|
47
|
+
message,
|
|
48
|
+
};
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
let yamlContent;
|
|
37
52
|
try {
|
|
38
53
|
yamlContent = await readFile(config.libraries, "utf8");
|
|
39
54
|
} catch {
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
const message = `Could not read libraries file: ${config.libraries}`;
|
|
56
|
+
log("error", message);
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
code: EXIT_CODES.CONFIG_ERROR,
|
|
60
|
+
shouldExit: true,
|
|
61
|
+
message,
|
|
62
|
+
};
|
|
42
63
|
}
|
|
43
64
|
|
|
44
65
|
const librariesMap = parseLibrariesYaml(yamlContent);
|
|
@@ -89,8 +110,24 @@ export default async function drupalAssets(args) {
|
|
|
89
110
|
}
|
|
90
111
|
|
|
91
112
|
if (!config.dryRun) {
|
|
92
|
-
|
|
113
|
+
const message = `Done. Updated ${updatedCount} component(s).`;
|
|
114
|
+
log("success", message);
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
code: EXIT_CODES.SUCCESS,
|
|
118
|
+
shouldExit: true,
|
|
119
|
+
message,
|
|
120
|
+
updatedCount,
|
|
121
|
+
};
|
|
93
122
|
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
126
|
+
code: EXIT_CODES.SUCCESS,
|
|
127
|
+
shouldExit: true,
|
|
128
|
+
message: "Dry run completed.",
|
|
129
|
+
updatedCount,
|
|
130
|
+
};
|
|
94
131
|
}
|
|
95
132
|
|
|
96
133
|
/**
|
package/lib/cli/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import lintImport from "./lint.js";
|
|
2
2
|
import componentImport from "./component.js";
|
|
3
3
|
import drupalAssetsImport from "./drupal-assets.js";
|
|
4
|
+
import doctorImport from "./doctor.js";
|
|
4
5
|
|
|
5
6
|
export const lint = lintImport;
|
|
6
7
|
export const component = componentImport;
|
|
7
8
|
export const drupalAssets = drupalAssetsImport;
|
|
9
|
+
export const doctor = doctorImport;
|
package/lib/cli/lint.js
CHANGED
|
@@ -10,14 +10,16 @@ import {
|
|
|
10
10
|
validateSchemas,
|
|
11
11
|
} from "../validator/schemas.js";
|
|
12
12
|
import { t } from "../i18n/index.js";
|
|
13
|
+
import { EXIT_CODES } from "../errors.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @param {object} args
|
|
17
|
+
* @returns {Promise<object>}
|
|
16
18
|
*/
|
|
17
19
|
export default async function lint(args) {
|
|
18
20
|
process.env.NODE_ENV = "development";
|
|
19
21
|
|
|
20
|
-
const componentArg = args.
|
|
22
|
+
const componentArg = args.component;
|
|
21
23
|
const config = await getConfig(args);
|
|
22
24
|
process.env.MIYAGI_LOG_CONTEXT = "lint";
|
|
23
25
|
process.env.MIYAGI_LOG_LEVEL = config.lint?.logLevel || "error";
|
|
@@ -36,26 +38,63 @@ export default async function lint(args) {
|
|
|
36
38
|
|
|
37
39
|
if (schemaValidation.errors.length > 0) {
|
|
38
40
|
reportSchemaErrors(schemaValidation.errors);
|
|
39
|
-
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
code: EXIT_CODES.VALIDATION_ERROR,
|
|
44
|
+
shouldExit: true,
|
|
45
|
+
};
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
log("success", "All schemas valid.");
|
|
43
49
|
|
|
44
|
-
await validateComponentMockData({
|
|
50
|
+
return await validateComponentMockData({
|
|
45
51
|
component,
|
|
46
52
|
validSchemas: schemaValidation.validSchemas,
|
|
47
53
|
});
|
|
48
54
|
} else {
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
const message = `The component ${componentArg} does not seem to exist.`;
|
|
56
|
+
log("error", message);
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
code: EXIT_CODES.CLI_USAGE_ERROR,
|
|
60
|
+
shouldExit: true,
|
|
61
|
+
message,
|
|
62
|
+
};
|
|
51
63
|
}
|
|
52
64
|
} else {
|
|
53
|
-
await validateAllMockData();
|
|
65
|
+
return await validateAllMockData();
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @param {object} options
|
|
71
|
+
* @param {boolean} options.success
|
|
72
|
+
* @param {boolean} options.shouldExit
|
|
73
|
+
* @param {boolean} [options.valid]
|
|
74
|
+
* @param {string} [options.type]
|
|
75
|
+
* @returns {object}
|
|
76
|
+
*/
|
|
77
|
+
function createLintResult({ success, shouldExit, valid, type }) {
|
|
78
|
+
const result = {
|
|
79
|
+
success,
|
|
80
|
+
code: success ? EXIT_CODES.SUCCESS : EXIT_CODES.VALIDATION_ERROR,
|
|
81
|
+
shouldExit,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (valid !== undefined) {
|
|
85
|
+
result.valid = valid;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (type) {
|
|
89
|
+
result.type = type;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
57
95
|
/**
|
|
58
96
|
* @param {boolean} exitProcess
|
|
97
|
+
* @returns {Promise<object>}
|
|
59
98
|
*/
|
|
60
99
|
async function validateAllMockData(exitProcess = true) {
|
|
61
100
|
log("info", t("linter.all.start"));
|
|
@@ -86,9 +125,17 @@ async function validateAllMockData(exitProcess = true) {
|
|
|
86
125
|
),
|
|
87
126
|
);
|
|
88
127
|
if (exitProcess) {
|
|
89
|
-
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
code: EXIT_CODES.VALIDATION_ERROR,
|
|
131
|
+
shouldExit: true,
|
|
132
|
+
};
|
|
90
133
|
}
|
|
91
|
-
return
|
|
134
|
+
return {
|
|
135
|
+
success: false,
|
|
136
|
+
code: EXIT_CODES.VALIDATION_ERROR,
|
|
137
|
+
shouldExit: false,
|
|
138
|
+
};
|
|
92
139
|
}
|
|
93
140
|
|
|
94
141
|
const results = await Promise.all(
|
|
@@ -134,15 +181,16 @@ async function validateAllMockData(exitProcess = true) {
|
|
|
134
181
|
|
|
135
182
|
if (mockInvalidResults.length === 0 && schemaValidation.errors.length === 0) {
|
|
136
183
|
log("success", t("linter.all.valid"));
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
184
|
+
return createLintResult({
|
|
185
|
+
success: true,
|
|
186
|
+
shouldExit: exitProcess,
|
|
187
|
+
});
|
|
141
188
|
}
|
|
142
189
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
190
|
+
return createLintResult({
|
|
191
|
+
success: false,
|
|
192
|
+
shouldExit: exitProcess,
|
|
193
|
+
});
|
|
146
194
|
}
|
|
147
195
|
|
|
148
196
|
/**
|
|
@@ -188,23 +236,19 @@ async function validateComponentMockData({
|
|
|
188
236
|
log("success", t("linter.component.valid"));
|
|
189
237
|
}
|
|
190
238
|
|
|
191
|
-
|
|
192
|
-
process.exit(0);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return {
|
|
239
|
+
return createLintResult({
|
|
196
240
|
valid: true,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (exitProcess) {
|
|
201
|
-
process.exit(1);
|
|
241
|
+
success: true,
|
|
242
|
+
shouldExit: exitProcess,
|
|
243
|
+
});
|
|
202
244
|
}
|
|
203
245
|
|
|
204
|
-
return {
|
|
246
|
+
return createLintResult({
|
|
205
247
|
valid: false,
|
|
248
|
+
success: false,
|
|
249
|
+
shouldExit: exitProcess,
|
|
206
250
|
type: results[0].type,
|
|
207
|
-
};
|
|
251
|
+
});
|
|
208
252
|
}
|
|
209
253
|
|
|
210
254
|
/**
|