diff --git a/packages/@n8n/create-node/README.md b/packages/@n8n/create-node/README.md index 9f02fec7cf..14f3d58496 100644 --- a/packages/@n8n/create-node/README.md +++ b/packages/@n8n/create-node/README.md @@ -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 diff --git a/packages/@n8n/create-node/bin/create-node.cjs b/packages/@n8n/create-node/bin/create-node.cjs new file mode 100755 index 0000000000..cb89956e38 --- /dev/null +++ b/packages/@n8n/create-node/bin/create-node.cjs @@ -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); diff --git a/packages/@n8n/create-node/bin/create.js b/packages/@n8n/create-node/bin/create.js deleted file mode 100755 index 5608e90b16..0000000000 --- a/packages/@n8n/create-node/bin/create.js +++ /dev/null @@ -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); diff --git a/packages/@n8n/create-node/package.json b/packages/@n8n/create-node/package.json index d4820749ed..96a2149403 100644 --- a/packages/@n8n/create-node/package.json +++ b/packages/@n8n/create-node/package.json @@ -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:*" } } diff --git a/packages/@n8n/node-cli/README.md b/packages/@n8n/node-cli/README.md index 350e30c7dd..e8f62e3216 100644 --- a/packages/@n8n/node-cli/README.md +++ b/packages/@n8n/node-cli/README.md @@ -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 diff --git a/packages/@n8n/node-cli/package.json b/packages/@n8n/node-cli/package.json index 28c2134dcb..61efe96085 100644 --- a/packages/@n8n/node-cli/package.json +++ b/packages/@n8n/node-cli/package.json @@ -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" diff --git a/packages/@n8n/node-cli/src/commands/dev/index.ts b/packages/@n8n/node-cli/src/commands/dev/index.ts index cbf98ca869..65c7812281 100644 --- a/packages/@n8n/node-cli/src/commands/dev/index.ts +++ b/packages/@n8n/node-cli/src/commands/dev/index.ts @@ -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,25 +67,52 @@ 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'], { - cwd: n8nUserFolder, - env: { - ...process.env, - N8N_DEV_RELOAD: 'true', - N8N_RUNNERS_ENABLED: 'true', - DB_SQLITE_POOL_SIZE: '10', - N8N_USER_FOLDER: n8nUserFolder, - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: 'false', - }, - name: 'n8n', - color: picocolors.green, - }); + 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((resolve) => { + runPersistentCommand('npx', ['-y', '--quiet', '--prefer-online', 'n8n@next'], { + cwd: n8nUserFolder, + env: { + ...process.env, + N8N_DEV_RELOAD: 'true', + N8N_RUNNERS_ENABLED: 'true', + DB_SQLITE_POOL_SIZE: '10', + N8N_USER_FOLDER: n8nUserFolder, + N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: 'false', + }, + name: 'n8n', + color: picocolors.green, + allowOutput: (line) => { + if (line.includes('Initializing n8n process')) { + resolve(); + } + + return setupComplete; + }, + }); + }), + new Promise((_, 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', diff --git a/packages/@n8n/node-cli/src/commands/dev/utils.ts b/packages/@n8n/node-cli/src/commands/dev/utils.ts index e055bd0223..09d5059fd6 100644 --- a/packages/@n8n/node-cli/src/commands/dev/utils.ts +++ b/packages/@n8n/node-cli/src/commands/dev/utils.ts @@ -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 { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0fb75a7070..4ba8594a7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: