Developing a plugin for meta

Patrick Lee Scott

In my last post, I introduced meta and we discussed a need for a templating tool that allows private templates to be created and easily shared between your team.

This post is the how to the why. If you are interested in developing your own meta plugin, then read ahead!

Setting up meta for development

The best way to get started is to do the following:

npm i -g meta
meta git clone git@github.com:mateodelnorte/meta.git
cd ./meta
npm install
meta npm install
meta npm link --all
npm link

This above does the following:

  1. install meta globally
  2. clone the meta project, aptly named meta
  3. change to the cloned directory
  4. use meta to perform npm install, npm link --all in each directory listed in projects of the .meta JSON configuration file
  5. link the version of meta in the current directory to be used as a global command, so when calling meta your system will use your in-development version.

You can then write your command and test using meta [subcommand].

Authoring the plugin

First thing’s first, I’m heading on over to GitHub to create a meta-template project. Then I will add it to meta using the following command:

meta project add plugins/meta-template git@github.com:patrickleet/meta-template.git

The goal of this project will ultimately be the following API

> meta project add templates/meta-plugin git@github.com:patrickleet/meta-template-meta-plugin.git> meta project add plugins/meta-xyz git@github.com:patrickleet/meta-xyz.git> meta template apply templates/meta-plugin plugins/meta-xyz

This will allow any git repository to serve as an initial template. I will create a template for building meta-plugins as the first meta-template template. So meta. Our meta-plugin template will need to generate the following:

- meta-xyz
— bin/
— meta-xyz
— .gitignore
— LICENSE
— README.md
— index.js
— package.json

I’ve created the repository over at https://github.com/patrickleet/meta-template-meta-plugin.

Let’s add the repository to our metarepo using meta project add.

meta project add templates/meta-plugin git@github.com:patrickleet/meta-template-meta-plugin.git

Now I’m just going to repurpose the contents of a stub project, meta-docker which has yet to be implemented into my template. We want everything except the git history. The following process being the inspiration for the plugin, and what we will soon automate.

cp -r plugins/meta-docker templates/tmp && rm -rf templates/tmp/.git && cp -R templates/tmp/* templates/meta-plugin && cp -R templates/tmp/.* templates/meta-plugin && rm -rf templates/tmp

Commit: copy meta-docker placeholder project

Now, we want to replace the docker strings with a template that we can find and replace later. I did this with a `Find & Replace` in VSCode.

In the end I have the following parameters that should be read when applying the template: {[PLUGIN_NAME]}, {[GITHUB_USERNAME]}, {[EMAIL]}, and {[FULL_NAME]}

Committed, pushed to Github: templatize

Next, we just need a way to apply the template, which will cp the contents of the template project, parse the contents for template variables, and then prompt the user to input each variable.

Unfortunately, since the plugin doesn’t yet exist, we will perform the manual version of the task. Let’s copy the contents of the template into meta-plugin

cd ../../ 
cp -R templates/meta-plugin/* plugins/meta-template && cp templates/meta-plugin/.* plugins/meta-template

We get an error the `.git` is not an empty directory, and not copied, which is what we want anyway. We will want to address that more gracefully in our automated version.

Find and replace each of the variables, and commit to GitHub. Next step, writing the plugin code to automate the process we just did.

  1. Copy the source template directory to a tmp directory
  2. Remove .git directory
  3. Copy tmp directory contents to destination directory
  4. Parse contents for variables
  5. Prompt for variables
  6. Replace variables with user inputs
  7. Remove tmp directory

First, let’s uncomment out a placeholder command, save, and then from ./meta run meta npm link --all

When we run meta we should now see meta template as an option in help, and running meta template should show us our apply command is available.

➜ meta git:(master) ✗ meta
Usage: meta [options] [command]
Commands:
docker run docker commands for your meta repo and child git repositories
gh github command tool
git manage your meta repo and child git repositories
init initialize a new meta repo
npm run npm commands against your meta and child repositories
project add & remove child repositories
template run template commands for your meta repo and child git repositories
yarn run yarn commands against your meta and child repositories
help [cmd] display help for [cmd]
Options: -h, — help output usage information
-V, — version output the version number
➜ meta git:(master) ✗ meta templateUsage: meta-template [options] [command]Commands:apply apply a source directory as a template on another destination directory
help [cmd] display help for [cmd]
Options:-h, — help output usage information

Alright, let’s write bin/meta-template-apply. We’ll set the #! and parse the src and dest directories. If the plugin is used without the correct arguments, we will output the usage string.

#!/usr/bin/env node
const usage = `\n usage:\n\n meta template apply <srcTemplateDir> <destProjectDir>\n`;
if ( ! process.argv[2] || process.argv[2] === ‘ — help’)
return console.log(usage);
const srcTemplateDir = process.argv[2] === ‘blank’ ?
process.argv[3] :
process.argv[2];
const destProjectDir = process.argv[3] === ‘blank’ ?
process.argv[4] :
process.argv[3];
if ( ! srcTemplateDir || ! destProjectDir) return console.log(usage);console.log(`meta template applying \’${srcTemplateDir}\’ to ${destProjectDir}`);

And add it to package.json so it’s executable.

After another meta npm link --all && npm link we can see apply outputting usage

meta git:(master) ✗ meta template applyusage:meta template apply <srcTemplateDir> <destProjectDir>

[meta apply · patrickleet/meta-template@56d5a17 · GitHub]

At this point you hopefully you now have a good sense of what it takes to develop a meta plugin locally. The fact that meta provides a way to do this makes it pretty straightforward. The actual implementation is beyond the scope of what I wanted to accomplish with this post, as it would go on for far too long, but I did finish implementing it. I suggest perusing the GitHub history starting at the last commit if you’re interested!

[GitHub — patrickleet/meta-template: Templates for new meta projects](https://github.com/patrickleet/meta-template)

Patrick Lee Scott

Written by

I make things for the internet, that scale, look nice, and make money!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade