We will iterate through this cycle until $CODE and $SAMPLE are identical:

If you are following the steps to create a template, you should by now have defined $TEMPLATE, $SAMPLE, and $CODE environmental variables.

  1. Whenever your template has changed, you must regenerate $CODE. Usually, running with the generate with the --noSetup flag is enough:
    ns generate $CODE -t $TEMPLATE --noSetup

    If your setup sequence changes, you'll have to go through a complete setup sequence again:

ns generate $CODE -t $TEMPLATE
  1. Keep using diff to find the differences between $CODE and $SAMPLE:

    diff -qr --exclude=node_modules \
         --exclude=.git \
    $SAMPLE/ $CODE/ | sort \
    | sed "s|$SAMPLE|\$SAMPLE|g" \
    | sed "s|$CODE|\$CODE|g" \
    | sed "s|: |\/|g" \
    | sed "s|Only in \$SAMPLE/|not being generated: |g" \
    | sed "s|Only in \$CODE/|new added: |g" \

    You might add --exclude statements to include files that are different but that do not concern us. For instance, package.json and package-lock.json.

  2. Resolve differences between $CODE and $SAMPLE. For specific file differences, you can again use diff:


Then start over with step 1 until no differences remain.

By the end of this process, $CODE (or $SAMPLE) will be a version of your $ORIGINAL that is based upon $TEMPLATE.

Following is more detail for the third step.

Resolve Differences

One assumption here is that you know what the files in $SAMPLE do. That should be true if you created it yourself, because your Setup Sequence should have gotten you to where you were before you added any files.

As the diagram above shows, essentially we will update $TEMPLATE and $SAMPLE until $CODE and $SAMPLE are the same. Where the diagram says "change $TEMPLATE", that may mean to classify a file only in $SAMPLE. Or, if there's just a difference in a file, you can figure out what you need to do to change the generation.

When you classify a file as standard, static or dynamic, you can then see specific instructions to create it:


Here's a sample output from running the command in step 2:

Files $SAMPLE/.eslintrc and $SAMPLE/.eslintrc differ
Files $SAMPLE/package.json and $SAMPLE/package.json differ
Files $SAMPLE/package-lock.json and $SAMPLE/package-lock.json differ
Files $SAMPLE/README.md and $SAMPLE/README.md differ
not being generated: /lib
not being generated: /.nyc_output
not being generated: /oclif.manifest.json
not being generated: src/ask.ts
not being generated: src/commands/pull.ts
not being generated: src/commands/push.ts
not being generated: src/executeCommand.ts
not being generated: src/getProjects.ts
not being generated: src/pullCode.ts
not being generated: src/pushCode.ts
not being generated: src/types.ts
not being generated: test/commands/pull.test.ts
not being generated: test/commands/push.test.ts
new added: meta/customCode.json
new added: src/commands/hello.ts
new added: test/commands/hello.test.ts

You see that the output has files that:

We will deal with each separately.

New Added File Diffs

These can be either necessary (such as meta, needed by any code base) or superfluous. In the above case, it happens that hello is a test generated automatically by a tool that was used in the setup sequence.

The second type of files should be removed. That can be done with a call to rm in setupSequence.preCommands in the config file:

    - title: setup git
      file: git
        - init
        - $codeDir
    - title: remove extra hello file
      file: rm
        - $codeDir/src/commands/hello.ts
    - title: remove extra hello test
      file: rm
        - $codeDir/test/commands/hello.test.ts

An added file or directory that is necessary can simply be copied over to $SAMPLE:

cp -r $SAMPLE/meta/ $SAMPLE/meta

Differing Files

The most important file to check for differences is the package.json if you've got one:

diff $SAMPLE/package.json $SAMPLE/package.json

You need to be sure any discrepancies in version or in packages are due to custom changes not relevant to the template. For instance, if $SAMPLE contains a package that is not in $CODE because the package was used for business logic relevant to the specific $SAMPLE code, then that's not relevant to the template. On the other hand, if you added a package update that would be relevant to any user of the template, then you should add it to the config file. For instance, say you get a discrepancy between the versions of mocha:

<     "mocha": "^5.0.2",
>     "mocha": "^7.1.2",

That's because you added that due to a security vulnerability with the older version. So you can add or update setupSequence.mainInstallation to ensure that any code will have the correct version.

    - mocha@7.1.2

You can also look at the results of diff on the other files and make sure you know the reason. Usually, it won't be an issue. Sometimes the difference is just due to something like using a different name than the sample, and can be ignored.

Files Not Being Generated

These files fall into a few categories:

  • You must tell ns-flip to ignore them. Ignored files do not change when you call regenerate and are ignored when you run test.

    Files in .git, meta, and the custom directories get ignored automatically by ns-flip. Also 'package.json' and 'package-lock.json'. Note Actually, ns-flip will update the package.json to reflect new or updated dependencies in the code, but otherwise will not change the package.json.

    Currently, any further files that should be ignored must be added into the config file as an array under ignore. For instance:

      - lib
      - oclif.manifest.json
      - .nyc_output
  • You may have files that are purely for business logic and that would never be generated by the template. For instance, a file to define a function that is only relevant to $SAMPLE.

Create a custom directory in $SAMPLE (based on dirs.custom in the config file). Then, refactor over to there the purely business logic files. Then you can add an --exclude=custom to your diff and call it again.

  • The remaining files not being generated should in fact be generated by the template, and must be classified as standard, custom static or custom dynamic.

In the above example, src has pushChanges.ts and commands/push.ts. If a file is just an application-specific command, like pushChanges, it will probably have to be placed into a custom directory, and is not directly relevant to the creation of the template.

Return to Creating Templates.