@valbuild/cli 0.15.0 → 0.17.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,8 +97,9 @@ 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({
37
- service
100
+ const valReqHandler = server.createRequestHandler(new server.LocalValServer({
101
+ service,
102
+ git: await server.safeReadGit(projectRoot)
38
103
  }));
39
104
  const app = express__default["default"]();
40
105
  // TODO: Properly configure CORS
@@ -75,12 +140,14 @@ async function main() {
75
140
  $ val [command]
76
141
  Commands
77
142
  serve Run val development server
143
+ validate val-idate val modules
78
144
 
79
145
  Options
80
146
  --help Show this message
81
147
  --port [port], -p [port] Set server port (default 4123)
82
148
  --root [root], -r [root] Set project root directory (default process.cwd())
83
149
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
150
+ --fix [fix] Attempt to fix validation errors
84
151
  `, {
85
152
  flags: {
86
153
  port: {
@@ -95,6 +162,9 @@ async function main() {
95
162
  cfg: {
96
163
  type: "string",
97
164
  alias: "c"
165
+ },
166
+ fix: {
167
+ type: "boolean"
98
168
  }
99
169
  },
100
170
  hardRejection: false
@@ -113,11 +183,18 @@ async function main() {
113
183
  port: flags.port,
114
184
  cfg: flags.cfg
115
185
  });
186
+ case "validate":
187
+ case "idate":
188
+ return validate({
189
+ root: flags.root,
190
+ cfg: flags.cfg,
191
+ fix: flags.fix
192
+ });
116
193
  default:
117
194
  return error(`Unknown command "${input.join(" ")}"`);
118
195
  }
119
196
  }
120
197
  void main().catch(err => {
121
- error(err);
198
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
122
199
  process.exitCode = 1;
123
200
  });
@@ -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,8 +97,9 @@ 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({
37
- service
100
+ const valReqHandler = server.createRequestHandler(new server.LocalValServer({
101
+ service,
102
+ git: await server.safeReadGit(projectRoot)
38
103
  }));
39
104
  const app = express__default["default"]();
40
105
  // TODO: Properly configure CORS
@@ -75,12 +140,14 @@ async function main() {
75
140
  $ val [command]
76
141
  Commands
77
142
  serve Run val development server
143
+ validate val-idate val modules
78
144
 
79
145
  Options
80
146
  --help Show this message
81
147
  --port [port], -p [port] Set server port (default 4123)
82
148
  --root [root], -r [root] Set project root directory (default process.cwd())
83
149
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
150
+ --fix [fix] Attempt to fix validation errors
84
151
  `, {
85
152
  flags: {
86
153
  port: {
@@ -95,6 +162,9 @@ async function main() {
95
162
  cfg: {
96
163
  type: "string",
97
164
  alias: "c"
165
+ },
166
+ fix: {
167
+ type: "boolean"
98
168
  }
99
169
  },
100
170
  hardRejection: false
@@ -113,11 +183,18 @@ async function main() {
113
183
  port: flags.port,
114
184
  cfg: flags.cfg
115
185
  });
186
+ case "validate":
187
+ case "idate":
188
+ return validate({
189
+ root: flags.root,
190
+ cfg: flags.cfg,
191
+ fix: flags.fix
192
+ });
116
193
  default:
117
194
  return error(`Unknown command "${input.join(" ")}"`);
118
195
  }
119
196
  }
120
197
  void main().catch(err => {
121
- error(err);
198
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
122
199
  process.exitCode = 1;
123
200
  });
@@ -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, safeReadGit } 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,
@@ -24,7 +87,8 @@ async function serve({
24
87
  valConfigPath: cfg ?? "./val.config"
25
88
  });
26
89
  const valReqHandler = createRequestHandler(new LocalValServer({
27
- service
90
+ service,
91
+ git: await safeReadGit(projectRoot)
28
92
  }));
29
93
  const app = express();
30
94
  // TODO: Properly configure CORS
@@ -65,12 +129,14 @@ async function main() {
65
129
  $ val [command]
66
130
  Commands
67
131
  serve Run val development server
132
+ validate val-idate val modules
68
133
 
69
134
  Options
70
135
  --help Show this message
71
136
  --port [port], -p [port] Set server port (default 4123)
72
137
  --root [root], -r [root] Set project root directory (default process.cwd())
73
138
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
139
+ --fix [fix] Attempt to fix validation errors
74
140
  `, {
75
141
  flags: {
76
142
  port: {
@@ -85,6 +151,9 @@ async function main() {
85
151
  cfg: {
86
152
  type: "string",
87
153
  alias: "c"
154
+ },
155
+ fix: {
156
+ type: "boolean"
88
157
  }
89
158
  },
90
159
  hardRejection: false
@@ -103,11 +172,18 @@ async function main() {
103
172
  port: flags.port,
104
173
  cfg: flags.cfg
105
174
  });
175
+ case "validate":
176
+ case "idate":
177
+ return validate({
178
+ root: flags.root,
179
+ cfg: flags.cfg,
180
+ fix: flags.fix
181
+ });
106
182
  default:
107
183
  return error(`Unknown command "${input.join(" ")}"`);
108
184
  }
109
185
  }
110
186
  void main().catch(err => {
111
- error(err);
187
+ error(err instanceof Error ? err.message + "\n" + err.stack : typeof err === "object" ? JSON.stringify(err, null, 2) : err);
112
188
  process.exitCode = 1;
113
189
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valbuild/cli",
3
3
  "private": false,
4
- "version": "0.15.0",
4
+ "version": "0.17.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.15.0",
20
+ "@valbuild/server": "~0.17.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
@@ -1,11 +1,16 @@
1
1
  import path from "path";
2
2
  import meow from "meow";
3
- import { createRequestHandler, createService } from "@valbuild/server";
3
+ import {
4
+ createRequestHandler,
5
+ createService,
6
+ safeReadGit,
7
+ } from "@valbuild/server";
4
8
  import { error, info } from "./logger";
5
9
  import express from "express";
6
10
  import cors from "cors";
7
11
  import { createServer, Server } from "node:http";
8
- import { LocalValServer } from "@valbuild/server/src/LocalValServer";
12
+ import { LocalValServer } from "@valbuild/server";
13
+ import { validate } from "./validate";
9
14
 
10
15
  async function serve({
11
16
  root,
@@ -23,6 +28,7 @@ async function serve({
23
28
  const valReqHandler = createRequestHandler(
24
29
  new LocalValServer({
25
30
  service,
31
+ git: await safeReadGit(projectRoot),
26
32
  })
27
33
  );
28
34
  const app = express();
@@ -68,12 +74,14 @@ async function main(): Promise<void> {
68
74
  $ val [command]
69
75
  Commands
70
76
  serve Run val development server
77
+ validate val-idate val modules
71
78
 
72
79
  Options
73
80
  --help Show this message
74
81
  --port [port], -p [port] Set server port (default 4123)
75
82
  --root [root], -r [root] Set project root directory (default process.cwd())
76
83
  --cfg [cfg], -c [cfg] Set path to config relative to root (default ./val.config)
84
+ --fix [fix] Attempt to fix validation errors
77
85
  `,
78
86
  {
79
87
  flags: {
@@ -90,6 +98,9 @@ async function main(): Promise<void> {
90
98
  type: "string",
91
99
  alias: "c",
92
100
  },
101
+ fix: {
102
+ type: "boolean",
103
+ },
93
104
  },
94
105
  hardRejection: false,
95
106
  }
@@ -111,12 +122,25 @@ async function main(): Promise<void> {
111
122
  port: flags.port,
112
123
  cfg: flags.cfg,
113
124
  });
125
+ case "validate":
126
+ case "idate":
127
+ return validate({
128
+ root: flags.root,
129
+ cfg: flags.cfg,
130
+ fix: flags.fix,
131
+ });
114
132
  default:
115
133
  return error(`Unknown command "${input.join(" ")}"`);
116
134
  }
117
135
  }
118
136
 
119
137
  void main().catch((err) => {
120
- error(err);
138
+ error(
139
+ err instanceof Error
140
+ ? err.message + "\n" + err.stack
141
+ : typeof err === "object"
142
+ ? JSON.stringify(err, null, 2)
143
+ : err
144
+ );
121
145
  process.exitCode = 1;
122
146
  });
@@ -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
+ }