@jonmash/n8n-nodes-altium365 0.1.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/LICENSE.md +21 -0
- package/README.md +245 -0
- package/dist/credentials/Altium365NexarApi.credentials.d.ts +10 -0
- package/dist/credentials/Altium365NexarApi.credentials.d.ts.map +1 -0
- package/dist/credentials/Altium365NexarApi.credentials.js +60 -0
- package/dist/credentials/Altium365NexarApi.credentials.js.map +1 -0
- package/dist/nodes/Altium365/Altium365.node.d.ts +6 -0
- package/dist/nodes/Altium365/Altium365.node.d.ts.map +1 -0
- package/dist/nodes/Altium365/Altium365.node.js +275 -0
- package/dist/nodes/Altium365/Altium365.node.js.map +1 -0
- package/dist/nodes/Altium365/altium365.svg +189 -0
- package/dist/nodes/Altium365/altiumn8n.svg +189 -0
- package/dist/nodes/Altium365Trigger/Altium365Trigger.node.d.ts +8 -0
- package/dist/nodes/Altium365Trigger/Altium365Trigger.node.d.ts.map +1 -0
- package/dist/nodes/Altium365Trigger/Altium365Trigger.node.js +204 -0
- package/dist/nodes/Altium365Trigger/Altium365Trigger.node.js.map +1 -0
- package/dist/nodes/Altium365Trigger/altium365trigger.svg +189 -0
- package/dist/nodes/Altium365Trigger/altiumn8n.svg +189 -0
- package/dist/shared/NexarClient.d.ts +31 -0
- package/dist/shared/NexarClient.d.ts.map +1 -0
- package/dist/shared/NexarClient.js +79 -0
- package/dist/shared/NexarClient.js.map +1 -0
- package/dist/shared/generated/graphql.d.ts +10549 -0
- package/dist/shared/generated/graphql.d.ts.map +1 -0
- package/dist/shared/generated/graphql.js +168 -0
- package/dist/shared/generated/graphql.js.map +1 -0
- package/package.json +87 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jon Mash
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# @jonmash/n8n-nodes-altium365
|
|
2
|
+
|
|
3
|
+
This is an n8n community node that integrates n8n with Altium 365 via the Nexar GraphQL API.
|
|
4
|
+
|
|
5
|
+
[n8n](https://n8n.io/) is a workflow automation platform with a visual editor.
|
|
6
|
+
|
|
7
|
+
[Altium 365](https://www.altium.com/altium-365) is a cloud platform for electronics design collaboration.
|
|
8
|
+
|
|
9
|
+
[Nexar API](https://nexar.com/api) is the GraphQL API for programmatic access to Altium 365 data.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Action Node (Altium 365)
|
|
14
|
+
|
|
15
|
+
**Projects**
|
|
16
|
+
- Get project by ID
|
|
17
|
+
- Get many projects (with pagination)
|
|
18
|
+
- Get latest commit for a project
|
|
19
|
+
- Get commit history for a project
|
|
20
|
+
- Update project parameters
|
|
21
|
+
|
|
22
|
+
**Workspaces**
|
|
23
|
+
- Get all workspaces
|
|
24
|
+
|
|
25
|
+
### Trigger Node (Altium 365 Trigger)
|
|
26
|
+
|
|
27
|
+
**Events**
|
|
28
|
+
- **Project Committed** - Triggers when a project is committed (Git push detected)
|
|
29
|
+
- Monitor specific project or all projects in workspace
|
|
30
|
+
- Includes file change details
|
|
31
|
+
- Returns commit message, author, timestamp
|
|
32
|
+
- **New Project** - Triggers when a new project is created in the workspace
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
### In n8n (recommended)
|
|
37
|
+
|
|
38
|
+
1. Go to **Settings** > **Community Nodes**
|
|
39
|
+
2. Select **Install**
|
|
40
|
+
3. Enter `@jonmash/n8n-nodes-altium365` in **Enter npm package name**
|
|
41
|
+
4. Agree to the risks of using community nodes
|
|
42
|
+
5. Select **Install**
|
|
43
|
+
|
|
44
|
+
After installing the node, you can use it in your workflows.
|
|
45
|
+
|
|
46
|
+
### Manual Installation
|
|
47
|
+
|
|
48
|
+
To install manually, navigate to your n8n installation directory and run:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install @jonmash/n8n-nodes-altium365
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For Docker-based deployments, add this to your `package.json` or Dockerfile.
|
|
55
|
+
|
|
56
|
+
## Credentials
|
|
57
|
+
|
|
58
|
+
This node requires Altium 365 Nexar API credentials.
|
|
59
|
+
|
|
60
|
+
### Setting up Nexar API Access
|
|
61
|
+
|
|
62
|
+
1. **Sign up at Nexar Portal**
|
|
63
|
+
- Go to [portal.nexar.com](https://portal.nexar.com/)
|
|
64
|
+
- Sign in with your Altium Live credentials (they link automatically)
|
|
65
|
+
|
|
66
|
+
2. **Create an Application**
|
|
67
|
+
- Click **Create Application**
|
|
68
|
+
- Give it a name (e.g., "n8n Integration")
|
|
69
|
+
- Enable the **Design** scope
|
|
70
|
+
- Save the application
|
|
71
|
+
|
|
72
|
+
3. **Get Credentials**
|
|
73
|
+
- Go to the **Authorization** tab
|
|
74
|
+
- Copy the **Client ID**
|
|
75
|
+
- Copy the **Client Secret** (guard this carefully!)
|
|
76
|
+
|
|
77
|
+
4. **Find Your Workspace URL**
|
|
78
|
+
- Your workspace URL follows the format: `https://YOURWORKSPACE.365.altium.com/`
|
|
79
|
+
- You can find this in your Altium 365 web interface URL
|
|
80
|
+
|
|
81
|
+
### Configuring in n8n
|
|
82
|
+
|
|
83
|
+
1. In n8n, create a new credential of type **Altium 365 Nexar API**
|
|
84
|
+
2. Enter your **Client ID**
|
|
85
|
+
3. Enter your **Client Secret**
|
|
86
|
+
4. Enter your **Workspace URL** (e.g., `https://mycompany.365.altium.com/`)
|
|
87
|
+
5. Test the credential to verify it works
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
### Example: Monitor Project Commits
|
|
92
|
+
|
|
93
|
+
Set up a workflow that triggers whenever a project is committed:
|
|
94
|
+
|
|
95
|
+
1. Add **Altium 365 Trigger** node
|
|
96
|
+
2. Select event: **Project Committed**
|
|
97
|
+
3. (Optional) Enter a specific **Project ID** to monitor one project, or leave blank to monitor all projects
|
|
98
|
+
4. Connect to any action (Slack notification, email, webhook, etc.)
|
|
99
|
+
|
|
100
|
+
The trigger outputs:
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"projectId": "abc123",
|
|
104
|
+
"projectName": "PowerSupply_v2",
|
|
105
|
+
"revisionId": "e4f8a9b2c1d3",
|
|
106
|
+
"message": "Fixed power rail routing on layer 3",
|
|
107
|
+
"author": "John Smith",
|
|
108
|
+
"committedAt": "2025-03-14T10:23:00Z",
|
|
109
|
+
"filesChanged": [
|
|
110
|
+
{
|
|
111
|
+
"kind": "MODIFIED",
|
|
112
|
+
"path": "PowerBoard.PcbDoc"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"kind": "MODIFIED",
|
|
116
|
+
"path": "PowerSchematic.SchDoc"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Example: Get Project Details
|
|
123
|
+
|
|
124
|
+
1. Add **Altium 365** action node
|
|
125
|
+
2. Select resource: **Project**
|
|
126
|
+
3. Select operation: **Get**
|
|
127
|
+
4. Enter the **Project ID**
|
|
128
|
+
|
|
129
|
+
Returns complete project information including metadata, parameters, and variant count.
|
|
130
|
+
|
|
131
|
+
### Example: List All Projects
|
|
132
|
+
|
|
133
|
+
1. Add **Altium 365** action node
|
|
134
|
+
2. Select resource: **Project**
|
|
135
|
+
3. Select operation: **Get Many**
|
|
136
|
+
4. Choose **Return All** or set a **Limit**
|
|
137
|
+
|
|
138
|
+
Returns paginated list of all projects in your workspace.
|
|
139
|
+
|
|
140
|
+
## API Rate Limits
|
|
141
|
+
|
|
142
|
+
- Design queries are **free and unlimited** with an active Altium 365 subscription
|
|
143
|
+
- OAuth tokens are valid for 24 hours and automatically refreshed
|
|
144
|
+
- The node caches tokens to minimize authentication requests
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
### Prerequisites
|
|
149
|
+
|
|
150
|
+
- Node.js >= 18.17.0
|
|
151
|
+
- npm >= 10.x
|
|
152
|
+
- Active Altium 365 subscription
|
|
153
|
+
- Nexar API credentials with Design scope
|
|
154
|
+
|
|
155
|
+
### Setup
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Clone the repository
|
|
159
|
+
git clone https://github.com/jonmash/n8n-nodes-altium365.git
|
|
160
|
+
cd n8n-nodes-altium365 # Note: package is published as @jonmash/n8n-nodes-altium365
|
|
161
|
+
|
|
162
|
+
# Install dependencies
|
|
163
|
+
npm install
|
|
164
|
+
|
|
165
|
+
# Generate GraphQL types from Nexar schema
|
|
166
|
+
npm run codegen
|
|
167
|
+
|
|
168
|
+
# Build the node
|
|
169
|
+
npm run build
|
|
170
|
+
|
|
171
|
+
# Run linter
|
|
172
|
+
npm run lint
|
|
173
|
+
|
|
174
|
+
# Format code
|
|
175
|
+
npm run format
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Project Structure
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
@jonmash/n8n-nodes-altium365/
|
|
182
|
+
├── credentials/
|
|
183
|
+
│ └── Altium365NexarApi.credentials.ts # OAuth2 credentials
|
|
184
|
+
├── nodes/
|
|
185
|
+
│ ├── Altium365/
|
|
186
|
+
│ │ ├── Altium365.node.ts # Main action node
|
|
187
|
+
│ │ └── altium365.svg # Node icon
|
|
188
|
+
│ └── Altium365Trigger/
|
|
189
|
+
│ ├── Altium365Trigger.node.ts # Polling trigger node
|
|
190
|
+
│ └── altium365trigger.svg # Trigger icon
|
|
191
|
+
├── shared/
|
|
192
|
+
│ ├── NexarClient.ts # GraphQL client with token caching
|
|
193
|
+
│ ├── queries/ # GraphQL query definitions
|
|
194
|
+
│ │ ├── workspace.graphql
|
|
195
|
+
│ │ └── projects.graphql
|
|
196
|
+
│ └── generated/
|
|
197
|
+
│ └── graphql.ts # Auto-generated types from schema
|
|
198
|
+
└── package.json
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### GraphQL Code Generation
|
|
202
|
+
|
|
203
|
+
This package uses GraphQL Code Generator to create fully typed SDK from the Nexar schema:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Regenerate types after modifying .graphql files
|
|
207
|
+
npm run codegen
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The codegen:
|
|
211
|
+
1. Introspects the Nexar GraphQL schema
|
|
212
|
+
2. Validates your queries against the schema
|
|
213
|
+
3. Generates TypeScript types and SDK functions
|
|
214
|
+
4. Provides full autocomplete and type safety
|
|
215
|
+
|
|
216
|
+
## Compatibility
|
|
217
|
+
|
|
218
|
+
- Tested with n8n version: 1.x
|
|
219
|
+
- Node.js: >= 18.17.0
|
|
220
|
+
- Altium 365: Current version (2025)
|
|
221
|
+
|
|
222
|
+
## Resources
|
|
223
|
+
|
|
224
|
+
- [n8n Documentation](https://docs.n8n.io/)
|
|
225
|
+
- [Nexar API Documentation](https://nexar.com/api)
|
|
226
|
+
- [Nexar Portal](https://portal.nexar.com/)
|
|
227
|
+
- [Altium 365](https://www.altium.com/altium-365)
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
[MIT](LICENSE.md)
|
|
232
|
+
|
|
233
|
+
## Contributing
|
|
234
|
+
|
|
235
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
236
|
+
|
|
237
|
+
## Support
|
|
238
|
+
|
|
239
|
+
For issues and questions:
|
|
240
|
+
- [GitHub Issues](https://github.com/jonmash/n8n-nodes-altium365/issues)
|
|
241
|
+
- [Nexar Community](https://community.nexar.com/)
|
|
242
|
+
|
|
243
|
+
## Changelog
|
|
244
|
+
|
|
245
|
+
See [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class Altium365NexarApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
test: ICredentialTestRequest;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=Altium365NexarApi.credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Altium365NexarApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/Altium365NexarApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,MAAM,cAAc,CAAC;AAEtB,qBAAa,iBAAkB,YAAW,eAAe;IACxD,IAAI,SAAuB;IAE3B,WAAW,SAA0B;IAErC,gBAAgB,SAA+B;IAE/C,UAAU,EAAE,eAAe,EAAE,CA2B3B;IAEF,YAAY,EAAE,oBAAoB,CAKhC;IAEF,IAAI,EAAE,sBAAsB,CAe1B;CACF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Altium365NexarApi = void 0;
|
|
4
|
+
class Altium365NexarApi {
|
|
5
|
+
name = 'altium365NexarApi';
|
|
6
|
+
displayName = 'Altium 365 Nexar API';
|
|
7
|
+
documentationUrl = 'https://portal.nexar.com/';
|
|
8
|
+
properties = [
|
|
9
|
+
{
|
|
10
|
+
displayName: 'Client ID',
|
|
11
|
+
name: 'clientId',
|
|
12
|
+
type: 'string',
|
|
13
|
+
default: '',
|
|
14
|
+
required: true,
|
|
15
|
+
description: 'The Client ID from your Nexar application',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
displayName: 'Client Secret',
|
|
19
|
+
name: 'clientSecret',
|
|
20
|
+
type: 'string',
|
|
21
|
+
typeOptions: { password: true },
|
|
22
|
+
default: '',
|
|
23
|
+
required: true,
|
|
24
|
+
description: 'The Client Secret from your Nexar application',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
displayName: 'Workspace URL',
|
|
28
|
+
name: 'workspaceUrl',
|
|
29
|
+
type: 'string',
|
|
30
|
+
default: '',
|
|
31
|
+
placeholder: 'https://yourworkspace.365.altium.com/',
|
|
32
|
+
required: true,
|
|
33
|
+
description: 'Your Altium 365 workspace URL',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
authenticate = {
|
|
37
|
+
type: 'generic',
|
|
38
|
+
properties: {
|
|
39
|
+
qs: {},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
test = {
|
|
43
|
+
request: {
|
|
44
|
+
baseURL: 'https://identity.nexar.com',
|
|
45
|
+
url: '/connect/token',
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
49
|
+
},
|
|
50
|
+
body: {
|
|
51
|
+
grant_type: 'client_credentials',
|
|
52
|
+
client_id: '={{$credentials.clientId}}',
|
|
53
|
+
client_secret: '={{$credentials.clientSecret}}',
|
|
54
|
+
scope: 'design.domain',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
exports.Altium365NexarApi = Altium365NexarApi;
|
|
60
|
+
//# sourceMappingURL=Altium365NexarApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Altium365NexarApi.credentials.js","sourceRoot":"","sources":["../../credentials/Altium365NexarApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,iBAAiB;IAC7B,IAAI,GAAG,mBAAmB,CAAC;IAE3B,WAAW,GAAG,sBAAsB,CAAC;IAErC,gBAAgB,GAAG,2BAA2B,CAAC;IAE/C,UAAU,GAAsB;QAC/B;YACC,WAAW,EAAE,WAAW;YACxB,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,2CAA2C;SACxD;QACD;YACC,WAAW,EAAE,eAAe;YAC5B,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC/B,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,+CAA+C;SAC5D;QACD;YACC,WAAW,EAAE,eAAe;YAC5B,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;YACX,WAAW,EAAE,uCAAuC;YACpD,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,+BAA+B;SAC5C;KACD,CAAC;IAEF,YAAY,GAAyB;QACpC,IAAI,EAAE,SAAS;QACf,UAAU,EAAE;YACX,EAAE,EAAE,EAAE;SACN;KACD,CAAC;IAEF,IAAI,GAA2B;QAC9B,OAAO,EAAE;YACR,OAAO,EAAE,4BAA4B;YACrC,GAAG,EAAE,gBAAgB;YACrB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACR,cAAc,EAAE,mCAAmC;aACnD;YACD,IAAI,EAAE;gBACL,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,4BAA4B;gBACvC,aAAa,EAAE,gCAAgC;gBAC/C,KAAK,EAAE,eAAe;aACtB;SACD;KACD,CAAC;CACF;AA3DD,8CA2DC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class Altium365 implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=Altium365.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Altium365.node.d.ts","sourceRoot":"","sources":["../../../nodes/Altium365/Altium365.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACpB,MAAM,cAAc,CAAC;AAKtB,qBAAa,SAAU,YAAW,SAAS;IAC1C,WAAW,EAAE,oBAAoB,CA2J/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAuJvE"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Altium365 = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const NexarClient_1 = require("../../shared/NexarClient");
|
|
6
|
+
class Altium365 {
|
|
7
|
+
description = {
|
|
8
|
+
displayName: 'Altium 365',
|
|
9
|
+
name: 'altium365',
|
|
10
|
+
icon: 'file:altium365.svg',
|
|
11
|
+
group: ['transform'],
|
|
12
|
+
version: 1,
|
|
13
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
14
|
+
description: 'Interact with Altium 365 via Nexar API',
|
|
15
|
+
defaults: {
|
|
16
|
+
name: 'Altium 365',
|
|
17
|
+
},
|
|
18
|
+
inputs: ['main'],
|
|
19
|
+
outputs: ['main'],
|
|
20
|
+
credentials: [
|
|
21
|
+
{
|
|
22
|
+
name: 'altium365NexarApi',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
properties: [
|
|
27
|
+
{
|
|
28
|
+
displayName: 'Resource',
|
|
29
|
+
name: 'resource',
|
|
30
|
+
type: 'options',
|
|
31
|
+
noDataExpression: true,
|
|
32
|
+
options: [
|
|
33
|
+
{
|
|
34
|
+
name: 'Project',
|
|
35
|
+
value: 'project',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Workspace',
|
|
39
|
+
value: 'workspace',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
default: 'project',
|
|
43
|
+
},
|
|
44
|
+
// Project operations
|
|
45
|
+
{
|
|
46
|
+
displayName: 'Operation',
|
|
47
|
+
name: 'operation',
|
|
48
|
+
type: 'options',
|
|
49
|
+
noDataExpression: true,
|
|
50
|
+
displayOptions: {
|
|
51
|
+
show: {
|
|
52
|
+
resource: ['project'],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
options: [
|
|
56
|
+
{
|
|
57
|
+
name: 'Get',
|
|
58
|
+
value: 'get',
|
|
59
|
+
description: 'Get a project by ID',
|
|
60
|
+
action: 'Get a project',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Get Many',
|
|
64
|
+
value: 'getMany',
|
|
65
|
+
description: 'Get many projects',
|
|
66
|
+
action: 'Get many projects',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Get Latest Commit',
|
|
70
|
+
value: 'getLatestCommit',
|
|
71
|
+
description: 'Get the latest commit for a project',
|
|
72
|
+
action: 'Get latest commit',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Get Commit History',
|
|
76
|
+
value: 'getCommitHistory',
|
|
77
|
+
description: 'Get commit history for a project',
|
|
78
|
+
action: 'Get commit history',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'Update Parameters',
|
|
82
|
+
value: 'updateParameters',
|
|
83
|
+
description: 'Update project parameters',
|
|
84
|
+
action: 'Update project parameters',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
default: 'get',
|
|
88
|
+
},
|
|
89
|
+
// Workspace operations
|
|
90
|
+
{
|
|
91
|
+
displayName: 'Operation',
|
|
92
|
+
name: 'operation',
|
|
93
|
+
type: 'options',
|
|
94
|
+
noDataExpression: true,
|
|
95
|
+
displayOptions: {
|
|
96
|
+
show: {
|
|
97
|
+
resource: ['workspace'],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
options: [
|
|
101
|
+
{
|
|
102
|
+
name: 'Get All',
|
|
103
|
+
value: 'getAll',
|
|
104
|
+
description: 'Get all workspaces',
|
|
105
|
+
action: 'Get all workspaces',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
default: 'getAll',
|
|
109
|
+
},
|
|
110
|
+
// Project ID field (used by multiple operations)
|
|
111
|
+
{
|
|
112
|
+
displayName: 'Project ID',
|
|
113
|
+
name: 'projectId',
|
|
114
|
+
type: 'string',
|
|
115
|
+
required: true,
|
|
116
|
+
displayOptions: {
|
|
117
|
+
show: {
|
|
118
|
+
resource: ['project'],
|
|
119
|
+
operation: ['get', 'getLatestCommit', 'getCommitHistory', 'updateParameters'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
default: '',
|
|
123
|
+
description: 'The ID of the project',
|
|
124
|
+
},
|
|
125
|
+
// Limit field for getMany
|
|
126
|
+
{
|
|
127
|
+
displayName: 'Limit',
|
|
128
|
+
name: 'limit',
|
|
129
|
+
type: 'number',
|
|
130
|
+
displayOptions: {
|
|
131
|
+
show: {
|
|
132
|
+
resource: ['project'],
|
|
133
|
+
operation: ['getMany', 'getCommitHistory'],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
typeOptions: {
|
|
137
|
+
minValue: 1,
|
|
138
|
+
},
|
|
139
|
+
default: 50,
|
|
140
|
+
description: 'Max number of results to return',
|
|
141
|
+
},
|
|
142
|
+
// Return all toggle for getMany
|
|
143
|
+
{
|
|
144
|
+
displayName: 'Return All',
|
|
145
|
+
name: 'returnAll',
|
|
146
|
+
type: 'boolean',
|
|
147
|
+
displayOptions: {
|
|
148
|
+
show: {
|
|
149
|
+
resource: ['project'],
|
|
150
|
+
operation: ['getMany', 'getCommitHistory'],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
default: false,
|
|
154
|
+
description: 'Whether to return all results or only up to a given limit',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
async execute() {
|
|
159
|
+
const items = this.getInputData();
|
|
160
|
+
const returnData = [];
|
|
161
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
162
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
163
|
+
// Get credentials
|
|
164
|
+
const credentials = await this.getCredentials('altium365NexarApi');
|
|
165
|
+
const client = new NexarClient_1.NexarClient(credentials.clientId, credentials.clientSecret);
|
|
166
|
+
for (let i = 0; i < items.length; i++) {
|
|
167
|
+
try {
|
|
168
|
+
if (resource === 'workspace') {
|
|
169
|
+
if (operation === 'getAll') {
|
|
170
|
+
const sdk = await client.getSdk();
|
|
171
|
+
const result = await sdk.GetWorkspaceInfos();
|
|
172
|
+
if (!result.desWorkspaceInfos) {
|
|
173
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No workspaces found');
|
|
174
|
+
}
|
|
175
|
+
result.desWorkspaceInfos.forEach((workspace) => {
|
|
176
|
+
returnData.push({
|
|
177
|
+
json: workspace,
|
|
178
|
+
pairedItem: { item: i },
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (resource === 'project') {
|
|
184
|
+
const sdk = await client.getSdk();
|
|
185
|
+
if (operation === 'get') {
|
|
186
|
+
const projectId = this.getNodeParameter('projectId', i);
|
|
187
|
+
const result = await sdk.GetProjectById({ id: projectId });
|
|
188
|
+
if (!result.desProjectById) {
|
|
189
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Project with ID ${projectId} not found`);
|
|
190
|
+
}
|
|
191
|
+
returnData.push({
|
|
192
|
+
json: result.desProjectById,
|
|
193
|
+
pairedItem: { item: i },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (operation === 'getMany') {
|
|
197
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
198
|
+
const limit = this.getNodeParameter('limit', i, 50);
|
|
199
|
+
const workspaceUrl = credentials.workspaceUrl;
|
|
200
|
+
const result = await sdk.GetProjects({
|
|
201
|
+
workspaceUrl,
|
|
202
|
+
first: returnAll ? undefined : limit,
|
|
203
|
+
});
|
|
204
|
+
if (!result.desProjects?.nodes) {
|
|
205
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No projects found');
|
|
206
|
+
}
|
|
207
|
+
result.desProjects.nodes.forEach((project) => {
|
|
208
|
+
returnData.push({
|
|
209
|
+
json: project,
|
|
210
|
+
pairedItem: { item: i },
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (operation === 'getLatestCommit') {
|
|
215
|
+
const projectId = this.getNodeParameter('projectId', i);
|
|
216
|
+
const result = await sdk.GetLatestCommit({ projectId });
|
|
217
|
+
if (!result.desProjectById?.latestRevision) {
|
|
218
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No commits found for project ${projectId}`);
|
|
219
|
+
}
|
|
220
|
+
returnData.push({
|
|
221
|
+
json: {
|
|
222
|
+
projectId: result.desProjectById.id,
|
|
223
|
+
projectName: result.desProjectById.name,
|
|
224
|
+
...result.desProjectById.latestRevision,
|
|
225
|
+
},
|
|
226
|
+
pairedItem: { item: i },
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (operation === 'getCommitHistory') {
|
|
230
|
+
const projectId = this.getNodeParameter('projectId', i);
|
|
231
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
232
|
+
const limit = this.getNodeParameter('limit', i, 50);
|
|
233
|
+
const result = await sdk.GetCommitHistory({
|
|
234
|
+
projectId,
|
|
235
|
+
first: returnAll ? undefined : limit,
|
|
236
|
+
});
|
|
237
|
+
if (!result.desProjectById?.revisions?.nodes) {
|
|
238
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No commit history found for project ${projectId}`);
|
|
239
|
+
}
|
|
240
|
+
result.desProjectById.revisions.nodes.forEach((commit) => {
|
|
241
|
+
returnData.push({
|
|
242
|
+
json: {
|
|
243
|
+
projectId: result.desProjectById.id,
|
|
244
|
+
projectName: result.desProjectById.name,
|
|
245
|
+
...commit,
|
|
246
|
+
},
|
|
247
|
+
pairedItem: { item: i },
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
if (operation === 'updateParameters') {
|
|
252
|
+
// TODO: Add parameter input fields and implement mutation
|
|
253
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Update Parameters operation not yet implemented');
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
if (this.continueOnFail()) {
|
|
259
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
260
|
+
returnData.push({
|
|
261
|
+
json: {
|
|
262
|
+
error: errorMessage,
|
|
263
|
+
},
|
|
264
|
+
pairedItem: { item: i },
|
|
265
|
+
});
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return [returnData];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
exports.Altium365 = Altium365;
|
|
275
|
+
//# sourceMappingURL=Altium365.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Altium365.node.js","sourceRoot":"","sources":["../../../nodes/Altium365/Altium365.node.ts"],"names":[],"mappings":"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"}
|