mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
fix: Improve @n8n/node-cli cross-platform compatibility and dev experience (no-changelog) (#19368)
This commit is contained in:
@@ -7,19 +7,19 @@ A powerful scaffolding tool to quickly create custom n8n community nodes with be
|
||||
Create a new n8n node in seconds:
|
||||
|
||||
```bash
|
||||
pnpm create @n8n/node
|
||||
npm create @n8n/node@latest # or pnpm/yarn/...
|
||||
```
|
||||
|
||||
Follow the interactive prompts to configure your node, or specify options directly:
|
||||
|
||||
```bash
|
||||
pnpm create @n8n/node my-awesome-node --template declarative/custom
|
||||
npm create @n8n/node my-awesome-node --template declarative/custom
|
||||
```
|
||||
|
||||
## 📋 Command Line Options
|
||||
|
||||
```bash
|
||||
pnpm create @n8n/node [NAME] [OPTIONS]
|
||||
npm create @n8n/node [NAME] [OPTIONS]
|
||||
```
|
||||
|
||||
### Options
|
||||
@@ -41,7 +41,7 @@ pnpm create @n8n/node [NAME] [OPTIONS]
|
||||
The CLI will guide you through setting up your node:
|
||||
|
||||
```
|
||||
$ pnpm create @n8n/node
|
||||
$ npm create @n8n/node
|
||||
┌ @n8n/create-node
|
||||
│
|
||||
◇ What is your node called?
|
||||
@@ -65,7 +65,7 @@ $ pnpm create @n8n/node
|
||||
│
|
||||
◇ Next Steps ─────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ cd ./my-awesome-api-node && pnpm run dev │
|
||||
│ cd ./my-awesome-api-node && npm run dev │
|
||||
│ │
|
||||
│ 📚 Documentation: https://docs.n8n.io/integrations/creating-nodes/ │
|
||||
│ 💬 Community: https://community.n8n.io │
|
||||
@@ -86,7 +86,7 @@ cd ./my-awesome-api-node
|
||||
### 2. Start development server
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This command:
|
||||
@@ -109,28 +109,28 @@ Your generated project comes with these convenient npm scripts:
|
||||
|
||||
### Development
|
||||
```bash
|
||||
pnpm dev
|
||||
npm run dev
|
||||
# Runs: n8n-node dev
|
||||
```
|
||||
|
||||
### Building
|
||||
```bash
|
||||
pnpm build
|
||||
npm run build
|
||||
# Runs: n8n-node build
|
||||
```
|
||||
|
||||
### Linting
|
||||
```bash
|
||||
pnpm lint
|
||||
npm run lint
|
||||
# Runs: n8n-node lint
|
||||
|
||||
pnpm lint:fix
|
||||
npm run lint:fix
|
||||
# Runs: n8n-node lint --fix
|
||||
```
|
||||
|
||||
### Publishing
|
||||
```bash
|
||||
pnpm run release
|
||||
npm run release
|
||||
# Runs: n8n-node release
|
||||
```
|
||||
|
||||
@@ -139,7 +139,7 @@ pnpm run release
|
||||
### Build for production
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
npm run build
|
||||
```
|
||||
|
||||
Generates:
|
||||
@@ -151,7 +151,7 @@ Generates:
|
||||
### Quality checks
|
||||
|
||||
```bash
|
||||
pnpm lint
|
||||
npm run lint
|
||||
```
|
||||
|
||||
Validates:
|
||||
@@ -163,13 +163,13 @@ Validates:
|
||||
Fix issues automatically:
|
||||
|
||||
```bash
|
||||
pnpm lint:fix
|
||||
npm run lint:fix
|
||||
```
|
||||
|
||||
### Publish your node
|
||||
|
||||
```bash
|
||||
pnpm run release
|
||||
npm run release
|
||||
```
|
||||
|
||||
Runs [release-it](https://github.com/release-it/release-it) to handle the complete release process:
|
||||
@@ -238,28 +238,28 @@ Choose the right template for your use case:
|
||||
```bash
|
||||
# Clear n8n node cli cache and restart
|
||||
rm -rf ~/.n8n-node-cli/.n8n/custom
|
||||
pnpm dev
|
||||
npm run dev
|
||||
```
|
||||
|
||||
**TypeScript errors:**
|
||||
```bash
|
||||
# Reinstall dependencies
|
||||
rm -rf node_modules pnpm-lock.yaml
|
||||
pnpm install
|
||||
rm -rf node_modules npm-lock.yaml
|
||||
npm install
|
||||
```
|
||||
|
||||
**Build failures:**
|
||||
```bash
|
||||
# Check for linting issues first
|
||||
pnpm lint --fix
|
||||
pnpm build
|
||||
npm run lint --fix
|
||||
npm run build
|
||||
```
|
||||
|
||||
**Development server issues:**
|
||||
```bash
|
||||
# Clear cache and restart development server
|
||||
rm -rf ~/.n8n-node-cli/.n8n/custom
|
||||
pnpm dev
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 🔧 Advanced Usage
|
||||
@@ -269,7 +269,7 @@ pnpm dev
|
||||
If you prefer to use your own n8n installation:
|
||||
|
||||
```bash
|
||||
pnpm dev --external-n8n
|
||||
npm run dev --external-n8n
|
||||
```
|
||||
|
||||
### Custom User Folder
|
||||
@@ -277,7 +277,7 @@ pnpm dev --external-n8n
|
||||
Specify a custom location for n8n user data:
|
||||
|
||||
```bash
|
||||
pnpm dev --custom-user-folder /path/to/custom/folder
|
||||
npm run dev --custom-user-folder /path/to/custom/folder
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
11
packages/@n8n/create-node/bin/create-node.cjs
Executable file
11
packages/@n8n/create-node/bin/create-node.cjs
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
const n8nNodeBin = require.resolve('.bin/n8n-node');
|
||||
|
||||
const result = spawnSync(n8nNodeBin, ['new', ...process.argv.slice(2)], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
|
||||
process.exit(result.status ?? 1);
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const result = spawnSync('n8n-node', ['new', ...process.argv.slice(2)], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
|
||||
process.exit(result.status ?? 1);
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@n8n/create-node",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"description": "Official CLI to create new community nodes for n8n",
|
||||
"bin": {
|
||||
"create-n8n-node": "bin/create.js"
|
||||
"create-node": "bin/create-node.cjs"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "node bin/create.js"
|
||||
"start": "node bin/create-node.cjs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -18,5 +18,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@n8n/node-cli": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@n8n/typescript-config": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,45 +7,45 @@ Official CLI for developing community nodes for n8n.
|
||||
**To create a new node**, run:
|
||||
|
||||
```bash
|
||||
pnpm create @n8n/node
|
||||
npm create @n8n/node@latest # or pnpm/yarn/...
|
||||
```
|
||||
|
||||
This will generate a project with `pnpm` scripts that use this CLI under the hood.
|
||||
This will generate a project with `npm` scripts that use this CLI under the hood.
|
||||
|
||||
## 📦 Generated Project Commands
|
||||
|
||||
After creating your node with `pnpm create @n8n/node`, you'll use these commands in your project:
|
||||
After creating your node with `npm create @n8n/node`, you'll use these commands in your project:
|
||||
|
||||
### Development
|
||||
```bash
|
||||
pnpm dev
|
||||
npm run dev
|
||||
# Runs: n8n-node dev
|
||||
```
|
||||
|
||||
### Building
|
||||
```bash
|
||||
pnpm build
|
||||
npm run build
|
||||
# Runs: n8n-node build
|
||||
```
|
||||
|
||||
### Linting
|
||||
```bash
|
||||
pnpm lint
|
||||
npm run lint
|
||||
# Runs: n8n-node lint
|
||||
|
||||
pnpm lint:fix
|
||||
npm run lint:fix
|
||||
# Runs: n8n-node lint --fix
|
||||
```
|
||||
|
||||
### Publishing
|
||||
```bash
|
||||
pnpm run release
|
||||
npm run release
|
||||
# Runs: n8n-node release
|
||||
```
|
||||
|
||||
## 🛠️ CLI Reference
|
||||
|
||||
> **Note:** These commands are typically wrapped by `pnpm` scripts in generated projects.
|
||||
> **Note:** These commands are typically wrapped by `npm` scripts in generated projects.
|
||||
|
||||
```bash
|
||||
n8n-node [COMMAND] [OPTIONS]
|
||||
@@ -76,7 +76,7 @@ n8n-node new n8n-nodes-my-app --force
|
||||
n8n-node new n8n-nodes-my-app --template declarative/custom
|
||||
```
|
||||
|
||||
> **Note:** This command is used internally by `pnpm create @n8n/node` to provide the interactive scaffolding experience.
|
||||
> **Note:** This command is used internally by `npm create @n8n/node` to provide the interactive scaffolding experience.
|
||||
|
||||
#### `n8n-node dev`
|
||||
|
||||
@@ -172,13 +172,13 @@ The recommended workflow using the scaffolding tool:
|
||||
|
||||
1. **Create your node**:
|
||||
```bash
|
||||
pnpm create @n8n/node my-awesome-node
|
||||
npm create @n8n/node my-awesome-node
|
||||
cd my-awesome-node
|
||||
```
|
||||
|
||||
2. **Start development**:
|
||||
```bash
|
||||
pnpm dev
|
||||
npm run dev
|
||||
```
|
||||
- Starts n8n on `http://localhost:5678`
|
||||
- Links your node automatically
|
||||
@@ -188,17 +188,17 @@ The recommended workflow using the scaffolding tool:
|
||||
|
||||
4. **Lint your code**:
|
||||
```bash
|
||||
pnpm lint
|
||||
npm run lint
|
||||
```
|
||||
|
||||
5. **Build for production**:
|
||||
```bash
|
||||
pnpm build
|
||||
npm run build
|
||||
```
|
||||
|
||||
6. **Publish**:
|
||||
```bash
|
||||
pnpm run release
|
||||
npm run release
|
||||
```
|
||||
|
||||
## 📁 Project Structure
|
||||
@@ -244,16 +244,16 @@ The CLI reads configuration from your `package.json`:
|
||||
rm -rf ~/.n8n-node-cli/.n8n/custom
|
||||
|
||||
# Restart development server
|
||||
pnpm dev
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Build failures
|
||||
```bash
|
||||
# Run linting first
|
||||
pnpm lint
|
||||
npm run lint
|
||||
|
||||
# Clean build
|
||||
pnpm build
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@n8n/node-cli",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"description": "Official CLI for developing community nodes for n8n",
|
||||
"bin": {
|
||||
"n8n-node": "bin/n8n-node.mjs"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { intro, outro, spinner } from '@clack/prompts';
|
||||
import { intro, outro, spinner, log } from '@clack/prompts';
|
||||
import { Command, Flags } from '@oclif/core';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
@@ -18,7 +18,7 @@ export default class Dev extends Command {
|
||||
static override examples = [
|
||||
'<%= config.bin %> <%= command.id %>',
|
||||
'<%= config.bin %> <%= command.id %> --external-n8n',
|
||||
'<%= config.bin %> <%= command.id %> --custom-nodes-dir /opt/n8n-extensions',
|
||||
'<%= config.bin %> <%= command.id %> --custom-user-folder /Users/test',
|
||||
];
|
||||
static override flags = {
|
||||
'external-n8n': Flags.boolean({
|
||||
@@ -29,7 +29,7 @@ export default class Dev extends Command {
|
||||
'custom-user-folder': Flags.directory({
|
||||
default: path.join(os.homedir(), '.n8n-node-cli'),
|
||||
description:
|
||||
'Folder to use to store user-specific n8n data. By default it will use ~/.n8n-node-cli. You probably want to enable this option if you run n8n with a custom N8N_CUSTOM_EXTENSIONS env variable.',
|
||||
'Folder to use to store user-specific n8n data. By default it will use ~/.n8n-node-cli.',
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -67,11 +67,17 @@ export default class Dev extends Command {
|
||||
|
||||
linkingSpinner.stop('Linked custom node to n8n');
|
||||
|
||||
outro('✓ Setup complete');
|
||||
|
||||
if (!flags['external-n8n']) {
|
||||
// Run n8n with hot reload enabled
|
||||
runPersistentCommand('npx', ['-y', '--quiet', 'n8n'], {
|
||||
let setupComplete = false;
|
||||
const npxN8nSpinner = spinner();
|
||||
npxN8nSpinner.start('Starting n8n dev server');
|
||||
log.warn(picocolors.dim('First run may take a few minutes while dependencies are installed'));
|
||||
|
||||
// Run n8n with hot reload enabled, always attempt to use latest n8n
|
||||
// TODO: Use n8n@latest. Currently using n8n@next because of broken hot reloading before n8n@1.111.0
|
||||
await Promise.race([
|
||||
new Promise<void>((resolve) => {
|
||||
runPersistentCommand('npx', ['-y', '--quiet', '--prefer-online', 'n8n@next'], {
|
||||
cwd: n8nUserFolder,
|
||||
env: {
|
||||
...process.env,
|
||||
@@ -83,9 +89,30 @@ export default class Dev extends Command {
|
||||
},
|
||||
name: 'n8n',
|
||||
color: picocolors.green,
|
||||
});
|
||||
allowOutput: (line) => {
|
||||
if (line.includes('Initializing n8n process')) {
|
||||
resolve();
|
||||
}
|
||||
|
||||
return setupComplete;
|
||||
},
|
||||
});
|
||||
}),
|
||||
new Promise<void>((_, reject) => {
|
||||
setTimeout(() => {
|
||||
const error = new Error('n8n startup timeout after 120 seconds');
|
||||
onCancel(error.message);
|
||||
reject(error);
|
||||
}, 120_000);
|
||||
}),
|
||||
]);
|
||||
|
||||
setupComplete = true;
|
||||
npxN8nSpinner.stop('Started n8n dev server');
|
||||
}
|
||||
|
||||
outro('✓ Setup complete');
|
||||
|
||||
// Run `tsc --watch` in background
|
||||
runPersistentCommand(packageManager, ['exec', '--', 'tsc', '--watch'], {
|
||||
name: 'build',
|
||||
|
||||
@@ -25,8 +25,14 @@ export function commands() {
|
||||
function runPersistentCommand(
|
||||
cmd: string,
|
||||
args: string[],
|
||||
opts: { cwd?: string; env?: NodeJS.ProcessEnv; name?: string; color?: Formatter } = {},
|
||||
): void {
|
||||
opts: {
|
||||
cwd?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
name?: string;
|
||||
color?: Formatter;
|
||||
allowOutput?: (line: string) => boolean;
|
||||
} = {},
|
||||
) {
|
||||
const child = spawn(cmd, args, {
|
||||
cwd: opts.cwd,
|
||||
env: { ...process.env, ...opts.env },
|
||||
@@ -46,6 +52,7 @@ export function commands() {
|
||||
}
|
||||
|
||||
const log = (text: string) => {
|
||||
if (opts.allowOutput && !opts.allowOutput(text)) return;
|
||||
if (opts.name) {
|
||||
const rawPrefix = `[${opts.name}]`;
|
||||
const prefix = opts.color ? opts.color(rawPrefix) : rawPrefix;
|
||||
@@ -71,6 +78,8 @@ export function commands() {
|
||||
console.log(`${opts.name ?? cmd} exited with code ${code}`);
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@@ -647,6 +647,10 @@ importers:
|
||||
'@n8n/node-cli':
|
||||
specifier: workspace:*
|
||||
version: link:../node-cli
|
||||
devDependencies:
|
||||
'@n8n/typescript-config':
|
||||
specifier: workspace:*
|
||||
version: link:../typescript-config
|
||||
|
||||
packages/@n8n/db:
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user