I've just been through the same problem.
It seems that it's not a real problem as the Tree instance only lists the files with their paths.
Folders are not listed among that Tree instance. The getDir(string) method creates a dirEntry which path does not really exist as an entry of the tree, it is only organizational entry that lists the subdirs and subfiles.
Here is what I've done to make it work as expected:
private files: string[] = {
// this file will be deleted
'test/test1/file.txt',
// this directory will be deleted
'test/test2',
}
createRule(): Rule {
return (tree: Tree, schematicContext: SchematicContext): Tree => {
this.files.forEach(file => {
this.deleteFile(file, tree, schematicContext);
});
return tree;
}
}
protected deleteFile(filePath: string, tree: Tree, schematicContext: SchematicContext): void {
try {
// as the tree only lists the files, this returns false for directories
if (!tree.exists(filePath)) {
// retrieve the directory corresponding to the path
const dirEntry = tree.getDir(filePath);
// if there are neither files nor dirs in the directory entry,
// it means the directory does not exist
if (!dirEntry.subdirs.length && !dirEntry.subfiles.length) {
schematicContext.logger.info(`${filePath} does not exist.`);
// otherwise, it exists, seriously !
} else {
schematicContext.logger.info(`deleting files in directory ${filePath}.`);
dirEntry.subfiles.forEach(subFile => this.deleteFile(`${filePath}/${subFile}`, tree, schematicContext));
dirEntry.subdirs.forEach(subDir => this.deleteFile(`${filePath}/${subDir}`, tree, schematicContext));
}
// if the file exists, delete it the easiest way
} else {
schematicContext.logger.debug(`deleting file ${filePath}.`);
tree.delete(filePath);
schematicContext.logger.info(`file ${filePath} deleted successfully.`);
}
} catch (error) {
throw new SchematicsError(`Could not delete file ${filePath}`, error);
}
}