Learn how to operate the Nodemaker's CLI utility
Table of Contents
To use the CLI utility:
- Enter node params as explained below.
- Run a command:
npm run ...
Command | Action | Docs |
---|---|---|
nodegen |
Generate node functionality files in TypeScript. | Section |
docsgen |
Generate node documentation files in Markdown. | Section |
packgen |
Generate an updated package.json file. |
Section |
shotgen |
Generate an in-app PNG screenshot. | Section |
flowgen |
Submit a sample workflow to n8n.io. | Section |
icongen |
Generate five PNG images as icon candidates. | Section |
resize |
Resize an icon candidate to a 60×60 px file. | Section |
place |
Move files to the n8n and n8n-docs repos. |
Section |
validate |
Validate properties in a params object. | Section |
empty |
Clear the /output directory. |
--- |
desktop |
Run the desktop app. | --- |
Note: At MVP stage, shotgen
, flowgen
, icongen
and resize
are not available through the desktop app.
Parameters are the input data needed for generating output files in TypeScript, Markdown, JSON, etc.
Nodemaker reads parameters from parameters.ts
and generates output files in /output
.
There are three types of parameters:
metaParameters
,regularNodeParameters
(ortriggerNodeParameters
), anddocsParameters
.
To enter parameters for generating a node, edit the keys and values in these three objects.
General properties related to the service.
export const metaParameters: MetaParameters = {
serviceName: "Hacker News",
authType: "OAuth2",
nodeColor: "#ff6600",
apiUrl: "http://hn.algolia.com/api/v1/",
};
Type definition:
type MetaParameters = {
serviceName: string;
authType: AuthType;
nodeColor: string;
apiUrl: string;
};
For more type information on MetaParameters
, see the global type definition.
Specific properties related to the API, for a regular or a trigger node. A regular node is called when the workflow is executed; a trigger node is called when the workflow is activated.
Example of regularNodeParameters
export const regularNodeParameters: RegularNodeParameters = {
Article: [
{
name: "Get",
description: "Get a Hacker News article",
endpoint: "items/:articleId",
requestMethod: "GET",
fields: [
{
name: "Article ID",
description: "The ID of the Hacker News article to be returned",
type: "string",
default: "",
},
{
name: "Additional Fields",
type: "collection",
default: {},
options: [
{
name: "Include comments",
type: "boolean",
default: false,
description: "Whether to include all the comments in the article",
},
],
},
],
},
{
name: "Get All",
description: "Get all Hacker News articles",
endpoint: "search?",
requestMethod: "GET",
fields: [
{
name: "Return All",
description: "Whether to return all results or only up to a limit",
type: "boolean",
default: false,
},
{
name: "Limit",
description:
"Limit of Hacker News articles to be returned for the query",
type: "number",
default: 5,
extraDisplayRestriction: { "Return All": true },
},
{
name: "Additional Fields",
type: "collection",
default: {},
options: [
{
name: "Keyword",
description: "The keyword for filtering the results of the query",
type: "string",
default: "",
},
{
name: "Tags",
description: "Tags for filtering the results of the query",
type: "multiOptions",
default: {},
options: [
{
name: "Story",
description: "Returns query results filtered by story tag",
},
{
name: "Comment",
description: "Returns query results filtered by comment tag",
},
{
name: "Poll",
description: "Returns query results filtered by poll tag",
},
{
name: "Show HN",
description: "Returns query results filtered by Show HN tag",
},
{
name: "Ask HN",
description: "Returns query results filtered by Ask HN tag",
},
{
name: "Front Page",
description:
"Returns query results filtered by Front Page tag",
},
],
},
],
},
],
},
],
User: [
{
name: "Get",
description: "Get a Hacker News user",
endpoint: "users/:username",
requestMethod: "GET",
fields: [
{
name: "Username",
description: "The Hacker News user to be returned",
type: "string",
default: "",
},
],
},
{
name: "Rename",
description: "Rename a Hacker News user",
endpoint: "users/:username",
requestMethod: "PUT",
fields: [
{
name: "Username",
description: "The Hacker News user to be renamed",
type: "string",
default: "",
},
],
},
],
};
Example of triggerNodeParameters
export const triggerNodeParameters: TriggerNodeParameters = {
webhookEndpoint: "/automations/hooks",
webhookProperties: [
{
displayName: "Event",
name: "event",
type: "options",
required: true,
default: "subscriberActivated",
description:
"The events that can trigger the webhook and whether they are enabled.",
options: [
{
name: "Subscriber Activated",
value: "subscriberActivated",
description:
"Whether the webhook is triggered when a subscriber is activated.",
},
{
name: "Link Clicked",
value: "linkClicked",
description:
"Whether the webhook is triggered when a link is clicked.",
fields: [
{
displayName: "Initiating Link",
name: "link",
type: "string",
required: true,
default: "",
description: "The URL of the initiating link",
},
],
},
],
},
],
};
Route parameter
In regularNodeParameters
, an operation's endpoint
property may contain a route parameter, signalled by a colon :
. The parameter references one of the (camelCased) names of the fields in the operation.
regularNodeParameters
with an endpoint with a route parameter:
Article: [
{
name: "Get",
description: "Get a Hacker News article",
endpoint: "items/:articleId", // route parameter referencing camelCased name of field
requestMethod: "GET",
fields: [
{
name: "Article ID",
description: "The ID of the Hacker News article to be returned",
type: "string",
default: "",
},
// ...
Output with route parameter in use:
if (operation === 'get') {
const articleId = this.getNodeParameter('articleId', i);
const endpoint = `items/${articleId}`;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
// TODO: Use additionalFields.fieldName in `qs` or in `body` or as boolean flag
responseData = await hackerNewsApiRequest.call(this, 'GET', endpoint, body, qs);
For more type information on RegularNodeParameters
, see the global type definition.
For more type information on TriggerNodeParameters
, see the global type definition.
Field display restrictions are inferred from the structure of the params object, but if you need an additional field display restriction, add it with extraDisplayRestriction: { fieldName: boolean }
. See the global type definition.
Snippets to be used for docs generation.
export const docsParameters: DocsParameters = {
serviceName: "Hacker News",
serviceUrl: "https://news.ycombinator.com",
introDescription:
"a social news website focusing on computer science and entrepreneurship",
exampleUsage: "get an article from Hacker News",
workflowNumber: "123",
};
Type definition:
type DocsParameters = {
serviceName: string;
serviceUrl: string;
introDescription: string;
exampleUsage: string;
workflowNumber: string;
};
To validate that your params object conforms to the expected shape, type the object you are editing in parameters.ts
and look for any TypeScript errors.
Alternatively, to validate a parameter bundle built on the frontend, use the validate
script.
Output files are all generated in the /output
dir.
Coverage: Output files do not contain 100% of the logic required for the node, because part of that logic always depends on the specific API and often cannot be predicted. The few sections requiring custom logic are pinpointed with // TODO
comments and TODO_
variables, together with an explanation of the logic that needs to be added in.
$ npm run nodegen
nodegen
generates:
*.node.ts
— main logic (regular or trigger node)GenericFunctions.ts
— node helper functions*Description.ts
— separate logic per resource (optional)*.credentials.ts
— node authentication params
To generate these files, the CLI prompts the user to select:
- whether the node will be:
- regular node, called when the workflow is executed, or
- trigger node, called when the workflow is activated.
- if a regular node, whether the node will be generated
- in simple mode, where the output node has its resources in the main logic file, or
- in complex mode, where the output node has its resources in separate
*Description.ts
files.
If metaParameters.authType
is set to "None"
, then no *.credentials.ts
file will be generated.
Note: Per the n8n submission guidelines, this operation auto-sorts all options
in the node parameters in alphabetical order.
Important:
docsgen
is currently only available for regular nodes, not for trigger nodes.
$ npm run docsgen
docsgen
generates:
README.md
— main doc fileREADME.md
— credentials doc file
$ npm run packgen
packgen
retrieves a copy of the latest package.json
file from the official repo, updates it with the paths to the new node files, and outputs the updated package.json
file. Path insertion follows alphabetical order.
Note: This operation disallows insertion of a node in the package.json
if its name already exists in the listing.
Important:
shotgen
requires credentials. See below.
$ npm run shotgen
shotgen
generates a PNG file containing an in-app screenshot of the node, intended for use in the main node documentation file and in the workflow submission to n8n.io.
To generate the screenshot, shotgen
:
- starts the n8n app,
- runs an automated Chrome instance, and
- uploads the screenshot to an image hosting service.
For now, the uploaded image URL is simply stored in image-upload-url.txt
.
shotgen
requires n8n
to be built. Refer to setup instructions for the n8n
repo.
There are two ways to run shotgen
:
- Separate startup: Open a terminal, access your local copy of the
n8n
repo and start it withnpm run start
. With the n8n app running, open a second terminal, access thenodemaker
repo and runnpm run shotgen
. - Concurrent startup: In the
nodemaker
repo, runnpm run runapp-shotgen
. Nodemaker will run two concurrent processes to start the n8n app and generate the screenshot. Concurrent startup functionality is not yet fully tested.
Concurrent startup requires the nodemaker
repo to be located alongside your copy of the n8n
repo.
.
├── n8n
└── nodemaker
Image upload credentials
After generating the screenshot, shotgen
uploads it to the image hosting service Imgbb, so that the screenshot can later be used for workflow submission to n8n.io.
Imgbb requires credentials. To generate them:
- Visit Imgbb.
- Create an account or sign in with Google, Facebook, etc.
- While logged in, visit the Imgbb API docs.
- Click on
Get API key
and copy your API key. - Create an
.env
file in/config
. - Enter your API key as
IMGBB_API_KEY
in the.env
file.
IMGBB_API_KEY="6d17c6..."
Important:
flowgen
requires credentials. See below.
$ npm run flowgen
flowgen
submits a sample workflow to the n8n.io collection. Before running flowgen
, make sure to first run shotgen
to generate workflow.png
and image-upload-url.txt
.
Workflow submission credentials
To log in to n8n.io, flowgen
needs credentials for a n8n account. Create an account at n8n.io and enter your credentials as env vars in the .env
file you created at /config
:
N8N_LOGIN_USERNAME="[email protected]"
N8N_LOGIN_PASSWORD="abc123"
Important:
icongen
requires credentials. See below.
$ npm run icongen
icongen
generates five icon candidates for the node, placing them in /output/icon-candidates
. To do so, the CLI prompts the user to enter a query string based on which to perform a search for a relevant image. Make sure to search for a specific string that is likely to return a logo image for the service—if the service name happens to be a generic word, add an identifier keyword.
Image search credentials
icongen
uses Google's Custom Search Engine, which requires two credentials:
- a Custom Search Engine engine ID, and
- a Google Cloud Platform project API key.
To generate a Custom Search Engine ID:
- Access the Custom Search Engine dashboard.
- Enter any site in
Sites to Search
, name the engine andCreate
. - Click on
Edit search engine
and then onSetup
. - Under
Basics
, copy the stringSearch engine ID
and use it forGOOGLE_IMAGE_SEARCH_ENGINE_ID
in the.env
file. - Under
Basics
, switch onImage search
. - Under
Basics
, switch onSearch the entire web
. - Under
Basics
, inSites to search
, delete the site you added in step 2.
To generate a Google Cloud Platform project API key:
- Access the Google Cloud Platform dashboard.
- On the top-left corner, click on the project name and then on
New Project
. - Name the project and
Create
. - Select your new project on the top-left corner.
- Click on
Enable APIs and Services
, search forCustom Search API
, select it and enable it. - Click on
Create Credentials
on the top-right corner, then onCredentials
on the left nav, then on theAPI key
hyperlink, and finally onCreate
. Use the generated API key forGOOGLE_PROJECT_API_KEY
in the.env
file.
End result in /config/.env
:
GOOGLE_IMAGE_SEARCH_ENGINE_ID="01782..."
GOOGLE_PROJECT_API_KEY="AIzaS..."
Google's Custom Search Engine is limited to 100 free requests a day.
$ npm run resize
resize
converts one of the icon candidates into a 60×60 px PNG file, for use as the final icon for the node. To do so, the CLI prompts the user to inspect the /output/icon-candidates
dir and select an icon candidate by its number. Before running resize
, make sure to first run icongen
to generate the icon candidates.
Per n8n codebase conventions, the output PNG filename is camelCased.
$ npm run place
place
relocates node functionality and documentation files in the /output
dir to their appropriate locations in the n8n
and n8n-docs
repos, respectively. To do so, the CLI prompts the user to select the type of file (functionality or documentation) to be relocated.
place
requires the nodemaker
repo to be located alongside your copies of the n8n
and n8n-docs
repos.
.
├── n8n
├── n8n-docs
└── nodemaker
$ npm run validate
validate
is intended to validate an untyped object, especially to help developers surface errors when troubleshooting why a certain parameter bundle built on the frontend is failing to generate a node.
To validate an untyped object built on the frontend, open validateParams.ts
, set the constant dataToValidate
to the object, choose the appropriate validator method and run npm run validate
. If validation fails, an error message pinpointing the problem will be shown.
For the available validator methods, see Validator.ts
.