n8nac 0.9.9-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -0
- package/dist/bin/legacy.d.ts +3 -0
- package/dist/bin/legacy.d.ts.map +1 -0
- package/dist/bin/legacy.js +7 -0
- package/dist/bin/legacy.js.map +1 -0
- package/dist/commands/base.d.ts +18 -0
- package/dist/commands/base.d.ts.map +1 -0
- package/dist/commands/base.js +58 -0
- package/dist/commands/base.js.map +1 -0
- package/dist/commands/convert.d.ts +18 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +174 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/init-ai.d.ts +10 -0
- package/dist/commands/init-ai.d.ts.map +1 -0
- package/dist/commands/init-ai.js +87 -0
- package/dist/commands/init-ai.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +133 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +11 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +123 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/switch.d.ts +7 -0
- package/dist/commands/switch.d.ts.map +1 -0
- package/dist/commands/switch.js +88 -0
- package/dist/commands/switch.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +124 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/core/assets/n8n-workflows.d.ts +320 -0
- package/dist/core/helpers/index.d.ts +8 -0
- package/dist/core/helpers/index.d.ts.map +1 -0
- package/dist/core/helpers/index.js +8 -0
- package/dist/core/helpers/index.js.map +1 -0
- package/dist/core/helpers/project-helpers.d.ts +93 -0
- package/dist/core/helpers/project-helpers.d.ts.map +1 -0
- package/dist/core/helpers/project-helpers.js +168 -0
- package/dist/core/helpers/project-helpers.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/services/cli-api.d.ts +89 -0
- package/dist/core/services/cli-api.d.ts.map +1 -0
- package/dist/core/services/cli-api.js +98 -0
- package/dist/core/services/cli-api.js.map +1 -0
- package/dist/core/services/directory-utils.d.ts +41 -0
- package/dist/core/services/directory-utils.d.ts.map +1 -0
- package/dist/core/services/directory-utils.js +87 -0
- package/dist/core/services/directory-utils.js.map +1 -0
- package/dist/core/services/hash-utils.d.ts +22 -0
- package/dist/core/services/hash-utils.d.ts.map +1 -0
- package/dist/core/services/hash-utils.js +31 -0
- package/dist/core/services/hash-utils.js.map +1 -0
- package/dist/core/services/n8n-api-client.d.ts +49 -0
- package/dist/core/services/n8n-api-client.d.ts.map +1 -0
- package/dist/core/services/n8n-api-client.js +504 -0
- package/dist/core/services/n8n-api-client.js.map +1 -0
- package/dist/core/services/resolution-manager.d.ts +73 -0
- package/dist/core/services/resolution-manager.d.ts.map +1 -0
- package/dist/core/services/resolution-manager.js +135 -0
- package/dist/core/services/resolution-manager.js.map +1 -0
- package/dist/core/services/state-manager.d.ts +44 -0
- package/dist/core/services/state-manager.d.ts.map +1 -0
- package/dist/core/services/state-manager.js +68 -0
- package/dist/core/services/state-manager.js.map +1 -0
- package/dist/core/services/sync-engine.d.ts +48 -0
- package/dist/core/services/sync-engine.d.ts.map +1 -0
- package/dist/core/services/sync-engine.js +285 -0
- package/dist/core/services/sync-engine.js.map +1 -0
- package/dist/core/services/sync-manager.d.ts +84 -0
- package/dist/core/services/sync-manager.d.ts.map +1 -0
- package/dist/core/services/sync-manager.js +280 -0
- package/dist/core/services/sync-manager.js.map +1 -0
- package/dist/core/services/watcher.d.ts +189 -0
- package/dist/core/services/watcher.d.ts.map +1 -0
- package/dist/core/services/watcher.js +1267 -0
- package/dist/core/services/watcher.js.map +1 -0
- package/dist/core/services/workflow-sanitizer.d.ts +38 -0
- package/dist/core/services/workflow-sanitizer.d.ts.map +1 -0
- package/dist/core/services/workflow-sanitizer.js +161 -0
- package/dist/core/services/workflow-sanitizer.js.map +1 -0
- package/dist/core/services/workflow-transformer-adapter.d.ts +87 -0
- package/dist/core/services/workflow-transformer-adapter.d.ts.map +1 -0
- package/dist/core/services/workflow-transformer-adapter.js +234 -0
- package/dist/core/services/workflow-transformer-adapter.js.map +1 -0
- package/dist/core/services/workspace-setup-service.d.ts +36 -0
- package/dist/core/services/workspace-setup-service.d.ts.map +1 -0
- package/dist/core/services/workspace-setup-service.js +107 -0
- package/dist/core/services/workspace-setup-service.js.map +1 -0
- package/dist/core/types.d.ts +58 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +140 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +7 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +7 -0
- package/dist/lib.js.map +1 -0
- package/dist/services/config-service.d.ts +46 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +162 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/utils/cli-helpers.d.ts +17 -0
- package/dist/utils/cli-helpers.d.ts.map +1 -0
- package/dist/utils/cli-helpers.js +56 -0
- package/dist/utils/cli-helpers.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# <img src="https://raw.githubusercontent.com/EtienneLescot/n8n-as-code/main/res/logo.png" alt="n8n-as-code logo" width="32" height="32"> n8nac
|
|
2
|
+
|
|
3
|
+
The main command-line interface for the **n8n-as-code** ecosystem. Manage, synchronize, and version-control your n8n workflows as TypeScript files.
|
|
4
|
+
|
|
5
|
+
> This package also embeds the synchronization engine and exposes it as a library for the VS Code extension. It includes a `skills` subcommand group that forwards to `@n8n-as-code/skills` for AI agent tooling.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g n8nac
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### `init`
|
|
16
|
+
Interactive wizard ā configure the connection to an n8n instance and pick the active project.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
n8nac init
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Creates `n8nac.json` in the current folder and stores the API key outside the repo.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
### `switch`
|
|
27
|
+
Switch the active n8n project (updates `projectId` / `projectName` in `n8nac.json`).
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
n8nac switch
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### `list`
|
|
36
|
+
Display workflow status in a git-like model. By default shows combined local and remote workflows.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
n8nac list # Combined view (default)
|
|
40
|
+
n8nac list --local # Show only local workflows
|
|
41
|
+
n8nac list --remote # Show only remote workflows (alias: --distant)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Output columns: `Status` Ā· `ID` Ā· `Name` Ā· `Local Path`
|
|
45
|
+
|
|
46
|
+
Status values:
|
|
47
|
+
|
|
48
|
+
| Status | Meaning | Action |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `TRACKED` | Workflow exists on both sides, no local changes detected | Nothing to do |
|
|
51
|
+
| `MODIFIED_LOCALLY` | Local file changed since last sync | `push --workflowsid` |
|
|
52
|
+
| `CONFLICT` | Both sides changed ā detected at push/pull time | `pull --workflowsid` (keep remote) or `push --workflowsid` (keep local) |
|
|
53
|
+
| `EXIST_ONLY_LOCALLY` | New local file not yet in n8n (or remote was deleted) | `push --workflowsid` to create in n8n |
|
|
54
|
+
| `EXIST_ONLY_REMOTELY` | Remote workflow not yet local (or local was deleted) | `pull --workflowsid` to download |
|
|
55
|
+
|
|
56
|
+
> **Git-like sync**: Status is a point-in-time observation. Use `fetch` to update remote state cache.
|
|
57
|
+
> **For agents**: always run `n8nac list` first to get workflow IDs and their current status before pulling or pushing.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### `fetch --workflowsid <workflowId>`
|
|
62
|
+
Update remote state cache for a specific workflow (internal reference for comparison).
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
n8nac fetch --workflowsid <workflowId> # Fetch specific workflow's remote state
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Updates internal comparison cache for the specified workflow only
|
|
69
|
+
- Use before `list` to ensure status reflects latest remote state for that workflow
|
|
70
|
+
- Required for accurate conflict detection
|
|
71
|
+
- For heavy instances, fetch individual workflows rather than all at once
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### `pull --workflowsid <workflowId>`
|
|
76
|
+
Download a single workflow from n8n and overwrite the local file.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
n8nac pull --workflowsid <workflowId>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> Recommended for agents and scripts. Targets exactly one workflow.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### `push --workflowsid <workflowId>`
|
|
87
|
+
Upload a single local workflow file to n8n.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
n8nac push --workflowsid <workflowId>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### `resolve --workflowsid <id> --mode <mode>`
|
|
96
|
+
Explicitly resolve a conflict for a specific workflow.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
n8nac resolve --workflowsid <id> --mode keep-current # Force-push local version
|
|
100
|
+
n8nac resolve --workflowsid <id> --mode keep-incoming # Force-pull remote version
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### `update-ai`
|
|
106
|
+
Generate or refresh AI context files in the project root. This command creates `AGENTS.md`, VS Code snippets, and editor rule files.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
n8nac update-ai
|
|
110
|
+
# or equivalently:
|
|
111
|
+
n8nac skills update-ai
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
AI tooling commands are available as `n8nac skills <command>` ā powered by `@n8n-as-code/skills`. Run via npx (no global install needed):
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx n8nac skills --help
|
|
118
|
+
npx n8nac skills search "google sheets"
|
|
119
|
+
npx n8nac skills node-info googleSheets
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### `convert`
|
|
125
|
+
Convert a single workflow between JSON and TypeScript formats.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
n8nac convert <file>
|
|
129
|
+
n8nac convert my-workflow.json --format typescript
|
|
130
|
+
n8nac convert my-workflow.workflow.ts --format json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `convert-batch`
|
|
134
|
+
Batch-convert all workflows in a directory.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
n8nac convert-batch workflows/ --format typescript
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## š¤ Agent workflow
|
|
143
|
+
|
|
144
|
+
The intended flow for an AI agent editing a workflow:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# 1. Fetch current state and get workflow IDs
|
|
148
|
+
n8nac list
|
|
149
|
+
|
|
150
|
+
# 2. Pull the target workflow
|
|
151
|
+
n8nac pull --workflowsid <workflowId>
|
|
152
|
+
|
|
153
|
+
# 3. Edit the local .workflow.ts file
|
|
154
|
+
|
|
155
|
+
# 4. Push it back
|
|
156
|
+
n8nac push --workflowsid <workflowId>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## š Part of the Ecosystem
|
|
162
|
+
- `@n8n-as-code/skills`: Internal AI-integration library (node search, schemas, context generation) ā accessible via `n8nac skills`.
|
|
163
|
+
- `vscode-extension`: Visual editing in VS Code (uses this package as its sync library).
|
|
164
|
+
|
|
165
|
+
## š License
|
|
166
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy.d.ts","sourceRoot":"","sources":["../../src/bin/legacy.ts"],"names":[],"mappings":";AAOA,OAAO,aAAa,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
console.warn(chalk.yellow('ā ļø Warning: "n8n-as-code" is deprecated and will be removed in a future version.'));
|
|
4
|
+
console.warn(chalk.yellow(' Please use the new "n8nac" command instead.\n'));
|
|
5
|
+
// Import the main CLI
|
|
6
|
+
import '../index.js';
|
|
7
|
+
//# sourceMappingURL=legacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy.js","sourceRoot":"","sources":["../../src/bin/legacy.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mFAAmF,CAAC,CAAC,CAAC;AAChH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,kDAAkD,CAAC,CAAC,CAAC;AAE/E,sBAAsB;AACtB,OAAO,aAAa,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { N8nApiClient } from '../core/index.js';
|
|
2
|
+
import { ConfigService } from '../services/config-service.js';
|
|
3
|
+
export declare class BaseCommand {
|
|
4
|
+
protected client: N8nApiClient;
|
|
5
|
+
protected config: any;
|
|
6
|
+
protected configService: ConfigService;
|
|
7
|
+
protected instanceIdentifier: string | null;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Get or create instance identifier and ensure it's in the config
|
|
11
|
+
*/
|
|
12
|
+
protected ensureInstanceIdentifier(): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Get sync config with instance identifier
|
|
15
|
+
*/
|
|
16
|
+
protected getSyncConfig(): Promise<any>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/commands/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmB,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,qBAAa,WAAW;IACpB,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;IAC/B,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;IACtB,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,SAAS,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAQ;;IA6BnD;;OAEG;cACa,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC;IAS3D;;OAEG;cACa,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC;CAchD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { N8nApiClient } from '../core/index.js';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ConfigService } from '../services/config-service.js';
|
|
4
|
+
export class BaseCommand {
|
|
5
|
+
client;
|
|
6
|
+
config;
|
|
7
|
+
configService;
|
|
8
|
+
instanceIdentifier = null;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.configService = new ConfigService();
|
|
11
|
+
const localConfig = this.configService.getLocalConfig();
|
|
12
|
+
const apiKey = localConfig.host ? this.configService.getApiKey(localConfig.host) : undefined;
|
|
13
|
+
if (!localConfig.host || !apiKey) {
|
|
14
|
+
console.error(chalk.red('ā CLI not configured.'));
|
|
15
|
+
console.error(chalk.yellow('Please run `n8nac init` to set up your environment.'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const credentials = {
|
|
19
|
+
host: localConfig.host,
|
|
20
|
+
apiKey: apiKey
|
|
21
|
+
};
|
|
22
|
+
this.client = new N8nApiClient(credentials);
|
|
23
|
+
// Basic config defaults from local config (syncInactive/ignoredTags now hardcoded defaults)
|
|
24
|
+
this.config = {
|
|
25
|
+
directory: localConfig.syncFolder || './workflows',
|
|
26
|
+
syncInactive: true,
|
|
27
|
+
ignoredTags: [],
|
|
28
|
+
host: localConfig.host
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get or create instance identifier and ensure it's in the config
|
|
33
|
+
*/
|
|
34
|
+
async ensureInstanceIdentifier() {
|
|
35
|
+
if (this.instanceIdentifier) {
|
|
36
|
+
return this.instanceIdentifier;
|
|
37
|
+
}
|
|
38
|
+
this.instanceIdentifier = await this.configService.getOrCreateInstanceIdentifier(this.config.host);
|
|
39
|
+
return this.instanceIdentifier;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get sync config with instance identifier
|
|
43
|
+
*/
|
|
44
|
+
async getSyncConfig() {
|
|
45
|
+
const instanceIdentifier = await this.ensureInstanceIdentifier();
|
|
46
|
+
const localConfig = this.configService.getLocalConfig();
|
|
47
|
+
return {
|
|
48
|
+
directory: this.config.directory,
|
|
49
|
+
syncInactive: true,
|
|
50
|
+
ignoredTags: [],
|
|
51
|
+
instanceIdentifier: instanceIdentifier,
|
|
52
|
+
instanceConfigPath: this.configService.getInstanceConfigPath(),
|
|
53
|
+
projectId: localConfig.projectId,
|
|
54
|
+
projectName: localConfig.projectName
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/commands/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmB,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,MAAM,OAAO,WAAW;IACV,MAAM,CAAe;IACrB,MAAM,CAAM;IACZ,aAAa,CAAgB;IAC7B,kBAAkB,GAAkB,IAAI,CAAC;IAEnD;QACI,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE7F,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,qDAAqD,CAAC,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,MAAM,WAAW,GAAoB;YACjC,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,MAAM,EAAE,MAAM;SACjB,CAAC;QAEF,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;QAE5C,4FAA4F;QAC5F,IAAI,CAAC,MAAM,GAAG;YACV,SAAS,EAAE,WAAW,CAAC,UAAU,IAAI,aAAa;YAClD,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,WAAW,CAAC,IAAI;SACzB,CAAC;IACN,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,wBAAwB;QACpC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,kBAAkB,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,kBAAkB,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnG,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACnC,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,aAAa;QACzB,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACjE,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QAExD,OAAO;YACH,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,EAAE;YACf,kBAAkB,EAAE,kBAAkB;YACtC,kBAAkB,EAAE,IAAI,CAAC,aAAa,CAAC,qBAAqB,EAAE;YAC9D,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,WAAW,EAAE,WAAW,CAAC,WAAW;SACvC,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class ConvertCommand {
|
|
2
|
+
/**
|
|
3
|
+
* Convert workflow: JSON ā TypeScript or TypeScript ā JSON
|
|
4
|
+
*/
|
|
5
|
+
run(inputPath: string, options: {
|
|
6
|
+
output?: string;
|
|
7
|
+
force?: boolean;
|
|
8
|
+
format?: 'json' | 'typescript';
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Batch convert all workflows in a directory
|
|
12
|
+
*/
|
|
13
|
+
batch(dirPath: string, options: {
|
|
14
|
+
format: 'json' | 'typescript';
|
|
15
|
+
force?: boolean;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"AAYA,qBAAa,cAAc;IACvB;;OAEG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA6G1H;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAqE3G"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
4
|
+
import { resolve, basename, extname, join } from 'path';
|
|
5
|
+
import { JsonToAstParser, AstToTypeScriptGenerator, TypeScriptParser, WorkflowBuilder } from '@n8n-as-code/transformer';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
export class ConvertCommand {
|
|
8
|
+
/**
|
|
9
|
+
* Convert workflow: JSON ā TypeScript or TypeScript ā JSON
|
|
10
|
+
*/
|
|
11
|
+
async run(inputPath, options) {
|
|
12
|
+
const absoluteInput = resolve(process.cwd(), inputPath);
|
|
13
|
+
if (!existsSync(absoluteInput)) {
|
|
14
|
+
console.error(chalk.red(`ā File not found: ${inputPath}`));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const inputExt = extname(absoluteInput);
|
|
18
|
+
const isTypeScript = inputExt === '.ts' || absoluteInput.endsWith('.workflow.ts');
|
|
19
|
+
const isJson = inputExt === '.json';
|
|
20
|
+
if (!isTypeScript && !isJson) {
|
|
21
|
+
console.error(chalk.red(`ā Unsupported file type: ${inputExt}`));
|
|
22
|
+
console.error(chalk.gray(' Supported: .json, .ts, .workflow.ts'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// Determine target format
|
|
26
|
+
let targetFormat;
|
|
27
|
+
if (options.format) {
|
|
28
|
+
targetFormat = options.format;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Auto-detect: JSON ā TS, TS ā JSON
|
|
32
|
+
targetFormat = isJson ? 'typescript' : 'json';
|
|
33
|
+
}
|
|
34
|
+
// Validate conversion direction
|
|
35
|
+
if (isJson && targetFormat === 'json') {
|
|
36
|
+
console.error(chalk.yellow('ā ļø File is already JSON. Nothing to convert.'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (isTypeScript && targetFormat === 'typescript') {
|
|
40
|
+
console.error(chalk.yellow('ā ļø File is already TypeScript. Nothing to convert.'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Determine output path
|
|
44
|
+
let outputPath;
|
|
45
|
+
if (options.output) {
|
|
46
|
+
outputPath = resolve(process.cwd(), options.output);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Auto-generate output path
|
|
50
|
+
const baseName = basename(absoluteInput, inputExt);
|
|
51
|
+
const dir = join(absoluteInput, '..');
|
|
52
|
+
outputPath = targetFormat === 'typescript'
|
|
53
|
+
? join(dir, `${baseName.replace('.workflow', '')}.workflow.ts`)
|
|
54
|
+
: join(dir, `${baseName.replace('.workflow', '')}.json`);
|
|
55
|
+
}
|
|
56
|
+
// Check if output exists
|
|
57
|
+
if (existsSync(outputPath) && !options.force) {
|
|
58
|
+
const { overwrite } = await inquirer.prompt([
|
|
59
|
+
{
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
name: 'overwrite',
|
|
62
|
+
message: `Output file exists: ${basename(outputPath)}. Overwrite?`,
|
|
63
|
+
default: false
|
|
64
|
+
}
|
|
65
|
+
]);
|
|
66
|
+
if (!overwrite) {
|
|
67
|
+
console.log(chalk.gray('Conversion cancelled.'));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const spinner = ora(`Converting ${isJson ? 'JSON ā TypeScript' : 'TypeScript ā JSON'}...`).start();
|
|
72
|
+
try {
|
|
73
|
+
const inputContent = readFileSync(absoluteInput, 'utf-8');
|
|
74
|
+
let outputContent;
|
|
75
|
+
if (targetFormat === 'typescript') {
|
|
76
|
+
// JSON ā TypeScript
|
|
77
|
+
const workflow = JSON.parse(inputContent);
|
|
78
|
+
const parser = new JsonToAstParser();
|
|
79
|
+
const ast = parser.parse(workflow);
|
|
80
|
+
const generator = new AstToTypeScriptGenerator();
|
|
81
|
+
outputContent = await generator.generate(ast, {
|
|
82
|
+
format: true,
|
|
83
|
+
commentStyle: 'verbose'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// TypeScript ā JSON
|
|
88
|
+
const parser = new TypeScriptParser();
|
|
89
|
+
const ast = await parser.parseCode(inputContent);
|
|
90
|
+
const builder = new WorkflowBuilder();
|
|
91
|
+
const workflow = builder.build(ast);
|
|
92
|
+
outputContent = JSON.stringify(workflow, null, 2);
|
|
93
|
+
}
|
|
94
|
+
writeFileSync(outputPath, outputContent, 'utf-8');
|
|
95
|
+
spinner.succeed(chalk.green('Conversion successful!'));
|
|
96
|
+
console.log(chalk.cyan('\nš Details:'));
|
|
97
|
+
console.log(chalk.gray(` Input: ${basename(absoluteInput)}`));
|
|
98
|
+
console.log(chalk.gray(` Output: ${basename(outputPath)}`));
|
|
99
|
+
console.log(chalk.gray(` Size: ${outputContent.length} bytes\n`));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
spinner.fail(chalk.red('Conversion failed'));
|
|
103
|
+
console.error(chalk.red(`ā ${error.message}`));
|
|
104
|
+
if (error.stack) {
|
|
105
|
+
console.error(chalk.gray(error.stack));
|
|
106
|
+
}
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Batch convert all workflows in a directory
|
|
112
|
+
*/
|
|
113
|
+
async batch(dirPath, options) {
|
|
114
|
+
const absoluteDir = resolve(process.cwd(), dirPath);
|
|
115
|
+
if (!existsSync(absoluteDir)) {
|
|
116
|
+
console.error(chalk.red(`ā Directory not found: ${dirPath}`));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const fs = await import('fs/promises');
|
|
120
|
+
const files = await fs.readdir(absoluteDir);
|
|
121
|
+
const sourceExt = options.format === 'typescript' ? '.json' : '.workflow.ts';
|
|
122
|
+
const targetFiles = files.filter(f => f.endsWith(sourceExt));
|
|
123
|
+
if (targetFiles.length === 0) {
|
|
124
|
+
console.log(chalk.yellow(`ā ļø No ${sourceExt} files found in ${dirPath}`));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
console.log(chalk.cyan(`\nš Found ${targetFiles.length} file(s) to convert\n`));
|
|
128
|
+
let converted = 0;
|
|
129
|
+
let failed = 0;
|
|
130
|
+
for (const file of targetFiles) {
|
|
131
|
+
const inputPath = join(absoluteDir, file);
|
|
132
|
+
const baseName = basename(file, sourceExt);
|
|
133
|
+
const targetExt = options.format === 'typescript' ? '.workflow.ts' : '.json';
|
|
134
|
+
const outputPath = join(absoluteDir, `${baseName}${targetExt}`);
|
|
135
|
+
try {
|
|
136
|
+
const inputContent = readFileSync(inputPath, 'utf-8');
|
|
137
|
+
let outputContent;
|
|
138
|
+
if (options.format === 'typescript') {
|
|
139
|
+
// JSON ā TypeScript
|
|
140
|
+
const workflow = JSON.parse(inputContent);
|
|
141
|
+
const parser = new JsonToAstParser();
|
|
142
|
+
const ast = parser.parse(workflow);
|
|
143
|
+
const generator = new AstToTypeScriptGenerator();
|
|
144
|
+
outputContent = await generator.generate(ast, {
|
|
145
|
+
format: true,
|
|
146
|
+
commentStyle: 'verbose'
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// TypeScript ā JSON
|
|
151
|
+
const parser = new TypeScriptParser();
|
|
152
|
+
const ast = await parser.parseCode(inputContent);
|
|
153
|
+
const builder = new WorkflowBuilder();
|
|
154
|
+
const workflow = builder.build(ast);
|
|
155
|
+
outputContent = JSON.stringify(workflow, null, 2);
|
|
156
|
+
}
|
|
157
|
+
writeFileSync(outputPath, outputContent, 'utf-8');
|
|
158
|
+
console.log(chalk.green(`ā
${file} ā ${basename(outputPath)}`));
|
|
159
|
+
converted++;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error(chalk.red(`ā ${file}: ${error.message}`));
|
|
163
|
+
failed++;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
console.log(chalk.cyan(`\nš Summary:`));
|
|
167
|
+
console.log(chalk.gray(` Converted: ${converted}`));
|
|
168
|
+
if (failed > 0) {
|
|
169
|
+
console.log(chalk.red(` Failed: ${failed}`));
|
|
170
|
+
}
|
|
171
|
+
console.log();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { IN8nCredentials } from '../core/index.js';
|
|
3
|
+
export declare class UpdateAiCommand {
|
|
4
|
+
private program;
|
|
5
|
+
constructor(program: Command);
|
|
6
|
+
run(options?: any, providedCredentials?: IN8nCredentials): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare class InitAiCommand extends UpdateAiCommand {
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=init-ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-ai.d.ts","sourceRoot":"","sources":["../../src/commands/init-ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,EAEH,eAAe,EAClB,MAAM,kBAAkB,CAAC;AAkB1B,qBAAa,eAAe;IACZ,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,OAAO;IASvB,GAAG,CAAC,OAAO,GAAE,GAAQ,EAAE,mBAAmB,CAAC,EAAE,eAAe;CAyD5E;AAGD,qBAAa,aAAc,SAAQ,eAAe;CAAI"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { N8nApiClient } from '../core/index.js';
|
|
6
|
+
import { AiContextGenerator, SnippetGenerator } from '@n8n-as-code/skills';
|
|
7
|
+
import dotenv from 'dotenv';
|
|
8
|
+
/** Returns 'next' if running from a pre-release build, undefined otherwise. */
|
|
9
|
+
function getDistTag() {
|
|
10
|
+
try {
|
|
11
|
+
const __dir = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const pkg = JSON.parse(readFileSync(join(__dir, '..', 'package.json'), 'utf8'));
|
|
13
|
+
return pkg.version?.includes('-') ? 'next' : undefined;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class UpdateAiCommand {
|
|
20
|
+
program;
|
|
21
|
+
constructor(program) {
|
|
22
|
+
this.program = program;
|
|
23
|
+
this.program
|
|
24
|
+
.command('update-ai')
|
|
25
|
+
.description('Update AI Context (AGENTS.md, rule files, snippets)')
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
await this.run(options);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async run(options = {}, providedCredentials) {
|
|
31
|
+
console.log(chalk.blue('š¤ Updating AI Context...'));
|
|
32
|
+
console.log(chalk.gray(' Regenerating AGENTS.md, rule files, and snippets\n'));
|
|
33
|
+
const projectRoot = process.cwd();
|
|
34
|
+
try {
|
|
35
|
+
// Initialize N8nApiClient if credentials are available
|
|
36
|
+
dotenv.config();
|
|
37
|
+
const credentials = providedCredentials || {
|
|
38
|
+
host: process.env.N8N_HOST || '',
|
|
39
|
+
apiKey: process.env.N8N_API_KEY || ''
|
|
40
|
+
};
|
|
41
|
+
let client;
|
|
42
|
+
if (credentials.host && credentials.apiKey) {
|
|
43
|
+
client = new N8nApiClient(credentials);
|
|
44
|
+
}
|
|
45
|
+
// 1. Fetch version once if possible
|
|
46
|
+
let version = "Unknown";
|
|
47
|
+
if (client) {
|
|
48
|
+
try {
|
|
49
|
+
const health = await client.getHealth();
|
|
50
|
+
version = health.version;
|
|
51
|
+
}
|
|
52
|
+
catch { } // Ignore version fetch error
|
|
53
|
+
}
|
|
54
|
+
// 2. Generate Context (AGENTS.md, rules)
|
|
55
|
+
console.log(chalk.gray('\n - Generating AI context files (AGENTS.md, rules)...'));
|
|
56
|
+
const aiContextGenerator = new AiContextGenerator();
|
|
57
|
+
await aiContextGenerator.generate(projectRoot, version, getDistTag());
|
|
58
|
+
console.log(chalk.green(' ā
AI context files created.'));
|
|
59
|
+
// 3. Generate VS Code Snippets
|
|
60
|
+
console.log(chalk.gray(' - Generating VS Code Snippets...'));
|
|
61
|
+
try {
|
|
62
|
+
const snippetGen = new SnippetGenerator();
|
|
63
|
+
await snippetGen.generate(projectRoot);
|
|
64
|
+
console.log(chalk.green(' ā
.vscode/n8n.code-snippets created.'));
|
|
65
|
+
}
|
|
66
|
+
catch (snippetError) {
|
|
67
|
+
console.log(chalk.yellow(` ā ļø Snippet generation skipped: ${snippetError.message}`));
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk.green('\n⨠AI Context Updated Successfully!'));
|
|
70
|
+
console.log(chalk.gray(' ā AGENTS.md: Complete AI agent guidelines'));
|
|
71
|
+
console.log(chalk.gray(' ā .cursorrules/.clinerules/.windsurfrules: AI agent rules'));
|
|
72
|
+
console.log(chalk.gray(' ā .vscode/n8n.code-snippets: Code completion snippets'));
|
|
73
|
+
console.log(chalk.gray(' ā Source of truth: n8n-nodes-technical.json (via @n8n-as-code/skills)\n'));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error(chalk.red(`ā Error during update-ai: ${error.message}`));
|
|
77
|
+
if (error.stack) {
|
|
78
|
+
console.error(chalk.gray(error.stack));
|
|
79
|
+
}
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Keep backward compatibility with old command name
|
|
85
|
+
export class InitAiCommand extends UpdateAiCommand {
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=init-ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-ai.js","sourceRoot":"","sources":["../../src/commands/init-ai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAQA,qBAAa,WAAW;IACpB,OAAO,CAAC,aAAa,CAAgB;;IAM/B,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAyI7B"}
|