Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overwrite file with angular schematics?

I want to write a Rule that overwrites a file every time. In the following and have MergeStrategy set to Overwrite:

collection.json

{
  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "function": {
      "aliases": [ "fn" ],
      "factory": "./function",
      "description": "Create a function.",
      "schema": "./function/schema.json"
    }
  }
}

function/index.ts

export default function(options: FunctionOptions): Rule {
  options.path = options.path ? normalize(options.path) : options.path;
  const sourceDir = options.sourceDir;
  if (!sourceDir) {
    throw new SchematicsException(`sourceDir option is required.`);
  }

  const templateSource: Source = apply(
    url('./files'),
    [
      template({
        ...strings,
        ...options,
      }),
      move(sourceDir),
    ]
  )

  return mergeWith(templateSource, MergeStrategy.Overwrite);

}

files/__path__/__name@dasherize__.ts

export function <%= camelize(name) %>(): void {
}

I run schematics .:function --name=test --dry-run=false I get

CREATE /src/app/test.ts (33 bytes)

but then, the second time.

ERROR! /src/app/test.ts already exists.

Should it not overwrite the file test.ts with out error?

Edit:

All of the answers work and are great but it seems they are workarounds and no obvious "right" answer and possibly based on preference / opinionated. So not sure how to mark as answered.

like image 691
William Lohan Avatar asked Feb 23 '18 22:02

William Lohan


1 Answers

Modifying chris' answer I was able to come up with the following solution:

export function applyWithOverwrite(source: Source, rules: Rule[]): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    const rule = mergeWith(
      apply(source, [
        ...rules,
        forEach((fileEntry) => {
          if (tree.exists(fileEntry.path)) {
            tree.overwrite(fileEntry.path, fileEntry.content);
            return null;
          }
          return fileEntry;
        }),

      ]),
    );

    return rule(tree, _context);
  };
}

Replace your usage of apply with calls to this function.

 applyWithOverwrite(url('./files/stylelint'), [
        template({
          dot: '.',
        }),
      ]),
like image 171
cgatian Avatar answered Sep 27 '22 22:09

cgatian