@valbuild/cli 0.90.0 → 0.91.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.
|
@@ -126,6 +126,8 @@ const textEncoder = new TextEncoder();
|
|
|
126
126
|
|
|
127
127
|
// Types for handler system
|
|
128
128
|
|
|
129
|
+
// Cache types for avoiding redundant service.get() calls
|
|
130
|
+
|
|
129
131
|
// Handler functions
|
|
130
132
|
async function handleFileMetadata(ctx) {
|
|
131
133
|
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(ctx.sourcePath);
|
|
@@ -183,7 +185,7 @@ async function handleKeyOfCheck(ctx) {
|
|
|
183
185
|
errorMessage: `Unexpected error in ${sourcePath}: ${ctx.validationError.message} (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)`
|
|
184
186
|
};
|
|
185
187
|
}
|
|
186
|
-
const res = await checkKeyIsValid(key, sourcePath, ctx.service);
|
|
188
|
+
const res = await checkKeyIsValid(key, sourcePath, ctx.service, ctx.keyOfCache);
|
|
187
189
|
if (res.error) {
|
|
188
190
|
return {
|
|
189
191
|
success: false,
|
|
@@ -397,15 +399,28 @@ async function handleRemoteFileCheck() {
|
|
|
397
399
|
}
|
|
398
400
|
|
|
399
401
|
// Helper function
|
|
400
|
-
async function checkKeyIsValid(key, sourcePath, service) {
|
|
402
|
+
async function checkKeyIsValid(key, sourcePath, service, cache) {
|
|
401
403
|
const [moduleFilePath, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
404
|
+
const cacheKey = `${moduleFilePath}::${modulePath}`;
|
|
405
|
+
let keyOfModuleSource;
|
|
406
|
+
let keyOfModuleSchema;
|
|
407
|
+
const cached = cache.get(cacheKey);
|
|
408
|
+
if (cached) {
|
|
409
|
+
keyOfModuleSource = cached.source;
|
|
410
|
+
keyOfModuleSchema = cached.schema;
|
|
411
|
+
} else {
|
|
412
|
+
const keyOfModule = await service.get(moduleFilePath, modulePath, {
|
|
413
|
+
source: true,
|
|
414
|
+
schema: true,
|
|
415
|
+
validate: false
|
|
416
|
+
});
|
|
417
|
+
keyOfModuleSource = keyOfModule.source;
|
|
418
|
+
keyOfModuleSchema = keyOfModule.schema;
|
|
419
|
+
cache.set(cacheKey, {
|
|
420
|
+
source: keyOfModuleSource,
|
|
421
|
+
schema: keyOfModuleSchema
|
|
422
|
+
});
|
|
423
|
+
}
|
|
409
424
|
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
410
425
|
return {
|
|
411
426
|
error: true,
|
|
@@ -434,25 +449,28 @@ async function checkKeyIsValid(key, sourcePath, service) {
|
|
|
434
449
|
* Check if a route is valid by scanning all router modules
|
|
435
450
|
* and validating against include/exclude patterns
|
|
436
451
|
*/
|
|
437
|
-
async function checkRouteIsValid(route, include, exclude, service, valFiles) {
|
|
438
|
-
// 1. Scan all val files to find modules with routers
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
452
|
+
async function checkRouteIsValid(route, include, exclude, service, valFiles, cache) {
|
|
453
|
+
// 1. Scan all val files to find modules with routers (use cache if available)
|
|
454
|
+
if (!cache.loaded) {
|
|
455
|
+
for (const file of valFiles) {
|
|
456
|
+
var _valModule$schema;
|
|
457
|
+
const moduleFilePath = `/${file}`;
|
|
458
|
+
const valModule = await service.get(moduleFilePath, "", {
|
|
459
|
+
source: true,
|
|
460
|
+
schema: true,
|
|
461
|
+
validate: false
|
|
462
|
+
});
|
|
448
463
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
464
|
+
// Check if this module has a router defined
|
|
465
|
+
if (((_valModule$schema = valModule.schema) === null || _valModule$schema === void 0 ? void 0 : _valModule$schema.type) === "record" && valModule.schema.router) {
|
|
466
|
+
if (valModule.source && typeof valModule.source === "object") {
|
|
467
|
+
cache.modules[moduleFilePath] = valModule.source;
|
|
468
|
+
}
|
|
453
469
|
}
|
|
454
470
|
}
|
|
471
|
+
cache.loaded = true;
|
|
455
472
|
}
|
|
473
|
+
const routerModules = cache.modules;
|
|
456
474
|
|
|
457
475
|
// 2. Check if route exists in any router module
|
|
458
476
|
let foundInModule = null;
|
|
@@ -502,7 +520,8 @@ async function handleRouteCheck(ctx) {
|
|
|
502
520
|
sourcePath,
|
|
503
521
|
validationError,
|
|
504
522
|
service,
|
|
505
|
-
valFiles
|
|
523
|
+
valFiles,
|
|
524
|
+
routerModulesCache
|
|
506
525
|
} = ctx;
|
|
507
526
|
|
|
508
527
|
// Extract route and patterns from validation error value
|
|
@@ -516,16 +535,13 @@ async function handleRouteCheck(ctx) {
|
|
|
516
535
|
const route = value.route;
|
|
517
536
|
|
|
518
537
|
// Check if the route is valid
|
|
519
|
-
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles);
|
|
538
|
+
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles, routerModulesCache);
|
|
520
539
|
if (result.error) {
|
|
521
540
|
return {
|
|
522
541
|
success: false,
|
|
523
542
|
errorMessage: `${sourcePath}: ${result.message}`
|
|
524
543
|
};
|
|
525
544
|
}
|
|
526
|
-
|
|
527
|
-
// Route is valid - no fix needed
|
|
528
|
-
console.log(picocolors__default["default"].green("✓"), `Route '${route}' is valid in`, sourcePath);
|
|
529
545
|
return {
|
|
530
546
|
success: true
|
|
531
547
|
};
|
|
@@ -577,6 +593,13 @@ async function validate({
|
|
|
577
593
|
console.log(picocolors__default["default"].greenBright(`Found ${valFiles.length} files...`));
|
|
578
594
|
let publicProjectId;
|
|
579
595
|
let didFix = false;
|
|
596
|
+
|
|
597
|
+
// Create caches that persist across all file validations
|
|
598
|
+
const keyOfCache = new Map();
|
|
599
|
+
const routerModulesCache = {
|
|
600
|
+
loaded: false,
|
|
601
|
+
modules: {}
|
|
602
|
+
};
|
|
580
603
|
async function validateFile(file) {
|
|
581
604
|
const moduleFilePath = `/${file}`; // TODO: check if this always works? (Windows?)
|
|
582
605
|
const start = Date.now();
|
|
@@ -631,7 +654,9 @@ async function validate({
|
|
|
631
654
|
remoteFilesCounter,
|
|
632
655
|
valRemoteHost,
|
|
633
656
|
contentHostUrl,
|
|
634
|
-
valConfigFile: valConfigFile ?? undefined
|
|
657
|
+
valConfigFile: valConfigFile ?? undefined,
|
|
658
|
+
keyOfCache,
|
|
659
|
+
routerModulesCache
|
|
635
660
|
});
|
|
636
661
|
|
|
637
662
|
// Update shared state from handler result
|
|
@@ -126,6 +126,8 @@ const textEncoder = new TextEncoder();
|
|
|
126
126
|
|
|
127
127
|
// Types for handler system
|
|
128
128
|
|
|
129
|
+
// Cache types for avoiding redundant service.get() calls
|
|
130
|
+
|
|
129
131
|
// Handler functions
|
|
130
132
|
async function handleFileMetadata(ctx) {
|
|
131
133
|
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(ctx.sourcePath);
|
|
@@ -183,7 +185,7 @@ async function handleKeyOfCheck(ctx) {
|
|
|
183
185
|
errorMessage: `Unexpected error in ${sourcePath}: ${ctx.validationError.message} (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)`
|
|
184
186
|
};
|
|
185
187
|
}
|
|
186
|
-
const res = await checkKeyIsValid(key, sourcePath, ctx.service);
|
|
188
|
+
const res = await checkKeyIsValid(key, sourcePath, ctx.service, ctx.keyOfCache);
|
|
187
189
|
if (res.error) {
|
|
188
190
|
return {
|
|
189
191
|
success: false,
|
|
@@ -397,15 +399,28 @@ async function handleRemoteFileCheck() {
|
|
|
397
399
|
}
|
|
398
400
|
|
|
399
401
|
// Helper function
|
|
400
|
-
async function checkKeyIsValid(key, sourcePath, service) {
|
|
402
|
+
async function checkKeyIsValid(key, sourcePath, service, cache) {
|
|
401
403
|
const [moduleFilePath, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
404
|
+
const cacheKey = `${moduleFilePath}::${modulePath}`;
|
|
405
|
+
let keyOfModuleSource;
|
|
406
|
+
let keyOfModuleSchema;
|
|
407
|
+
const cached = cache.get(cacheKey);
|
|
408
|
+
if (cached) {
|
|
409
|
+
keyOfModuleSource = cached.source;
|
|
410
|
+
keyOfModuleSchema = cached.schema;
|
|
411
|
+
} else {
|
|
412
|
+
const keyOfModule = await service.get(moduleFilePath, modulePath, {
|
|
413
|
+
source: true,
|
|
414
|
+
schema: true,
|
|
415
|
+
validate: false
|
|
416
|
+
});
|
|
417
|
+
keyOfModuleSource = keyOfModule.source;
|
|
418
|
+
keyOfModuleSchema = keyOfModule.schema;
|
|
419
|
+
cache.set(cacheKey, {
|
|
420
|
+
source: keyOfModuleSource,
|
|
421
|
+
schema: keyOfModuleSchema
|
|
422
|
+
});
|
|
423
|
+
}
|
|
409
424
|
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
410
425
|
return {
|
|
411
426
|
error: true,
|
|
@@ -434,25 +449,28 @@ async function checkKeyIsValid(key, sourcePath, service) {
|
|
|
434
449
|
* Check if a route is valid by scanning all router modules
|
|
435
450
|
* and validating against include/exclude patterns
|
|
436
451
|
*/
|
|
437
|
-
async function checkRouteIsValid(route, include, exclude, service, valFiles) {
|
|
438
|
-
// 1. Scan all val files to find modules with routers
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
452
|
+
async function checkRouteIsValid(route, include, exclude, service, valFiles, cache) {
|
|
453
|
+
// 1. Scan all val files to find modules with routers (use cache if available)
|
|
454
|
+
if (!cache.loaded) {
|
|
455
|
+
for (const file of valFiles) {
|
|
456
|
+
var _valModule$schema;
|
|
457
|
+
const moduleFilePath = `/${file}`;
|
|
458
|
+
const valModule = await service.get(moduleFilePath, "", {
|
|
459
|
+
source: true,
|
|
460
|
+
schema: true,
|
|
461
|
+
validate: false
|
|
462
|
+
});
|
|
448
463
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
464
|
+
// Check if this module has a router defined
|
|
465
|
+
if (((_valModule$schema = valModule.schema) === null || _valModule$schema === void 0 ? void 0 : _valModule$schema.type) === "record" && valModule.schema.router) {
|
|
466
|
+
if (valModule.source && typeof valModule.source === "object") {
|
|
467
|
+
cache.modules[moduleFilePath] = valModule.source;
|
|
468
|
+
}
|
|
453
469
|
}
|
|
454
470
|
}
|
|
471
|
+
cache.loaded = true;
|
|
455
472
|
}
|
|
473
|
+
const routerModules = cache.modules;
|
|
456
474
|
|
|
457
475
|
// 2. Check if route exists in any router module
|
|
458
476
|
let foundInModule = null;
|
|
@@ -502,7 +520,8 @@ async function handleRouteCheck(ctx) {
|
|
|
502
520
|
sourcePath,
|
|
503
521
|
validationError,
|
|
504
522
|
service,
|
|
505
|
-
valFiles
|
|
523
|
+
valFiles,
|
|
524
|
+
routerModulesCache
|
|
506
525
|
} = ctx;
|
|
507
526
|
|
|
508
527
|
// Extract route and patterns from validation error value
|
|
@@ -516,16 +535,13 @@ async function handleRouteCheck(ctx) {
|
|
|
516
535
|
const route = value.route;
|
|
517
536
|
|
|
518
537
|
// Check if the route is valid
|
|
519
|
-
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles);
|
|
538
|
+
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles, routerModulesCache);
|
|
520
539
|
if (result.error) {
|
|
521
540
|
return {
|
|
522
541
|
success: false,
|
|
523
542
|
errorMessage: `${sourcePath}: ${result.message}`
|
|
524
543
|
};
|
|
525
544
|
}
|
|
526
|
-
|
|
527
|
-
// Route is valid - no fix needed
|
|
528
|
-
console.log(picocolors__default["default"].green("✓"), `Route '${route}' is valid in`, sourcePath);
|
|
529
545
|
return {
|
|
530
546
|
success: true
|
|
531
547
|
};
|
|
@@ -577,6 +593,13 @@ async function validate({
|
|
|
577
593
|
console.log(picocolors__default["default"].greenBright(`Found ${valFiles.length} files...`));
|
|
578
594
|
let publicProjectId;
|
|
579
595
|
let didFix = false;
|
|
596
|
+
|
|
597
|
+
// Create caches that persist across all file validations
|
|
598
|
+
const keyOfCache = new Map();
|
|
599
|
+
const routerModulesCache = {
|
|
600
|
+
loaded: false,
|
|
601
|
+
modules: {}
|
|
602
|
+
};
|
|
580
603
|
async function validateFile(file) {
|
|
581
604
|
const moduleFilePath = `/${file}`; // TODO: check if this always works? (Windows?)
|
|
582
605
|
const start = Date.now();
|
|
@@ -631,7 +654,9 @@ async function validate({
|
|
|
631
654
|
remoteFilesCounter,
|
|
632
655
|
valRemoteHost,
|
|
633
656
|
contentHostUrl,
|
|
634
|
-
valConfigFile: valConfigFile ?? undefined
|
|
657
|
+
valConfigFile: valConfigFile ?? undefined,
|
|
658
|
+
keyOfCache,
|
|
659
|
+
routerModulesCache
|
|
635
660
|
});
|
|
636
661
|
|
|
637
662
|
// Update shared state from handler result
|
|
@@ -94,6 +94,8 @@ const textEncoder = new TextEncoder();
|
|
|
94
94
|
|
|
95
95
|
// Types for handler system
|
|
96
96
|
|
|
97
|
+
// Cache types for avoiding redundant service.get() calls
|
|
98
|
+
|
|
97
99
|
// Handler functions
|
|
98
100
|
async function handleFileMetadata(ctx) {
|
|
99
101
|
const [, modulePath] = Internal.splitModuleFilePathAndModulePath(ctx.sourcePath);
|
|
@@ -151,7 +153,7 @@ async function handleKeyOfCheck(ctx) {
|
|
|
151
153
|
errorMessage: `Unexpected error in ${sourcePath}: ${ctx.validationError.message} (Expected value property 'sourcePath' to be a string - this is likely a bug in Val)`
|
|
152
154
|
};
|
|
153
155
|
}
|
|
154
|
-
const res = await checkKeyIsValid(key, sourcePath, ctx.service);
|
|
156
|
+
const res = await checkKeyIsValid(key, sourcePath, ctx.service, ctx.keyOfCache);
|
|
155
157
|
if (res.error) {
|
|
156
158
|
return {
|
|
157
159
|
success: false,
|
|
@@ -365,15 +367,28 @@ async function handleRemoteFileCheck() {
|
|
|
365
367
|
}
|
|
366
368
|
|
|
367
369
|
// Helper function
|
|
368
|
-
async function checkKeyIsValid(key, sourcePath, service) {
|
|
370
|
+
async function checkKeyIsValid(key, sourcePath, service, cache) {
|
|
369
371
|
const [moduleFilePath, modulePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
372
|
+
const cacheKey = `${moduleFilePath}::${modulePath}`;
|
|
373
|
+
let keyOfModuleSource;
|
|
374
|
+
let keyOfModuleSchema;
|
|
375
|
+
const cached = cache.get(cacheKey);
|
|
376
|
+
if (cached) {
|
|
377
|
+
keyOfModuleSource = cached.source;
|
|
378
|
+
keyOfModuleSchema = cached.schema;
|
|
379
|
+
} else {
|
|
380
|
+
const keyOfModule = await service.get(moduleFilePath, modulePath, {
|
|
381
|
+
source: true,
|
|
382
|
+
schema: true,
|
|
383
|
+
validate: false
|
|
384
|
+
});
|
|
385
|
+
keyOfModuleSource = keyOfModule.source;
|
|
386
|
+
keyOfModuleSchema = keyOfModule.schema;
|
|
387
|
+
cache.set(cacheKey, {
|
|
388
|
+
source: keyOfModuleSource,
|
|
389
|
+
schema: keyOfModuleSchema
|
|
390
|
+
});
|
|
391
|
+
}
|
|
377
392
|
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
378
393
|
return {
|
|
379
394
|
error: true,
|
|
@@ -402,25 +417,28 @@ async function checkKeyIsValid(key, sourcePath, service) {
|
|
|
402
417
|
* Check if a route is valid by scanning all router modules
|
|
403
418
|
* and validating against include/exclude patterns
|
|
404
419
|
*/
|
|
405
|
-
async function checkRouteIsValid(route, include, exclude, service, valFiles) {
|
|
406
|
-
// 1. Scan all val files to find modules with routers
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
420
|
+
async function checkRouteIsValid(route, include, exclude, service, valFiles, cache) {
|
|
421
|
+
// 1. Scan all val files to find modules with routers (use cache if available)
|
|
422
|
+
if (!cache.loaded) {
|
|
423
|
+
for (const file of valFiles) {
|
|
424
|
+
var _valModule$schema;
|
|
425
|
+
const moduleFilePath = `/${file}`;
|
|
426
|
+
const valModule = await service.get(moduleFilePath, "", {
|
|
427
|
+
source: true,
|
|
428
|
+
schema: true,
|
|
429
|
+
validate: false
|
|
430
|
+
});
|
|
416
431
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
432
|
+
// Check if this module has a router defined
|
|
433
|
+
if (((_valModule$schema = valModule.schema) === null || _valModule$schema === void 0 ? void 0 : _valModule$schema.type) === "record" && valModule.schema.router) {
|
|
434
|
+
if (valModule.source && typeof valModule.source === "object") {
|
|
435
|
+
cache.modules[moduleFilePath] = valModule.source;
|
|
436
|
+
}
|
|
421
437
|
}
|
|
422
438
|
}
|
|
439
|
+
cache.loaded = true;
|
|
423
440
|
}
|
|
441
|
+
const routerModules = cache.modules;
|
|
424
442
|
|
|
425
443
|
// 2. Check if route exists in any router module
|
|
426
444
|
let foundInModule = null;
|
|
@@ -470,7 +488,8 @@ async function handleRouteCheck(ctx) {
|
|
|
470
488
|
sourcePath,
|
|
471
489
|
validationError,
|
|
472
490
|
service,
|
|
473
|
-
valFiles
|
|
491
|
+
valFiles,
|
|
492
|
+
routerModulesCache
|
|
474
493
|
} = ctx;
|
|
475
494
|
|
|
476
495
|
// Extract route and patterns from validation error value
|
|
@@ -484,16 +503,13 @@ async function handleRouteCheck(ctx) {
|
|
|
484
503
|
const route = value.route;
|
|
485
504
|
|
|
486
505
|
// Check if the route is valid
|
|
487
|
-
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles);
|
|
506
|
+
const result = await checkRouteIsValid(route, value.include, value.exclude, service, valFiles, routerModulesCache);
|
|
488
507
|
if (result.error) {
|
|
489
508
|
return {
|
|
490
509
|
success: false,
|
|
491
510
|
errorMessage: `${sourcePath}: ${result.message}`
|
|
492
511
|
};
|
|
493
512
|
}
|
|
494
|
-
|
|
495
|
-
// Route is valid - no fix needed
|
|
496
|
-
console.log(picocolors.green("✓"), `Route '${route}' is valid in`, sourcePath);
|
|
497
513
|
return {
|
|
498
514
|
success: true
|
|
499
515
|
};
|
|
@@ -545,6 +561,13 @@ async function validate({
|
|
|
545
561
|
console.log(picocolors.greenBright(`Found ${valFiles.length} files...`));
|
|
546
562
|
let publicProjectId;
|
|
547
563
|
let didFix = false;
|
|
564
|
+
|
|
565
|
+
// Create caches that persist across all file validations
|
|
566
|
+
const keyOfCache = new Map();
|
|
567
|
+
const routerModulesCache = {
|
|
568
|
+
loaded: false,
|
|
569
|
+
modules: {}
|
|
570
|
+
};
|
|
548
571
|
async function validateFile(file) {
|
|
549
572
|
const moduleFilePath = `/${file}`; // TODO: check if this always works? (Windows?)
|
|
550
573
|
const start = Date.now();
|
|
@@ -599,7 +622,9 @@ async function validate({
|
|
|
599
622
|
remoteFilesCounter,
|
|
600
623
|
valRemoteHost,
|
|
601
624
|
contentHostUrl,
|
|
602
|
-
valConfigFile: valConfigFile ?? undefined
|
|
625
|
+
valConfigFile: valConfigFile ?? undefined,
|
|
626
|
+
keyOfCache,
|
|
627
|
+
routerModulesCache
|
|
603
628
|
});
|
|
604
629
|
|
|
605
630
|
// Update shared state from handler result
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valbuild/cli",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.91.1",
|
|
5
5
|
"description": "Val CLI tools",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"typecheck": "tsc --noEmit"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@valbuild/core": "~0.
|
|
26
|
-
"@valbuild/eslint-plugin": "~0.
|
|
27
|
-
"@valbuild/server": "~0.
|
|
28
|
-
"@valbuild/shared": "~0.
|
|
25
|
+
"@valbuild/core": "~0.91.1",
|
|
26
|
+
"@valbuild/eslint-plugin": "~0.91.1",
|
|
27
|
+
"@valbuild/server": "~0.91.1",
|
|
28
|
+
"@valbuild/shared": "~0.91.1",
|
|
29
29
|
"chalk": "^4.1.2",
|
|
30
30
|
"cors": "^2.8.5",
|
|
31
31
|
"fast-glob": "^3.3.1",
|
package/src/validate.ts
CHANGED
|
@@ -42,6 +42,16 @@ type ValidationError = {
|
|
|
42
42
|
fixes?: ValidationFix[];
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
// Cache types for avoiding redundant service.get() calls
|
|
46
|
+
type KeyOfCache = Map<
|
|
47
|
+
string, // moduleFilePath + modulePath key
|
|
48
|
+
{ source: unknown; schema: { type: string } | undefined }
|
|
49
|
+
>;
|
|
50
|
+
type RouterModulesCache = {
|
|
51
|
+
loaded: boolean;
|
|
52
|
+
modules: Record<string, Record<string, unknown>>;
|
|
53
|
+
};
|
|
54
|
+
|
|
45
55
|
type FixHandlerContext = {
|
|
46
56
|
sourcePath: SourcePath;
|
|
47
57
|
validationError: ValidationError;
|
|
@@ -63,6 +73,9 @@ type FixHandlerContext = {
|
|
|
63
73
|
valRemoteHost: string;
|
|
64
74
|
contentHostUrl: string;
|
|
65
75
|
valConfigFile?: { project?: string };
|
|
76
|
+
// Caches for validation
|
|
77
|
+
keyOfCache: KeyOfCache;
|
|
78
|
+
routerModulesCache: RouterModulesCache;
|
|
66
79
|
};
|
|
67
80
|
|
|
68
81
|
type FixHandlerResult = {
|
|
@@ -157,7 +170,12 @@ async function handleKeyOfCheck(
|
|
|
157
170
|
};
|
|
158
171
|
}
|
|
159
172
|
|
|
160
|
-
const res = await checkKeyIsValid(
|
|
173
|
+
const res = await checkKeyIsValid(
|
|
174
|
+
key,
|
|
175
|
+
sourcePath,
|
|
176
|
+
ctx.service,
|
|
177
|
+
ctx.keyOfCache,
|
|
178
|
+
);
|
|
161
179
|
if (res.error) {
|
|
162
180
|
return {
|
|
163
181
|
success: false,
|
|
@@ -438,17 +456,33 @@ async function checkKeyIsValid(
|
|
|
438
456
|
key: string,
|
|
439
457
|
sourcePath: string,
|
|
440
458
|
service: Service,
|
|
459
|
+
cache: KeyOfCache,
|
|
441
460
|
): Promise<{ error: false } | { error: true; message: string }> {
|
|
442
461
|
const [moduleFilePath, modulePath] =
|
|
443
462
|
Internal.splitModuleFilePathAndModulePath(sourcePath as SourcePath);
|
|
444
|
-
const keyOfModule = await service.get(moduleFilePath, modulePath, {
|
|
445
|
-
source: true,
|
|
446
|
-
schema: false,
|
|
447
|
-
validate: false,
|
|
448
|
-
});
|
|
449
463
|
|
|
450
|
-
const
|
|
451
|
-
|
|
464
|
+
const cacheKey = `${moduleFilePath}::${modulePath}`;
|
|
465
|
+
let keyOfModuleSource: unknown;
|
|
466
|
+
let keyOfModuleSchema: { type: string } | undefined;
|
|
467
|
+
|
|
468
|
+
const cached = cache.get(cacheKey);
|
|
469
|
+
if (cached) {
|
|
470
|
+
keyOfModuleSource = cached.source;
|
|
471
|
+
keyOfModuleSchema = cached.schema;
|
|
472
|
+
} else {
|
|
473
|
+
const keyOfModule = await service.get(moduleFilePath, modulePath, {
|
|
474
|
+
source: true,
|
|
475
|
+
schema: true,
|
|
476
|
+
validate: false,
|
|
477
|
+
});
|
|
478
|
+
keyOfModuleSource = keyOfModule.source;
|
|
479
|
+
keyOfModuleSchema = keyOfModule.schema as { type: string } | undefined;
|
|
480
|
+
cache.set(cacheKey, {
|
|
481
|
+
source: keyOfModuleSource,
|
|
482
|
+
schema: keyOfModuleSchema,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
452
486
|
if (keyOfModuleSchema && keyOfModuleSchema.type !== "record") {
|
|
453
487
|
return {
|
|
454
488
|
error: true,
|
|
@@ -488,29 +522,33 @@ async function checkRouteIsValid(
|
|
|
488
522
|
exclude: SerializedRegExpPattern | undefined,
|
|
489
523
|
service: Service,
|
|
490
524
|
valFiles: string[],
|
|
525
|
+
cache: RouterModulesCache,
|
|
491
526
|
): Promise<{ error: false } | { error: true; message: string }> {
|
|
492
|
-
// 1. Scan all val files to find modules with routers
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
});
|
|
527
|
+
// 1. Scan all val files to find modules with routers (use cache if available)
|
|
528
|
+
if (!cache.loaded) {
|
|
529
|
+
for (const file of valFiles) {
|
|
530
|
+
const moduleFilePath = `/${file}` as ModuleFilePath;
|
|
531
|
+
const valModule = await service.get(moduleFilePath, "" as ModulePath, {
|
|
532
|
+
source: true,
|
|
533
|
+
schema: true,
|
|
534
|
+
validate: false,
|
|
535
|
+
});
|
|
502
536
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
537
|
+
// Check if this module has a router defined
|
|
538
|
+
if (valModule.schema?.type === "record" && valModule.schema.router) {
|
|
539
|
+
if (valModule.source && typeof valModule.source === "object") {
|
|
540
|
+
cache.modules[moduleFilePath] = valModule.source as Record<
|
|
541
|
+
string,
|
|
542
|
+
unknown
|
|
543
|
+
>;
|
|
544
|
+
}
|
|
510
545
|
}
|
|
511
546
|
}
|
|
547
|
+
cache.loaded = true;
|
|
512
548
|
}
|
|
513
549
|
|
|
550
|
+
const routerModules = cache.modules;
|
|
551
|
+
|
|
514
552
|
// 2. Check if route exists in any router module
|
|
515
553
|
let foundInModule: string | null = null;
|
|
516
554
|
for (const [moduleFilePath, source] of Object.entries(routerModules)) {
|
|
@@ -569,7 +607,8 @@ async function checkRouteIsValid(
|
|
|
569
607
|
async function handleRouteCheck(
|
|
570
608
|
ctx: FixHandlerContext,
|
|
571
609
|
): Promise<FixHandlerResult> {
|
|
572
|
-
const { sourcePath, validationError, service, valFiles } =
|
|
610
|
+
const { sourcePath, validationError, service, valFiles, routerModulesCache } =
|
|
611
|
+
ctx;
|
|
573
612
|
|
|
574
613
|
// Extract route and patterns from validation error value
|
|
575
614
|
const value = validationError.value as
|
|
@@ -596,6 +635,7 @@ async function handleRouteCheck(
|
|
|
596
635
|
value.exclude,
|
|
597
636
|
service,
|
|
598
637
|
valFiles,
|
|
638
|
+
routerModulesCache,
|
|
599
639
|
);
|
|
600
640
|
|
|
601
641
|
if (result.error) {
|
|
@@ -605,12 +645,6 @@ async function handleRouteCheck(
|
|
|
605
645
|
};
|
|
606
646
|
}
|
|
607
647
|
|
|
608
|
-
// Route is valid - no fix needed
|
|
609
|
-
console.log(
|
|
610
|
-
picocolors.green("✓"),
|
|
611
|
-
`Route '${route}' is valid in`,
|
|
612
|
-
sourcePath,
|
|
613
|
-
);
|
|
614
648
|
return { success: true };
|
|
615
649
|
}
|
|
616
650
|
|
|
@@ -672,6 +706,11 @@ export async function validate({
|
|
|
672
706
|
console.log(picocolors.greenBright(`Found ${valFiles.length} files...`));
|
|
673
707
|
let publicProjectId: string | undefined;
|
|
674
708
|
let didFix = false;
|
|
709
|
+
|
|
710
|
+
// Create caches that persist across all file validations
|
|
711
|
+
const keyOfCache: KeyOfCache = new Map();
|
|
712
|
+
const routerModulesCache: RouterModulesCache = { loaded: false, modules: {} };
|
|
713
|
+
|
|
675
714
|
async function validateFile(file: string): Promise<number> {
|
|
676
715
|
const moduleFilePath = `/${file}` as ModuleFilePath; // TODO: check if this always works? (Windows?)
|
|
677
716
|
const start = Date.now();
|
|
@@ -748,6 +787,8 @@ export async function validate({
|
|
|
748
787
|
valRemoteHost,
|
|
749
788
|
contentHostUrl,
|
|
750
789
|
valConfigFile: valConfigFile ?? undefined,
|
|
790
|
+
keyOfCache,
|
|
791
|
+
routerModulesCache,
|
|
751
792
|
});
|
|
752
793
|
|
|
753
794
|
// Update shared state from handler result
|