@valbuild/cli 0.72.0 → 0.72.1

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.
@@ -51,6 +51,38 @@ async function validate({
51
51
  ignore: false
52
52
  });
53
53
  const service = await server.createService(projectRoot, {});
54
+ const checkKeyIsValid = async (key, sourcePath) => {
55
+ const [moduleFilePath, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
56
+ const keyOfModule = await service.get(moduleFilePath, modulePath, {
57
+ source: true,
58
+ schema: false,
59
+ validate: false
60
+ });
61
+ const keyOfModuleSource = keyOfModule.source;
62
+ const keyOfModuleSchema = keyOfModule.schema;
63
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
64
+ return {
65
+ error: true,
66
+ message: `Expected key at ${sourcePath} to be of type 'record'`
67
+ };
68
+ }
69
+ if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
70
+ return {
71
+ error: false
72
+ };
73
+ }
74
+ if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
75
+ return {
76
+ error: true,
77
+ message: `Expected ${sourcePath} to be a truthy object`
78
+ };
79
+ }
80
+ const alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
81
+ return {
82
+ error: true,
83
+ message: `Key '${key}' does not exist in ${sourcePath}. Closest match: '${alternatives[0].target}'. Other similar: ${alternatives.slice(1, 4).map(a => `'${a.target}'`).join(", ")}${alternatives.length > 4 ? ", ..." : ""}`
84
+ };
85
+ };
54
86
  let prettier;
55
87
  try {
56
88
  prettier = (await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('prettier')); })).default;
@@ -130,6 +162,36 @@ async function validate({
130
162
  continue;
131
163
  }
132
164
  }
165
+ } else if (v.fixes.includes("keyof:check-keys")) {
166
+ const prevErrors = errors;
167
+ if (v.value && typeof v.value === "object" && "key" in v.value && "sourcePath" in v.value) {
168
+ const {
169
+ key,
170
+ sourcePath
171
+ } = v.value;
172
+ if (typeof key !== "string") {
173
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'key' to be a string - this is likely a bug in Val)");
174
+ errors += 1;
175
+ } else if (typeof sourcePath !== "string") {
176
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)");
177
+ errors += 1;
178
+ } else {
179
+ const res = await checkKeyIsValid(key, sourcePath);
180
+ if (res.error) {
181
+ console.log(picocolors__default["default"].red("✘"), res.message);
182
+ errors += 1;
183
+ }
184
+ }
185
+ } else {
186
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value to be an object with 'key' and 'sourcePath' properties - this is likely a bug in Val)");
187
+ errors += 1;
188
+ }
189
+ if (prevErrors < errors) {
190
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}`);
191
+ }
192
+ } else {
193
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}:`, v.message);
194
+ errors += 1;
133
195
  }
134
196
  const fixPatch = await server.createFixPatch({
135
197
  projectRoot
@@ -160,7 +222,7 @@ async function validate({
160
222
  return errors;
161
223
  }
162
224
  }
163
- for (const file of valFiles) {
225
+ for (const file of valFiles.sort()) {
164
226
  didFix = false;
165
227
  errors += await validateFile(file);
166
228
  if (prettier && didFix) {
@@ -205,6 +267,31 @@ function logEslintMessage(fileContent, filePath, eslintMessage) {
205
267
  }
206
268
  }
207
269
 
270
+ // GPT generated levenshtein distance algorithm:
271
+ const levenshtein = (a, b) => {
272
+ const [m, n] = [a.length, b.length];
273
+ if (!m || !n) return Math.max(m, n);
274
+ const dp = Array.from({
275
+ length: m + 1
276
+ }, (_, i) => i);
277
+ for (let j = 1; j <= n; j++) {
278
+ let prev = dp[0];
279
+ dp[0] = j;
280
+ for (let i = 1; i <= m; i++) {
281
+ const temp = dp[i];
282
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
283
+ prev = temp;
284
+ }
285
+ }
286
+ return dp[m];
287
+ };
288
+ function findSimilar(key, targets) {
289
+ return targets.map(target => ({
290
+ target,
291
+ distance: levenshtein(key, target)
292
+ })).sort((a, b) => a.distance - b.distance);
293
+ }
294
+
208
295
  async function files({
209
296
  root,
210
297
  managedDir
@@ -51,6 +51,38 @@ async function validate({
51
51
  ignore: false
52
52
  });
53
53
  const service = await server.createService(projectRoot, {});
54
+ const checkKeyIsValid = async (key, sourcePath) => {
55
+ const [moduleFilePath, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
56
+ const keyOfModule = await service.get(moduleFilePath, modulePath, {
57
+ source: true,
58
+ schema: false,
59
+ validate: false
60
+ });
61
+ const keyOfModuleSource = keyOfModule.source;
62
+ const keyOfModuleSchema = keyOfModule.schema;
63
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
64
+ return {
65
+ error: true,
66
+ message: `Expected key at ${sourcePath} to be of type 'record'`
67
+ };
68
+ }
69
+ if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
70
+ return {
71
+ error: false
72
+ };
73
+ }
74
+ if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
75
+ return {
76
+ error: true,
77
+ message: `Expected ${sourcePath} to be a truthy object`
78
+ };
79
+ }
80
+ const alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
81
+ return {
82
+ error: true,
83
+ message: `Key '${key}' does not exist in ${sourcePath}. Closest match: '${alternatives[0].target}'. Other similar: ${alternatives.slice(1, 4).map(a => `'${a.target}'`).join(", ")}${alternatives.length > 4 ? ", ..." : ""}`
84
+ };
85
+ };
54
86
  let prettier;
55
87
  try {
56
88
  prettier = (await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('prettier')); })).default;
@@ -130,6 +162,36 @@ async function validate({
130
162
  continue;
131
163
  }
132
164
  }
165
+ } else if (v.fixes.includes("keyof:check-keys")) {
166
+ const prevErrors = errors;
167
+ if (v.value && typeof v.value === "object" && "key" in v.value && "sourcePath" in v.value) {
168
+ const {
169
+ key,
170
+ sourcePath
171
+ } = v.value;
172
+ if (typeof key !== "string") {
173
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'key' to be a string - this is likely a bug in Val)");
174
+ errors += 1;
175
+ } else if (typeof sourcePath !== "string") {
176
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)");
177
+ errors += 1;
178
+ } else {
179
+ const res = await checkKeyIsValid(key, sourcePath);
180
+ if (res.error) {
181
+ console.log(picocolors__default["default"].red("✘"), res.message);
182
+ errors += 1;
183
+ }
184
+ }
185
+ } else {
186
+ console.log(picocolors__default["default"].red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value to be an object with 'key' and 'sourcePath' properties - this is likely a bug in Val)");
187
+ errors += 1;
188
+ }
189
+ if (prevErrors < errors) {
190
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}`);
191
+ }
192
+ } else {
193
+ console.log(picocolors__default["default"].red("✘"), "Found error in", `${sourcePath}:`, v.message);
194
+ errors += 1;
133
195
  }
134
196
  const fixPatch = await server.createFixPatch({
135
197
  projectRoot
@@ -160,7 +222,7 @@ async function validate({
160
222
  return errors;
161
223
  }
162
224
  }
163
- for (const file of valFiles) {
225
+ for (const file of valFiles.sort()) {
164
226
  didFix = false;
165
227
  errors += await validateFile(file);
166
228
  if (prettier && didFix) {
@@ -205,6 +267,31 @@ function logEslintMessage(fileContent, filePath, eslintMessage) {
205
267
  }
206
268
  }
207
269
 
270
+ // GPT generated levenshtein distance algorithm:
271
+ const levenshtein = (a, b) => {
272
+ const [m, n] = [a.length, b.length];
273
+ if (!m || !n) return Math.max(m, n);
274
+ const dp = Array.from({
275
+ length: m + 1
276
+ }, (_, i) => i);
277
+ for (let j = 1; j <= n; j++) {
278
+ let prev = dp[0];
279
+ dp[0] = j;
280
+ for (let i = 1; i <= m; i++) {
281
+ const temp = dp[i];
282
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
283
+ prev = temp;
284
+ }
285
+ }
286
+ return dp[m];
287
+ };
288
+ function findSimilar(key, targets) {
289
+ return targets.map(target => ({
290
+ target,
291
+ distance: levenshtein(key, target)
292
+ })).sort((a, b) => a.distance - b.distance);
293
+ }
294
+
208
295
  async function files({
209
296
  root,
210
297
  managedDir
@@ -23,6 +23,38 @@ async function validate({
23
23
  ignore: false
24
24
  });
25
25
  const service = await createService(projectRoot, {});
26
+ const checkKeyIsValid = async (key, sourcePath) => {
27
+ const [moduleFilePath, modulePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
28
+ const keyOfModule = await service.get(moduleFilePath, modulePath, {
29
+ source: true,
30
+ schema: false,
31
+ validate: false
32
+ });
33
+ const keyOfModuleSource = keyOfModule.source;
34
+ const keyOfModuleSchema = keyOfModule.schema;
35
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
36
+ return {
37
+ error: true,
38
+ message: `Expected key at ${sourcePath} to be of type 'record'`
39
+ };
40
+ }
41
+ if (keyOfModuleSource && typeof keyOfModuleSource === "object" && key in keyOfModuleSource) {
42
+ return {
43
+ error: false
44
+ };
45
+ }
46
+ if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
47
+ return {
48
+ error: true,
49
+ message: `Expected ${sourcePath} to be a truthy object`
50
+ };
51
+ }
52
+ const alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
53
+ return {
54
+ error: true,
55
+ message: `Key '${key}' does not exist in ${sourcePath}. Closest match: '${alternatives[0].target}'. Other similar: ${alternatives.slice(1, 4).map(a => `'${a.target}'`).join(", ")}${alternatives.length > 4 ? ", ..." : ""}`
56
+ };
57
+ };
26
58
  let prettier;
27
59
  try {
28
60
  prettier = (await import('prettier')).default;
@@ -102,6 +134,36 @@ async function validate({
102
134
  continue;
103
135
  }
104
136
  }
137
+ } else if (v.fixes.includes("keyof:check-keys")) {
138
+ const prevErrors = errors;
139
+ if (v.value && typeof v.value === "object" && "key" in v.value && "sourcePath" in v.value) {
140
+ const {
141
+ key,
142
+ sourcePath
143
+ } = v.value;
144
+ if (typeof key !== "string") {
145
+ console.log(picocolors.red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'key' to be a string - this is likely a bug in Val)");
146
+ errors += 1;
147
+ } else if (typeof sourcePath !== "string") {
148
+ console.log(picocolors.red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)");
149
+ errors += 1;
150
+ } else {
151
+ const res = await checkKeyIsValid(key, sourcePath);
152
+ if (res.error) {
153
+ console.log(picocolors.red("✘"), res.message);
154
+ errors += 1;
155
+ }
156
+ }
157
+ } else {
158
+ console.log(picocolors.red("✘"), "Unexpected error in", `${sourcePath}:`, v.message, " (Expected value to be an object with 'key' and 'sourcePath' properties - this is likely a bug in Val)");
159
+ errors += 1;
160
+ }
161
+ if (prevErrors < errors) {
162
+ console.log(picocolors.red("✘"), "Found error in", `${sourcePath}`);
163
+ }
164
+ } else {
165
+ console.log(picocolors.red("✘"), "Found error in", `${sourcePath}:`, v.message);
166
+ errors += 1;
105
167
  }
106
168
  const fixPatch = await createFixPatch({
107
169
  projectRoot
@@ -132,7 +194,7 @@ async function validate({
132
194
  return errors;
133
195
  }
134
196
  }
135
- for (const file of valFiles) {
197
+ for (const file of valFiles.sort()) {
136
198
  didFix = false;
137
199
  errors += await validateFile(file);
138
200
  if (prettier && didFix) {
@@ -177,6 +239,31 @@ function logEslintMessage(fileContent, filePath, eslintMessage) {
177
239
  }
178
240
  }
179
241
 
242
+ // GPT generated levenshtein distance algorithm:
243
+ const levenshtein = (a, b) => {
244
+ const [m, n] = [a.length, b.length];
245
+ if (!m || !n) return Math.max(m, n);
246
+ const dp = Array.from({
247
+ length: m + 1
248
+ }, (_, i) => i);
249
+ for (let j = 1; j <= n; j++) {
250
+ let prev = dp[0];
251
+ dp[0] = j;
252
+ for (let i = 1; i <= m; i++) {
253
+ const temp = dp[i];
254
+ dp[i] = a[i - 1] === b[j - 1] ? prev : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
255
+ prev = temp;
256
+ }
257
+ }
258
+ return dp[m];
259
+ };
260
+ function findSimilar(key, targets) {
261
+ return targets.map(target => ({
262
+ target,
263
+ distance: levenshtein(key, target)
264
+ })).sort((a, b) => a.distance - b.distance);
265
+ }
266
+
180
267
  async function files({
181
268
  root,
182
269
  managedDir
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valbuild/cli",
3
3
  "private": false,
4
- "version": "0.72.0",
4
+ "version": "0.72.1",
5
5
  "description": "Val CLI tools",
6
6
  "bin": {
7
7
  "val": "./bin.js"
@@ -18,9 +18,9 @@
18
18
  "typecheck": "tsc --noEmit"
19
19
  },
20
20
  "dependencies": {
21
- "@valbuild/core": "~0.72.0",
22
- "@valbuild/server": "~0.72.0",
23
- "@valbuild/eslint-plugin": "~0.70.0",
21
+ "@valbuild/core": "~0.72.1",
22
+ "@valbuild/server": "~0.72.1",
23
+ "@valbuild/eslint-plugin": "~0.72.1",
24
24
  "eslint": "^8.31.0",
25
25
  "@inquirer/confirm": "^2.0.15",
26
26
  "@inquirer/prompts": "^3.0.2",
package/src/validate.ts CHANGED
@@ -28,6 +28,48 @@ export async function validate({
28
28
  ignore: false,
29
29
  });
30
30
  const service = await createService(projectRoot, {});
31
+ const checkKeyIsValid = async (
32
+ key: string,
33
+ sourcePath: string,
34
+ ): Promise<{ error: false } | { error: true; message: string }> => {
35
+ const [moduleFilePath, modulePath] =
36
+ Internal.splitModuleFilePathAndModulePath(sourcePath as SourcePath);
37
+ const keyOfModule = await service.get(moduleFilePath, modulePath, {
38
+ source: true,
39
+ schema: false,
40
+ validate: false,
41
+ });
42
+
43
+ const keyOfModuleSource = keyOfModule.source;
44
+ const keyOfModuleSchema = keyOfModule.schema;
45
+ if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
46
+ return {
47
+ error: true,
48
+ message: `Expected key at ${sourcePath} to be of type 'record'`,
49
+ };
50
+ }
51
+ if (
52
+ keyOfModuleSource &&
53
+ typeof keyOfModuleSource === "object" &&
54
+ key in keyOfModuleSource
55
+ ) {
56
+ return { error: false };
57
+ }
58
+ if (!keyOfModuleSource || typeof keyOfModuleSource !== "object") {
59
+ return {
60
+ error: true,
61
+ message: `Expected ${sourcePath} to be a truthy object`,
62
+ };
63
+ }
64
+ const alternatives = findSimilar(key, Object.keys(keyOfModuleSource));
65
+ return {
66
+ error: true,
67
+ message: `Key '${key}' does not exist in ${sourcePath}. Closest match: '${alternatives[0].target}'. Other similar: ${alternatives
68
+ .slice(1, 4)
69
+ .map((a) => `'${a.target}'`)
70
+ .join(", ")}${alternatives.length > 4 ? ", ..." : ""}`,
71
+ };
72
+ };
31
73
  let prettier;
32
74
  try {
33
75
  prettier = (await import("prettier")).default;
@@ -152,6 +194,65 @@ export async function validate({
152
194
  continue;
153
195
  }
154
196
  }
197
+ } else if (v.fixes.includes("keyof:check-keys")) {
198
+ const prevErrors = errors;
199
+ if (
200
+ v.value &&
201
+ typeof v.value === "object" &&
202
+ "key" in v.value &&
203
+ "sourcePath" in v.value
204
+ ) {
205
+ const { key, sourcePath } = v.value;
206
+ if (typeof key !== "string") {
207
+ console.log(
208
+ picocolors.red("✘"),
209
+ "Unexpected error in",
210
+ `${sourcePath}:`,
211
+ v.message,
212
+ " (Expected value property 'key' to be a string - this is likely a bug in Val)",
213
+ );
214
+ errors += 1;
215
+ } else if (typeof sourcePath !== "string") {
216
+ console.log(
217
+ picocolors.red("✘"),
218
+ "Unexpected error in",
219
+ `${sourcePath}:`,
220
+ v.message,
221
+ " (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)",
222
+ );
223
+ errors += 1;
224
+ } else {
225
+ const res = await checkKeyIsValid(key, sourcePath);
226
+ if (res.error) {
227
+ console.log(picocolors.red("✘"), res.message);
228
+ errors += 1;
229
+ }
230
+ }
231
+ } else {
232
+ console.log(
233
+ picocolors.red("✘"),
234
+ "Unexpected error in",
235
+ `${sourcePath}:`,
236
+ v.message,
237
+ " (Expected value to be an object with 'key' and 'sourcePath' properties - this is likely a bug in Val)",
238
+ );
239
+ errors += 1;
240
+ }
241
+ if (prevErrors < errors) {
242
+ console.log(
243
+ picocolors.red("✘"),
244
+ "Found error in",
245
+ `${sourcePath}`,
246
+ );
247
+ }
248
+ } else {
249
+ console.log(
250
+ picocolors.red("✘"),
251
+ "Found error in",
252
+ `${sourcePath}:`,
253
+ v.message,
254
+ );
255
+ errors += 1;
155
256
  }
156
257
  const fixPatch = await createFixPatch(
157
258
  { projectRoot },
@@ -209,7 +310,7 @@ export async function validate({
209
310
  }
210
311
  }
211
312
 
212
- for (const file of valFiles) {
313
+ for (const file of valFiles.sort()) {
213
314
  didFix = false;
214
315
  errors += await validateFile(file);
215
316
  if (prettier && didFix) {
@@ -289,3 +390,33 @@ function logEslintMessage(
289
390
  );
290
391
  }
291
392
  }
393
+
394
+ // GPT generated levenshtein distance algorithm:
395
+ const levenshtein = (a: string, b: string): number => {
396
+ const [m, n] = [a.length, b.length];
397
+ if (!m || !n) return Math.max(m, n);
398
+
399
+ const dp = Array.from({ length: m + 1 }, (_, i) => i);
400
+
401
+ for (let j = 1; j <= n; j++) {
402
+ let prev = dp[0];
403
+ dp[0] = j;
404
+
405
+ for (let i = 1; i <= m; i++) {
406
+ const temp = dp[i];
407
+ dp[i] =
408
+ a[i - 1] === b[j - 1]
409
+ ? prev
410
+ : Math.min(prev + 1, dp[i - 1] + 1, dp[i] + 1);
411
+ prev = temp;
412
+ }
413
+ }
414
+
415
+ return dp[m];
416
+ };
417
+
418
+ function findSimilar(key: string, targets: string[]) {
419
+ return targets
420
+ .map((target) => ({ target, distance: levenshtein(key, target) }))
421
+ .sort((a, b) => a.distance - b.distance);
422
+ }