@valbuild/cli 0.14.0 → 0.16.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.
@@ -7,7 +7,8 @@ var chalk = require('chalk');
7
7
  var express = require('express');
8
8
  var cors = require('cors');
9
9
  var node_http = require('node:http');
10
- var LocalValServer = require('@valbuild/server/src/LocalValServer');
10
+ var fastGlob = require('fast-glob');
11
+ var picocolors = require('picocolors');
11
12
 
12
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
13
14
 
@@ -16,6 +17,7 @@ var meow__default = /*#__PURE__*/_interopDefault(meow);
16
17
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
17
18
  var express__default = /*#__PURE__*/_interopDefault(express);
18
19
  var cors__default = /*#__PURE__*/_interopDefault(cors);
20
+ var picocolors__default = /*#__PURE__*/_interopDefault(picocolors);
19
21
 
20
22
  function error(...message) {
21
23
  console.error(chalk__default["default"].red(...message));
@@ -24,6 +26,68 @@ function info(...message) {
24
26
  console.log(...message);
25
27
  }
26
28
 
29
+ async function validate({
30
+ root,
31
+ cfg,
32
+ fix
33
+ }) {
34
+ const projectRoot = root ? path__default["default"].resolve(root) : process.cwd();
35
+ const service = await server.createService(projectRoot, {
36
+ valConfigPath: cfg ?? "./val.config"
37
+ });
38
+ const valFiles = await fastGlob.glob("**/*.val.{js,ts}", {
39
+ ignore: ["node_modules/**"],
40
+ cwd: projectRoot
41
+ });
42
+ console.log(picocolors__default["default"].green("✔"), "Validating", valFiles.length, "files");
43
+ async function validateFile(file) {
44
+ const moduleId = `/${file}`.replace(/(\.val\.(ts|js))$/, ""); // TODO: check if this always works? (Windows?)
45
+ const start = Date.now();
46
+ const valModule = await service.get(moduleId, "");
47
+ if (!valModule.errors) {
48
+ console.log(picocolors__default["default"].green("✔"), moduleId, "is valid (", Date.now() - start, "ms)");
49
+ return 0;
50
+ } else {
51
+ let errors = 0;
52
+ if (valModule.errors.validation) for (const [sourcePath, validationErrors] of Object.entries(valModule.errors.validation)) {
53
+ for (const v of validationErrors) {
54
+ if (v.fixes && v.fixes.length > 0) {
55
+ var _fixPatch$remainingEr;
56
+ const fixPatch = await server.createFixPatch({
57
+ projectRoot
58
+ }, !!fix, sourcePath, v);
59
+ if (fix && fixPatch !== null && fixPatch !== void 0 && fixPatch.patch && (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.patch.length) > 0) {
60
+ await service.patch(moduleId, fixPatch.patch);
61
+ console.log(picocolors__default["default"].green("✔"), "Applied fix for", sourcePath);
62
+ }
63
+ fixPatch === null || fixPatch === void 0 ? void 0 : (_fixPatch$remainingEr = fixPatch.remainingErrors) === null || _fixPatch$remainingEr === void 0 ? void 0 : _fixPatch$remainingEr.forEach(e => {
64
+ errors += 1;
65
+ console.log(v.fixes ? picocolors__default["default"].yellow("⚠") : picocolors__default["default"].red("✘"), `Found ${v.fixes ? "fixable " : ""}error in`, `${sourcePath}:`, e.message);
66
+ });
67
+ } else {
68
+ errors += 1;
69
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}:`, v.message);
70
+ }
71
+ }
72
+ }
73
+ for (const fatalError of valModule.errors.fatal || []) {
74
+ errors += 1;
75
+ console.log(picocolors__default["default"].red("✘"), moduleId, "is invalid:", fatalError.message);
76
+ }
77
+ return errors;
78
+ }
79
+ }
80
+ const errors = (await Promise.all(valFiles.map(validateFile))).reduce((a, b) => a + b, 0);
81
+ if (errors > 0) {
82
+ console.log(picocolors__default["default"].red("✘"), "Found", errors, "validation error" + (errors > 1 ? "s" : ""));
83
+ process.exit(1);
84
+ } else {
85
+ console.log(picocolors__default["default"].green("✔"), "No validation errors found");
86
+ }
87
+ service.dispose();
88
+ return;
89
+ }
90
+
27
91
  async function serve({
28
92
  root,
29
93
  port,
@@ -33,7 +97,7 @@ async function serve({
33
97
  const service = await server.createService(projectRoot, {
34
98
  valConfigPath: cfg ?? "./val.config"
35
99
  });
36
- const valReqHandler = server.createRequestHandler(new LocalValServer.LocalValServer({
100
+ const valReqHandler = server.createRequestHandler(new server.LocalValServer({
37
101
  service
38
102
  }));
39
103
  const app = express__default["default"]();
@@ -75,12 +139,14 @@ async function main() {
75
139
  $ val [command]
76
140
  Commands
77
141
  serve Run val development server
142
+ validate val-idate val modules
78
143
 
79
144
  Options
80
145
  --help Show this message
81
146
  --port [port], -p [port] Set server port (default 4123)
82
147
  --root [root], -r [root] Set project root directory (default process.cwd())
83
148
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
149
+ --fix [fix] Attempt to fix validation errors
84
150
  `, {
85
151
  flags: {
86
152
  port: {
@@ -95,6 +161,9 @@ async function main() {
95
161
  cfg: {
96
162
  type: "string",
97
163
  alias: "c"
164
+ },
165
+ fix: {
166
+ type: "boolean"
98
167
  }
99
168
  },
100
169
  hardRejection: false
@@ -113,11 +182,18 @@ async function main() {
113
182
  port: flags.port,
114
183
  cfg: flags.cfg
115
184
  });
185
+ case "validate":
186
+ case "idate":
187
+ return validate({
188
+ root: flags.root,
189
+ cfg: flags.cfg,
190
+ fix: flags.fix
191
+ });
116
192
  default:
117
193
  return error(`Unknown command "${input.join(" ")}"`);
118
194
  }
119
195
  }
120
196
  void main().catch(err => {
121
- error(err);
197
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
122
198
  process.exitCode = 1;
123
199
  });
@@ -7,7 +7,8 @@ var chalk = require('chalk');
7
7
  var express = require('express');
8
8
  var cors = require('cors');
9
9
  var node_http = require('node:http');
10
- var LocalValServer = require('@valbuild/server/src/LocalValServer');
10
+ var fastGlob = require('fast-glob');
11
+ var picocolors = require('picocolors');
11
12
 
12
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
13
14
 
@@ -16,6 +17,7 @@ var meow__default = /*#__PURE__*/_interopDefault(meow);
16
17
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
17
18
  var express__default = /*#__PURE__*/_interopDefault(express);
18
19
  var cors__default = /*#__PURE__*/_interopDefault(cors);
20
+ var picocolors__default = /*#__PURE__*/_interopDefault(picocolors);
19
21
 
20
22
  function error(...message) {
21
23
  console.error(chalk__default["default"].red(...message));
@@ -24,6 +26,68 @@ function info(...message) {
24
26
  console.log(...message);
25
27
  }
26
28
 
29
+ async function validate({
30
+ root,
31
+ cfg,
32
+ fix
33
+ }) {
34
+ const projectRoot = root ? path__default["default"].resolve(root) : process.cwd();
35
+ const service = await server.createService(projectRoot, {
36
+ valConfigPath: cfg ?? "./val.config"
37
+ });
38
+ const valFiles = await fastGlob.glob("**/*.val.{js,ts}", {
39
+ ignore: ["node_modules/**"],
40
+ cwd: projectRoot
41
+ });
42
+ console.log(picocolors__default["default"].green("✔"), "Validating", valFiles.length, "files");
43
+ async function validateFile(file) {
44
+ const moduleId = `/${file}`.replace(/(\.val\.(ts|js))$/, ""); // TODO: check if this always works? (Windows?)
45
+ const start = Date.now();
46
+ const valModule = await service.get(moduleId, "");
47
+ if (!valModule.errors) {
48
+ console.log(picocolors__default["default"].green("✔"), moduleId, "is valid (", Date.now() - start, "ms)");
49
+ return 0;
50
+ } else {
51
+ let errors = 0;
52
+ if (valModule.errors.validation) for (const [sourcePath, validationErrors] of Object.entries(valModule.errors.validation)) {
53
+ for (const v of validationErrors) {
54
+ if (v.fixes && v.fixes.length > 0) {
55
+ var _fixPatch$remainingEr;
56
+ const fixPatch = await server.createFixPatch({
57
+ projectRoot
58
+ }, !!fix, sourcePath, v);
59
+ if (fix && fixPatch !== null && fixPatch !== void 0 && fixPatch.patch && (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.patch.length) > 0) {
60
+ await service.patch(moduleId, fixPatch.patch);
61
+ console.log(picocolors__default["default"].green("✔"), "Applied fix for", sourcePath);
62
+ }
63
+ fixPatch === null || fixPatch === void 0 ? void 0 : (_fixPatch$remainingEr = fixPatch.remainingErrors) === null || _fixPatch$remainingEr === void 0 ? void 0 : _fixPatch$remainingEr.forEach(e => {
64
+ errors += 1;
65
+ console.log(v.fixes ? picocolors__default["default"].yellow("⚠") : picocolors__default["default"].red("✘"), `Found ${v.fixes ? "fixable " : ""}error in`, `${sourcePath}:`, e.message);
66
+ });
67
+ } else {
68
+ errors += 1;
69
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}:`, v.message);
70
+ }
71
+ }
72
+ }
73
+ for (const fatalError of valModule.errors.fatal || []) {
74
+ errors += 1;
75
+ console.log(picocolors__default["default"].red("✘"), moduleId, "is invalid:", fatalError.message);
76
+ }
77
+ return errors;
78
+ }
79
+ }
80
+ const errors = (await Promise.all(valFiles.map(validateFile))).reduce((a, b) => a + b, 0);
81
+ if (errors > 0) {
82
+ console.log(picocolors__default["default"].red("✘"), "Found", errors, "validation error" + (errors > 1 ? "s" : ""));
83
+ process.exit(1);
84
+ } else {
85
+ console.log(picocolors__default["default"].green("✔"), "No validation errors found");
86
+ }
87
+ service.dispose();
88
+ return;
89
+ }
90
+
27
91
  async function serve({
28
92
  root,
29
93
  port,
@@ -33,7 +97,7 @@ async function serve({
33
97
  const service = await server.createService(projectRoot, {
34
98
  valConfigPath: cfg ?? "./val.config"
35
99
  });
36
- const valReqHandler = server.createRequestHandler(new LocalValServer.LocalValServer({
100
+ const valReqHandler = server.createRequestHandler(new server.LocalValServer({
37
101
  service
38
102
  }));
39
103
  const app = express__default["default"]();
@@ -75,12 +139,14 @@ async function main() {
75
139
  $ val [command]
76
140
  Commands
77
141
  serve Run val development server
142
+ validate val-idate val modules
78
143
 
79
144
  Options
80
145
  --help Show this message
81
146
  --port [port], -p [port] Set server port (default 4123)
82
147
  --root [root], -r [root] Set project root directory (default process.cwd())
83
148
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
149
+ --fix [fix] Attempt to fix validation errors
84
150
  `, {
85
151
  flags: {
86
152
  port: {
@@ -95,6 +161,9 @@ async function main() {
95
161
  cfg: {
96
162
  type: "string",
97
163
  alias: "c"
164
+ },
165
+ fix: {
166
+ type: "boolean"
98
167
  }
99
168
  },
100
169
  hardRejection: false
@@ -113,11 +182,18 @@ async function main() {
113
182
  port: flags.port,
114
183
  cfg: flags.cfg
115
184
  });
185
+ case "validate":
186
+ case "idate":
187
+ return validate({
188
+ root: flags.root,
189
+ cfg: flags.cfg,
190
+ fix: flags.fix
191
+ });
116
192
  default:
117
193
  return error(`Unknown command "${input.join(" ")}"`);
118
194
  }
119
195
  }
120
196
  void main().catch(err => {
121
- error(err);
197
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
122
198
  process.exitCode = 1;
123
199
  });
@@ -1,11 +1,12 @@
1
1
  import path from 'path';
2
2
  import meow from 'meow';
3
- import { createService, createRequestHandler } from '@valbuild/server';
3
+ import { createService, createFixPatch, createRequestHandler, LocalValServer } from '@valbuild/server';
4
4
  import chalk from 'chalk';
5
5
  import express from 'express';
6
6
  import cors from 'cors';
7
7
  import { createServer } from 'node:http';
8
- import { LocalValServer } from '@valbuild/server/src/LocalValServer';
8
+ import { glob } from 'fast-glob';
9
+ import picocolors from 'picocolors';
9
10
 
10
11
  function error(...message) {
11
12
  console.error(chalk.red(...message));
@@ -14,6 +15,68 @@ function info(...message) {
14
15
  console.log(...message);
15
16
  }
16
17
 
18
+ async function validate({
19
+ root,
20
+ cfg,
21
+ fix
22
+ }) {
23
+ const projectRoot = root ? path.resolve(root) : process.cwd();
24
+ const service = await createService(projectRoot, {
25
+ valConfigPath: cfg ?? "./val.config"
26
+ });
27
+ const valFiles = await glob("**/*.val.{js,ts}", {
28
+ ignore: ["node_modules/**"],
29
+ cwd: projectRoot
30
+ });
31
+ console.log(picocolors.green("✔"), "Validating", valFiles.length, "files");
32
+ async function validateFile(file) {
33
+ const moduleId = `/${file}`.replace(/(\.val\.(ts|js))$/, ""); // TODO: check if this always works? (Windows?)
34
+ const start = Date.now();
35
+ const valModule = await service.get(moduleId, "");
36
+ if (!valModule.errors) {
37
+ console.log(picocolors.green("✔"), moduleId, "is valid (", Date.now() - start, "ms)");
38
+ return 0;
39
+ } else {
40
+ let errors = 0;
41
+ if (valModule.errors.validation) for (const [sourcePath, validationErrors] of Object.entries(valModule.errors.validation)) {
42
+ for (const v of validationErrors) {
43
+ if (v.fixes && v.fixes.length > 0) {
44
+ var _fixPatch$remainingEr;
45
+ const fixPatch = await createFixPatch({
46
+ projectRoot
47
+ }, !!fix, sourcePath, v);
48
+ if (fix && fixPatch !== null && fixPatch !== void 0 && fixPatch.patch && (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.patch.length) > 0) {
49
+ await service.patch(moduleId, fixPatch.patch);
50
+ console.log(picocolors.green("✔"), "Applied fix for", sourcePath);
51
+ }
52
+ fixPatch === null || fixPatch === void 0 ? void 0 : (_fixPatch$remainingEr = fixPatch.remainingErrors) === null || _fixPatch$remainingEr === void 0 ? void 0 : _fixPatch$remainingEr.forEach(e => {
53
+ errors += 1;
54
+ console.log(v.fixes ? picocolors.yellow("⚠") : picocolors.red("✘"), `Found ${v.fixes ? "fixable " : ""}error in`, `${sourcePath}:`, e.message);
55
+ });
56
+ } else {
57
+ errors += 1;
58
+ console.log(picocolors.red("✘"), "Found error in", `${sourcePath}:`, v.message);
59
+ }
60
+ }
61
+ }
62
+ for (const fatalError of valModule.errors.fatal || []) {
63
+ errors += 1;
64
+ console.log(picocolors.red("✘"), moduleId, "is invalid:", fatalError.message);
65
+ }
66
+ return errors;
67
+ }
68
+ }
69
+ const errors = (await Promise.all(valFiles.map(validateFile))).reduce((a, b) => a + b, 0);
70
+ if (errors > 0) {
71
+ console.log(picocolors.red("✘"), "Found", errors, "validation error" + (errors > 1 ? "s" : ""));
72
+ process.exit(1);
73
+ } else {
74
+ console.log(picocolors.green("✔"), "No validation errors found");
75
+ }
76
+ service.dispose();
77
+ return;
78
+ }
79
+
17
80
  async function serve({
18
81
  root,
19
82
  port,
@@ -65,12 +128,14 @@ async function main() {
65
128
  $ val [command]
66
129
  Commands
67
130
  serve Run val development server
131
+ validate val-idate val modules
68
132
 
69
133
  Options
70
134
  --help Show this message
71
135
  --port [port], -p [port] Set server port (default 4123)
72
136
  --root [root], -r [root] Set project root directory (default process.cwd())
73
137
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
138
+ --fix [fix] Attempt to fix validation errors
74
139
  `, {
75
140
  flags: {
76
141
  port: {
@@ -85,6 +150,9 @@ async function main() {
85
150
  cfg: {
86
151
  type: "string",
87
152
  alias: "c"
153
+ },
154
+ fix: {
155
+ type: "boolean"
88
156
  }
89
157
  },
90
158
  hardRejection: false
@@ -103,11 +171,18 @@ async function main() {
103
171
  port: flags.port,
104
172
  cfg: flags.cfg
105
173
  });
174
+ case "validate":
175
+ case "idate":
176
+ return validate({
177
+ root: flags.root,
178
+ cfg: flags.cfg,
179
+ fix: flags.fix
180
+ });
106
181
  default:
107
182
  return error(`Unknown command "${input.join(" ")}"`);
108
183
  }
109
184
  }
110
185
  void main().catch(err => {
111
- error(err);
186
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
112
187
  process.exitCode = 1;
113
188
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valbuild/cli",
3
3
  "private": false,
4
- "version": "0.14.0",
4
+ "version": "0.16.0",
5
5
  "description": "Val CLI tools",
6
6
  "bin": {
7
7
  "val": "./bin.js"
@@ -17,11 +17,13 @@
17
17
  "typecheck": "tsc --noEmit"
18
18
  },
19
19
  "dependencies": {
20
- "@valbuild/server": "~0.14.0",
20
+ "@valbuild/server": "~0.16.0",
21
21
  "chalk": "^4.1.2",
22
22
  "cors": "^2.8.5",
23
23
  "express": "^4.18.2",
24
- "meow": "^9.0.0"
24
+ "fast-glob": "^3.3.1",
25
+ "meow": "^9.0.0",
26
+ "picocolors": "^1.0.0"
25
27
  },
26
28
  "preconstruct": {
27
29
  "entrypoints": [
package/src/cli.ts CHANGED
@@ -5,7 +5,8 @@ import { error, info } from "./logger";
5
5
  import express from "express";
6
6
  import cors from "cors";
7
7
  import { createServer, Server } from "node:http";
8
- import { LocalValServer } from "@valbuild/server/src/LocalValServer";
8
+ import { LocalValServer } from "@valbuild/server";
9
+ import { validate } from "./validate";
9
10
 
10
11
  async function serve({
11
12
  root,
@@ -68,12 +69,14 @@ async function main(): Promise<void> {
68
69
  $ val [command]
69
70
  Commands
70
71
  serve Run val development server
72
+ validate val-idate val modules
71
73
 
72
74
  Options
73
75
  --help Show this message
74
76
  --port [port], -p [port] Set server port (default 4123)
75
77
  --root [root], -r [root] Set project root directory (default process.cwd())
76
78
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
79
+ --fix [fix] Attempt to fix validation errors
77
80
  `,
78
81
  {
79
82
  flags: {
@@ -90,6 +93,9 @@ async function main(): Promise<void> {
90
93
  type: "string",
91
94
  alias: "c",
92
95
  },
96
+ fix: {
97
+ type: "boolean",
98
+ },
93
99
  },
94
100
  hardRejection: false,
95
101
  }
@@ -111,12 +117,25 @@ async function main(): Promise<void> {
111
117
  port: flags.port,
112
118
  cfg: flags.cfg,
113
119
  });
120
+ case "validate":
121
+ case "idate":
122
+ return validate({
123
+ root: flags.root,
124
+ cfg: flags.cfg,
125
+ fix: flags.fix,
126
+ });
114
127
  default:
115
128
  return error(`Unknown command "${input.join(" ")}"`);
116
129
  }
117
130
  }
118
131
 
119
132
  void main().catch((err) => {
120
- error(err);
133
+ error(
134
+ err instanceof Error
135
+ ? err.message + "\n" + err.stack
136
+ : typeof err === "object"
137
+ ? JSON.stringify(err, null, 2)
138
+ : err
139
+ );
121
140
  process.exitCode = 1;
122
141
  });
@@ -0,0 +1,114 @@
1
+ import path from "path";
2
+ import { createFixPatch, createService } from "@valbuild/server";
3
+ import { ModuleId, ModulePath, SourcePath } from "@valbuild/core";
4
+ import { glob } from "fast-glob";
5
+ import picocolors from "picocolors";
6
+
7
+ export async function validate({
8
+ root,
9
+ cfg,
10
+ fix,
11
+ }: {
12
+ root?: string;
13
+ cfg?: string;
14
+ fix?: boolean;
15
+ }) {
16
+ const projectRoot = root ? path.resolve(root) : process.cwd();
17
+ const service = await createService(projectRoot, {
18
+ valConfigPath: cfg ?? "./val.config",
19
+ });
20
+
21
+ const valFiles: string[] = await glob("**/*.val.{js,ts}", {
22
+ ignore: ["node_modules/**"],
23
+ cwd: projectRoot,
24
+ });
25
+ console.log(picocolors.green("✔"), "Validating", valFiles.length, "files");
26
+
27
+ async function validateFile(file: string): Promise<number> {
28
+ const moduleId = `/${file}`.replace(/(\.val\.(ts|js))$/, "") as ModuleId; // TODO: check if this always works? (Windows?)
29
+ const start = Date.now();
30
+ const valModule = await service.get(moduleId, "" as ModulePath);
31
+
32
+ if (!valModule.errors) {
33
+ console.log(
34
+ picocolors.green("✔"),
35
+ moduleId,
36
+ "is valid (",
37
+ Date.now() - start,
38
+ "ms)"
39
+ );
40
+ return 0;
41
+ } else {
42
+ let errors = 0;
43
+ if (valModule.errors.validation)
44
+ for (const [sourcePath, validationErrors] of Object.entries(
45
+ valModule.errors.validation
46
+ )) {
47
+ for (const v of validationErrors) {
48
+ if (v.fixes && v.fixes.length > 0) {
49
+ const fixPatch = await createFixPatch(
50
+ { projectRoot },
51
+ !!fix,
52
+ sourcePath as SourcePath,
53
+ v
54
+ );
55
+ if (fix && fixPatch?.patch && fixPatch?.patch.length > 0) {
56
+ await service.patch(moduleId, fixPatch.patch);
57
+ console.log(
58
+ picocolors.green("✔"),
59
+ "Applied fix for",
60
+ sourcePath
61
+ );
62
+ }
63
+ fixPatch?.remainingErrors?.forEach((e) => {
64
+ errors += 1;
65
+ console.log(
66
+ v.fixes ? picocolors.yellow("⚠") : picocolors.red("✘"),
67
+ `Found ${v.fixes ? "fixable " : ""}error in`,
68
+ `${sourcePath}:`,
69
+ e.message
70
+ );
71
+ });
72
+ } else {
73
+ errors += 1;
74
+ console.log(
75
+ picocolors.red("✘"),
76
+ "Found error in",
77
+ `${sourcePath}:`,
78
+ v.message
79
+ );
80
+ }
81
+ }
82
+ }
83
+ for (const fatalError of valModule.errors.fatal || []) {
84
+ errors += 1;
85
+ console.log(
86
+ picocolors.red("✘"),
87
+ moduleId,
88
+ "is invalid:",
89
+ fatalError.message
90
+ );
91
+ }
92
+ return errors;
93
+ }
94
+ }
95
+
96
+ const errors = (await Promise.all(valFiles.map(validateFile))).reduce(
97
+ (a, b) => a + b,
98
+ 0
99
+ );
100
+ if (errors > 0) {
101
+ console.log(
102
+ picocolors.red("✘"),
103
+ "Found",
104
+ errors,
105
+ "validation error" + (errors > 1 ? "s" : "")
106
+ );
107
+ process.exit(1);
108
+ } else {
109
+ console.log(picocolors.green("✔"), "No validation errors found");
110
+ }
111
+
112
+ service.dispose();
113
+ return;
114
+ }