A Deno tool to validate that all occurrences of Sections, Loaders, and Actions (in deco.cx blocks and pages) have data structures compatible with their TypeScript types.
The tool detects several types of unused code:
| Type | Detection | Auto-Removal |
|---|---|---|
| Unused Sections | β Detected | β
With -rm-sections |
| Unused Loaders | β Detected | β Manual only* |
| Unused Actions | β Detected | β Manual only* |
| Unused Properties | β
With -unused |
β
With -rm-vars |
*Loaders and actions are not auto-removed because they may be imported dynamically or called programmatically.
When using -rm-sections, the tool performs import analysis to avoid false positives:
- Scans all TypeScript files in the project for import statements
- Identifies files that are imported in code (e.g.,
import { helper } from "site/sections/Utils/Helper.tsx") - Excludes imported files from the removal list, even if they don't appear in block configurations
This prevents accidentally deleting utility sections or helper files that are used programmatically.
The tool automatically detects common issues in block configurations:
| Issue | Description | Action |
|---|---|---|
| Disabled Variants | Variants with never matcher rule |
|
| Lazy wrapping Multivariate | Lazy section containing a multivariate inside |
Performance issue - multivariate should wrap Lazy, not the other way around |
Variants with a never matcher are intentionally disabled content, not dead code. Common uses include:
- Seasonal campaigns (Black Friday, Christmas, Back to School, etc.)
- A/B test variants that are temporarily paused
- Content templates preserved for future campaigns
- Historical content kept for reference
Never automatically delete these! They can be reactivated by simply changing the matcher rule.
π¨ ISSUES DETECTED
βΈοΈ Disabled Variants (3 sections with 'never' matcher):
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β οΈ WARNING: These are NOT dead code! DO NOT DELETE! β
β These are intentionally disabled campaigns/content that can be β
β reactivated by changing the matcher. Common uses: β
β β’ Seasonal campaigns (Black Friday, Christmas, etc.) β
β β’ A/B test variants that are paused β
β β’ Content templates for future campaigns β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π pages-Home-287364.json: 2 disabled variant(s)
π pages-category-7493d4.json: 1 disabled variant(s)
β οΈ Lazy wrapping Multivariate (1 instances):
π pages-productpage-ce4850.json
Path: sections[5].value
Lazy wrapping multivariate is an anti-pattern. Multivariate should wrap Lazy, not the other way around.
Issue counts are included in the validation report when using -report.
No installation needed - just run from any deco site directory:
# Validate all sections, loaders, and actions
deno run -A https://deco.cx/validate
# Generate a JSON report
deno run -A https://deco.cx/validate -report validation-report.jsonAdd to your site's deno.json for convenience:
{
"tasks": {
"validate-blocks": "deno run -A https://deco.cx/validate"
}
}Then run:
deno task validate-blocksdeno run -A https://deco.cx/validatedeno run -A https://deco.cx/validate sections/Footer/Footer.tsxYou can use relative or absolute paths.
By default, the script searches for JSONs in .deco/blocks. You can specify another path:
deno run -A https://deco.cx/validate -blocks /full/path/to/jsonsThis allows running the script in one project and validating blocks from another project.
By default, the script does not show warnings for properties not defined in the types. Use this flag to include them:
deno run -A https://deco.cx/validate -unusedSpecifies a custom path for the directory containing JSON blocks. Defaults to .deco/blocks:
deno run -A https://deco.cx/validate -blocks /full/path/to/jsonsRemoves all properties that are not defined in the types:
deno run -A https://deco.cx/validate -rm-varsThe script:
- Identifies properties in the JSON that don't exist in the
Propsinterface - Removes these properties automatically
- Saves the modified JSON file
Example:
If the JSON has:
{
"__resolveType": "site/sections/Footer/Footer.tsx",
"title": "Footer",
"teste": "unused value" // <- not in Props interface
}After running -rm-vars, the JSON becomes:
{
"__resolveType": "site/sections/Footer/Footer.tsx",
"title": "Footer"
}Removes all section files that are not referenced in any JSON:
deno run -A https://deco.cx/validate -rm-sectionsThe script:
- Identifies sections/loaders that have no occurrences in JSONs
- Lists the files that will be removed
- Asks for confirmation (type
yesto confirm) - Permanently deletes the files
Example output:
ποΈ Removing unused sections/loaders...
π 15 file(s) will be removed:
- sections/Category/CategoryGrid.tsx
- sections/Institutional/NumbersWithImage.tsx
- sections/Product/ProductShelf.tsx
...
β οΈ This action is irreversible!
Type 'yes' to confirm removal:
Note: This flag only works for full validation (without specifying a file), it doesn't work when validating a specific section.
The script:
- Iterates through all files in
sections/,loaders/, andactions/ - Generates the
__resolveTypefor each section/loader/action - Searches for ALL occurrences of that
__resolveTypein.deco/blocks(including inside pages) - Extracts the Props interface from the TypeScript file
- Deeply validates each occurrence against the types
- Reports errors and warnings with exact path in the JSON
- Detects unused files that aren't referenced anywhere
- β
Follows re-exports (
export { default } from "./other-file") - β
Resolves Deno import aliases from
deno.json($store/,$home/,site/, etc.) - β Extracts type from the component parameter exported as default
- β Fallback to interface/type named "Props"
- β Supports type aliases and interfaces
- β Supports utility types (Omit, Pick, Partial)
- β Supports arrow function components and function declarations
- β
Primitive types:
string,number,boolean,null - β Arrays with element validation
- β Nested objects recursively
- β
Optional properties (
?) - β
Union types (
string | number) - β
Special types:
ImageWidget,Product,RichText, etc - β
Respects
@ignoreannotation on properties β οΈ Detects extra properties not defined in types (warnings)
- β Ignores blocks from external apps (vtex, commerce, shopify, etc)
- β Ignores Theme blocks
- β Protection against infinite recursion in circular types
- β
Detects dead code (variants with
nevermatcher) - β Detects Lazy wrapping Multivariate (should be inverted)
- β Reports anti-patterns in summary and JSON report
- β Valid - Block is correct
β οΈ Warning - Props not found OR extra properties not defined in types OR section is not being used (doesn't fail the build)- π¨ Anti-pattern - Configuration issues that may cause performance problems or dead code
- β Error - Required properties missing or incorrect types (fails the build)
Generates a JSON report file with validation results:
# Default: creates validation-report.json
deno run -A https://deco.cx/validate -report
# Custom path
deno run -A https://deco.cx/validate -report my-report.jsonThe report includes:
- Summary with total counts (sections, errors, warnings, unused)
- Detailed list of sections with errors (including file, line, property, message)
- Detailed list of sections with warnings
- List of unused sections
Example report structure:
{
"timestamp": "2024-01-15T10:30:00.000Z",
"projectRoot": "/path/to/project",
"summary": {
"totalSections": 133,
"totalOccurrences": 1606,
"totalErrors": 15,
"totalWarnings": 4,
"sectionsWithErrors": 5,
"sectionsWithWarnings": 10,
"unusedSections": 8,
"validSections": 110
},
"sectionsWithErrors": [...],
"sectionsWithWarnings": [...],
"unusedSections": [...]
}validate-blocks/
βββ main.ts # Main entrypoint
βββ deno.json # Deno configuration and tasks
βββ src/
β βββ type-mapper.ts # Maps __resolveType to paths
β βββ ts-parser.ts # TypeScript parser (extracts Props)
β βββ validator.ts # Recursive type validator
β βββ validate-blocks.ts # Orchestrator and reporting
βββ tests/
β βββ ts-parser_test.ts # Tests for TypeScript parser
β βββ validator_test.ts # Tests for validator
β βββ type-mapper_test.ts # Tests for type mapper
β βββ fixtures/ # Test fixtures
βββ README.md # This documentation
# Run all tests
deno test -A
# Run specific test file
deno test -A tests/validator_test.ts
# Run with verbose output
deno test -A --reporter=verboseπ Validating sections and loaders...
β
sections/Header/Header.tsx - 15 occurrence(s)
β
sections/Footer/Footer.tsx - 1 occurrence(s)
β οΈ sections/Footer/Footer.tsx - 1 occurrence(s), 2 warning(s)
Footer.json
- property not defined in types (can be removed) (.deco/blocks/Footer.json:265)
- property not defined in types (can be removed) (.deco/blocks/Footer.json:273)
β sections/Category/CategoryGrid.tsx - 1 occurrence(s), 1 error(s)
Preview%20%2Fsections%2FCategory%2FCategoryGrid.tsx.json
- "items": required property missing (.deco/blocks/Preview%20%2Fsections%2FCategory%2FCategoryGrid.tsx.json:2)
β sections/Sac/Stores.tsx - 2 occurrence(s), 2 error(s)
pages-Lojas-735837.json
- expected array, received object (.deco/blocks/pages-Lojas-735837.json:57)
- expected array, received object (.deco/blocks/pages-Lojas-735837.json:73)
βββββββββββββββββββββββββββββββββββββββ
π SUMMARY
βββββββββββββββββββββββββββββββββββββββ
Total sections/loaders/actions: 95
Total occurrences: 284
β
No issues: 85
β οΈ With warnings: 3
β οΈ Unused: 3
β With errors: 4
β οΈ Unused sections:
- sections/Example/Unused.tsx
- sections/Test/OldComponent.tsx
β Sections with errors:
- sections/Category/CategoryGrid.tsx (1 error(s))
Note: The script shows the path and line of the JSON file in clickable format
(ex: .deco/blocks/pages-Lojas-735837.json:61). In most modern terminals
(VSCode, Cursor, iTerm2), you can click directly on the link to
open the file at the exact line of the problem.
deno task validate-blocksdeno task validate-blocks sections/Header/Header.tsxdeno task validate-blocks loaders/Product/categoryTabs.ts# All sections with warnings for extra props
deno task validate-blocks -unused
# Specific section with warnings for extra props
deno task validate-blocks sections/Footer/Footer.tsx -unusedAll code is organized in the src folder to facilitate migration
to another repository.