n8n-nodes-shipstatic 0.3.3 → 0.4.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 CHANGED
@@ -1,8 +1,6 @@
1
1
  # n8n-nodes-shipstatic
2
2
 
3
- n8n community node for [ShipStatic](https://shipstatic.com) — free, no account needed. Deploy static websites, landing pages, and prototypes instantly from n8n workflows.
4
-
5
- ShipStatic is static hosting without the complexity. No build steps, no framework lock-in — upload your files and get a live URL.
3
+ n8n community node for [ShipStatic](https://shipstatic.com) — deploy static websites, landing pages, and prototypes instantly from n8n workflows.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,62 +20,56 @@ npm install n8n-nodes-shipstatic
22
20
 
23
21
  Restart n8n after installing.
24
22
 
25
- ## Getting Started
23
+ ## Deploy — Free, No Account Needed
24
+
25
+ Add a **ShipStatic** node to your workflow. No credentials to configure.
26
+
27
+ 1. Set Resource to **Deployment**, Operation to **Upload**
28
+ 2. Connect binary files from an upstream node (e.g. Read Binary Files, HTTP Request)
29
+ 3. Run — you get a live, shareable URL on `*.shipstatic.com`
26
30
 
27
- 1. Add a **ShipStatic** node to your workflow
28
- 2. Set Resource to **Deployment**, Operation to **Upload**
29
- 3. Enter the path to the folder with your website files
30
- 4. Run — your site is live instantly
31
+ That's it. Your site is live instantly. No sign-up, no API key, no configuration.
31
32
 
32
- No credentials required for deploy. Deployments without an API key are public and expire in 3 days.
33
+ Deployments without an API key are public and expire in 3 days.
33
34
 
34
- ### API Key (optional)
35
+ ## All Operations — Free API Key
35
36
 
36
- For permanent deployments and access to all operations:
37
+ For permanent deployments and full control over your sites and domains, add a free API key:
37
38
 
38
39
  1. Get a free key at [my.shipstatic.com/api-key](https://my.shipstatic.com/api-key)
39
40
  2. In n8n, go to **Credentials > New Credential > ShipStatic API**
40
41
  3. Paste your API key and save — n8n verifies the connection automatically
41
42
 
42
- ## Operations
43
-
44
43
  ### Deployments
45
44
 
46
- | Operation | Description |
47
- |-----------|-------------|
48
- | **Upload** | Publish files and get a live URL instantly — no account needed |
49
- | **Get Many** | List all your deployed sites with their URLs, status, and labels |
50
- | **Get** | Get details for a specific deployment including URL, status, and file count |
51
- | **Update** | Update the labels on a deployment for organization and filtering |
52
- | **Delete** | Permanently remove a deployment and all its files |
45
+ | Operation | Description |
46
+ | ------------ | --------------------------------------------------------------------------- |
47
+ | **Upload** | Publish files and get a live URL instantly |
48
+ | **Get Many** | List all your deployed sites with their URLs, status, and labels |
49
+ | **Get** | Get details for a specific deployment including URL, status, and file count |
50
+ | **Update** | Update the labels on a deployment for organization and filtering |
51
+ | **Delete** | Permanently remove a deployment and all its files |
53
52
 
54
53
  ### Domains
55
54
 
56
- | Operation | Description |
57
- |-----------|-------------|
58
- | **Create or Update** | Connect a custom domain to your site, switch deployments, or update labels |
59
- | **Get Many** | List all your custom domains with their linked sites and verification status |
60
- | **Get** | Get details for a specific domain including its linked site and DNS status |
61
- | **Get DNS Records** | Get the DNS records you need to configure at your DNS provider |
62
- | **Validate** | Check if a domain name is valid and available before connecting it |
63
- | **Verify DNS** | Check if DNS is configured correctly after you set up the records |
64
- | **Delete** | Permanently disconnect and remove a custom domain |
55
+ | Operation | Description |
56
+ | -------------------- | ---------------------------------------------------------------------------- |
57
+ | **Create or Update** | Connect a custom domain to your site, switch deployments, or update labels |
58
+ | **Get Many** | List all your custom domains with their linked sites and verification status |
59
+ | **Get** | Get details for a specific domain including its linked site and DNS status |
60
+ | **Get DNS Records** | Get the DNS records you need to configure at your DNS provider |
61
+ | **Validate** | Check if a domain name is valid and available before connecting it |
62
+ | **Verify DNS** | Check if DNS is configured correctly after you set up the records |
63
+ | **Delete** | Permanently disconnect and remove a custom domain |
65
64
 
66
65
  ### Account
67
66
 
68
- | Operation | Description |
69
- |-----------|-------------|
70
- | **Get** | Get your account details including email, plan, and usage |
67
+ | Operation | Description |
68
+ | --------- | --------------------------------------------------------- |
69
+ | **Get** | Get your account details including email, plan, and usage |
71
70
 
72
71
  ## Example Workflows
73
72
 
74
- ### Publish a site (no account needed)
75
-
76
- 1. Add a **ShipStatic** node — no credential setup required
77
- 2. Set Resource to **Deployment**, Operation to **Upload**
78
- 3. Enter the path to the folder with your website files
79
- 4. Run — you get a live URL on `*.shipstatic.com`
80
-
81
73
  ### Publish and connect a custom domain
82
74
 
83
75
  1. **ShipStatic** > Upload deployment (get the deployment ID)
@@ -102,7 +94,7 @@ This node works as a tool in n8n's AI Agent workflows (`usableAsTool: true`). Co
102
94
 
103
95
  - [ShipStatic Documentation](https://docs.shipstatic.com)
104
96
  - [ShipStatic Dashboard](https://my.shipstatic.com)
105
- - [Report an Issue](https://github.com/shipstatic/node/issues)
97
+ - [Report an Issue](https://github.com/shipstatic/n8n/issues)
106
98
 
107
99
  ## License
108
100
 
@@ -1 +1 @@
1
- {"version":3,"file":"ShipstaticApi.credentials.js","sourceRoot":"","sources":["../../credentials/ShipstaticApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,aAAa;IAA1B;QACC,SAAI,GAAG,eAAe,CAAC;QACvB,gBAAW,GAAG,gBAAgB,CAAC;QAC/B,SAAI,GAAG,qBAA8B,CAAC;QACtC,qBAAgB,GAAG,6BAA6B,CAAC;QACjD,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,UAAU;gBACvB,WAAW,EAAE,oGAAoG;aACjH;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,sCAAsC;iBACrD;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,4BAA4B;gBACrC,GAAG,EAAE,UAAU;gBACf,MAAM,EAAE,KAAK;aACb;SACD,CAAC;IACH,CAAC;CAAA;AAjCD,sCAiCC"}
1
+ {"version":3,"file":"ShipstaticApi.credentials.js","sourceRoot":"","sources":["../../credentials/ShipstaticApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,aAAa;IAA1B;QACC,SAAI,GAAG,eAAe,CAAC;QACvB,gBAAW,GAAG,gBAAgB,CAAC;QAC/B,SAAI,GAAG,qBAA8B,CAAC;QACtC,qBAAgB,GAAG,6BAA6B,CAAC;QACjD,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,UAAU;gBACvB,WAAW,EACV,oGAAoG;aACrG;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,sCAAsC;iBACrD;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,4BAA4B;gBACrC,GAAG,EAAE,UAAU;gBACf,MAAM,EAAE,KAAK;aACb;SACD,CAAC;IACH,CAAC;CAAA;AAlCD,sCAkCC"}
@@ -1,23 +1,101 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.Shipstatic = void 0;
7
4
  exports.parseLabels = parseLabels;
8
5
  const n8n_workflow_1 = require("n8n-workflow");
9
- const ship_1 = __importDefault(require("@shipstatic/ship"));
10
- const promises_1 = require("fs/promises");
11
- const os_1 = require("os");
12
- const path_1 = require("path");
6
+ const node_crypto_1 = require("node:crypto");
7
+ const API = 'https://api.shipstatic.com';
8
+ function md5(buf) {
9
+ return (0, node_crypto_1.createHash)('md5').update(buf).digest('hex');
10
+ }
13
11
  function parseLabels(value) {
14
12
  if (!value)
15
13
  return undefined;
16
- return value.split(',').map((l) => l.trim()).filter(Boolean);
14
+ return value
15
+ .split(',')
16
+ .map((l) => l.trim())
17
+ .filter(Boolean);
17
18
  }
18
19
  function toJson(data) {
19
20
  return data;
20
21
  }
22
+ async function handleUpload(ctx, items, apiKey) {
23
+ const binaryPropertyName = ctx.getNodeParameter('binaryPropertyName', 0);
24
+ const options = ctx.getNodeParameter('options', 0);
25
+ const files = [];
26
+ for (let i = 0; i < items.length; i++) {
27
+ const binaryData = ctx.helpers.assertBinaryData(i, binaryPropertyName);
28
+ const buffer = await ctx.helpers.getBinaryDataBuffer(i, binaryPropertyName);
29
+ if (buffer.length === 0)
30
+ continue;
31
+ const dir = (binaryData.directory || '').replace(/^\/+/, '');
32
+ const fileName = binaryData.fileName || `file_${i}`;
33
+ files.push({
34
+ path: dir ? `${dir}/${fileName}` : fileName,
35
+ content: buffer,
36
+ md5: md5(buffer),
37
+ });
38
+ }
39
+ if (files.length > 1) {
40
+ const segments = files.map((f) => f.path.replace(/\\/g, '/').split('/'));
41
+ const minLen = Math.min(...segments.map((s) => s.length));
42
+ let strip = 0;
43
+ for (let i = 0; i < minLen - 1; i++) {
44
+ if (segments.every((s) => s[i] === segments[0][i]))
45
+ strip++;
46
+ else
47
+ break;
48
+ }
49
+ if (strip > 0) {
50
+ for (const f of files) {
51
+ f.path = f.path.replace(/\\/g, '/').split('/').slice(strip).join('/');
52
+ }
53
+ }
54
+ }
55
+ const form = new FormData();
56
+ for (const f of files) {
57
+ form.append('files[]', new File([new Uint8Array(f.content)], f.path, { type: 'application/octet-stream' }));
58
+ }
59
+ form.append('checksums', JSON.stringify(files.map((f) => f.md5)));
60
+ form.append('via', 'n8n');
61
+ form.append('spa', 'true');
62
+ const labels = parseLabels(options.labels);
63
+ if (labels)
64
+ form.append('labels', JSON.stringify(labels));
65
+ let authorization;
66
+ if (apiKey) {
67
+ authorization = `Bearer ${apiKey}`;
68
+ }
69
+ else {
70
+ const { secret } = (await ctx.helpers.httpRequest({
71
+ method: 'POST',
72
+ url: `${API}/tokens/agent`,
73
+ body: {},
74
+ json: true,
75
+ }));
76
+ authorization = `Bearer ${secret}`;
77
+ }
78
+ const result = await ctx.helpers.httpRequest({
79
+ method: 'POST',
80
+ url: `${API}/deployments`,
81
+ body: form,
82
+ headers: { Authorization: authorization },
83
+ });
84
+ return [
85
+ {
86
+ json: toJson(result),
87
+ pairedItem: items.map((_, i) => ({ item: i })),
88
+ },
89
+ ];
90
+ }
91
+ async function apiRequest(ctx, method, path, body) {
92
+ return ctx.helpers.httpRequestWithAuthentication.call(ctx, 'shipstaticApi', {
93
+ method,
94
+ url: `${API}${path}`,
95
+ body,
96
+ json: true,
97
+ });
98
+ }
21
99
  class Shipstatic {
22
100
  constructor() {
23
101
  this.description = {
@@ -60,11 +138,36 @@ class Shipstatic {
60
138
  noDataExpression: true,
61
139
  displayOptions: { show: { resource: ['deployment'] } },
62
140
  options: [
63
- { name: 'Upload', value: 'upload', description: 'Publish files and get a live URL instantly — no account needed', action: 'Upload a deployment' },
64
- { name: 'Get Many', value: 'getMany', description: 'List all your deployed sites with their URLs, status, and labels', action: 'List all deployments' },
65
- { name: 'Get', value: 'get', description: 'Get details for a specific deployment including URL, status, and file count', action: 'Get a deployment' },
66
- { name: 'Update', value: 'update', description: 'Update the labels on a deployment for organization and filtering', action: 'Update a deployment' },
67
- { name: 'Delete', value: 'delete', description: 'Permanently remove a deployment and all its files', action: 'Delete a deployment' },
141
+ {
142
+ name: 'Delete',
143
+ value: 'delete',
144
+ description: 'Permanently remove a deployment and all its files',
145
+ action: 'Delete a deployment',
146
+ },
147
+ {
148
+ name: 'Get',
149
+ value: 'get',
150
+ description: 'Get details for a specific deployment including URL, status, and file count',
151
+ action: 'Get a deployment',
152
+ },
153
+ {
154
+ name: 'Get Many',
155
+ value: 'getMany',
156
+ description: 'List all your deployed sites with their URLs, status, and labels',
157
+ action: 'List all deployments',
158
+ },
159
+ {
160
+ name: 'Update',
161
+ value: 'update',
162
+ description: 'Update the labels on a deployment for organization and filtering',
163
+ action: 'Update a deployment',
164
+ },
165
+ {
166
+ name: 'Upload',
167
+ value: 'upload',
168
+ description: 'Publish files and get a live URL instantly — no account needed',
169
+ action: 'Upload a deployment',
170
+ },
68
171
  ],
69
172
  default: 'upload',
70
173
  },
@@ -75,13 +178,48 @@ class Shipstatic {
75
178
  noDataExpression: true,
76
179
  displayOptions: { show: { resource: ['domain'] } },
77
180
  options: [
78
- { name: 'Create or Update', value: 'set', description: 'Connect a custom domain to your site, switch deployments, or update labels', action: 'Create or update a domain' },
79
- { name: 'Get Many', value: 'getMany', description: 'List all your custom domains with their linked sites and verification status', action: 'List all domains' },
80
- { name: 'Get', value: 'get', description: 'Get details for a specific domain including its linked site and DNS status', action: 'Get a domain' },
81
- { name: 'Get DNS Records', value: 'records', description: 'Get the DNS records you need to configure at your DNS provider', action: 'Get DNS records' },
82
- { name: 'Validate', value: 'validate', description: 'Check if a domain name is valid and available before connecting it', action: 'Validate a domain' },
83
- { name: 'Verify DNS', value: 'verify', description: 'Check if DNS is configured correctly after you set up the records', action: 'Verify DNS' },
84
- { name: 'Delete', value: 'delete', description: 'Permanently disconnect and remove a custom domain', action: 'Delete a domain' },
181
+ {
182
+ name: 'Create or Update',
183
+ value: 'set',
184
+ description: 'Connect a custom domain to your site, switch deployments, or update labels',
185
+ action: 'Create or update a domain',
186
+ },
187
+ {
188
+ name: 'Delete',
189
+ value: 'delete',
190
+ description: 'Permanently disconnect and remove a custom domain',
191
+ action: 'Delete a domain',
192
+ },
193
+ {
194
+ name: 'Get',
195
+ value: 'get',
196
+ description: 'Get details for a specific domain including its linked site and DNS status',
197
+ action: 'Get a domain',
198
+ },
199
+ {
200
+ name: 'Get DNS Records',
201
+ value: 'records',
202
+ description: 'Get the DNS records you need to configure at your DNS provider',
203
+ action: 'Get DNS records',
204
+ },
205
+ {
206
+ name: 'Get Many',
207
+ value: 'getMany',
208
+ description: 'List all your custom domains with their linked sites and verification status',
209
+ action: 'List all domains',
210
+ },
211
+ {
212
+ name: 'Validate',
213
+ value: 'validate',
214
+ description: 'Check if a domain name is valid and available before connecting it',
215
+ action: 'Validate a domain',
216
+ },
217
+ {
218
+ name: 'Verify DNS',
219
+ value: 'verify',
220
+ description: 'Check if DNS is configured correctly after you set up the records',
221
+ action: 'Verify DNS',
222
+ },
85
223
  ],
86
224
  default: 'set',
87
225
  },
@@ -92,7 +230,12 @@ class Shipstatic {
92
230
  noDataExpression: true,
93
231
  displayOptions: { show: { resource: ['account'] } },
94
232
  options: [
95
- { name: 'Get', value: 'get', description: 'Get your account details including email, plan, and usage', action: 'Get account info' },
233
+ {
234
+ name: 'Get',
235
+ value: 'get',
236
+ description: 'Get your account details including email, plan, and usage',
237
+ action: 'Get account info',
238
+ },
96
239
  ],
97
240
  default: 'get',
98
241
  },
@@ -105,14 +248,16 @@ class Shipstatic {
105
248
  hint: 'The name of the input binary field containing the file data',
106
249
  },
107
250
  {
108
- displayName: 'Deployment',
251
+ displayName: 'Deployment Name or ID',
109
252
  name: 'deploymentId',
110
253
  type: 'options',
111
254
  typeOptions: { loadOptionsMethod: 'getDeployments' },
112
255
  default: '',
113
256
  required: true,
114
- displayOptions: { show: { resource: ['deployment'], operation: ['get', 'update', 'delete'] } },
115
- description: 'Deployment hostname (e.g. "happy-cat-abc1234.shipstatic.com")',
257
+ displayOptions: {
258
+ show: { resource: ['deployment'], operation: ['get', 'update', 'delete'] },
259
+ },
260
+ description: 'Deployment hostname (e.g. "happy-cat-abc1234.shipstatic.com"). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
116
261
  },
117
262
  {
118
263
  displayName: 'Labels',
@@ -124,14 +269,16 @@ class Shipstatic {
124
269
  description: 'Comma-separated labels',
125
270
  },
126
271
  {
127
- displayName: 'Domain Name',
272
+ displayName: 'Domain Name or ID',
128
273
  name: 'domainName',
129
274
  type: 'options',
130
275
  typeOptions: { loadOptionsMethod: 'getDomains' },
131
276
  default: '',
132
277
  required: true,
133
- displayOptions: { show: { resource: ['domain'], operation: ['get', 'records', 'verify', 'delete'] } },
134
- description: 'Domain name (e.g. "www.example.com")',
278
+ displayOptions: {
279
+ show: { resource: ['domain'], operation: ['get', 'records', 'verify', 'delete'] },
280
+ },
281
+ description: 'Domain name (e.g. "www.example.com"). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
135
282
  },
136
283
  {
137
284
  displayName: 'Domain Name',
@@ -187,12 +334,12 @@ class Shipstatic {
187
334
  displayOptions: { show: { resource: ['domain'], operation: ['set'] } },
188
335
  options: [
189
336
  {
190
- displayName: 'Deployment',
337
+ displayName: 'Deployment Name or ID',
191
338
  name: 'deployment',
192
339
  type: 'options',
193
340
  typeOptions: { loadOptionsMethod: 'getDeployments' },
194
341
  default: '',
195
- description: 'Deployment to link to this domain',
342
+ description: 'Deployment to link to this domain. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
196
343
  },
197
344
  {
198
345
  displayName: 'Labels',
@@ -213,7 +360,7 @@ class Shipstatic {
213
360
  try {
214
361
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'shipstaticApi', {
215
362
  method: 'GET',
216
- url: 'https://api.shipstatic.com/deployments',
363
+ url: `${API}/deployments`,
217
364
  json: true,
218
365
  });
219
366
  return ((_a = response.deployments) !== null && _a !== void 0 ? _a : []).map((d) => ({
@@ -230,7 +377,7 @@ class Shipstatic {
230
377
  try {
231
378
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'shipstaticApi', {
232
379
  method: 'GET',
233
- url: 'https://api.shipstatic.com/domains',
380
+ url: `${API}/domains`,
234
381
  json: true,
235
382
  });
236
383
  return ((_a = response.domains) !== null && _a !== void 0 ? _a : []).map((d) => ({
@@ -246,39 +393,22 @@ class Shipstatic {
246
393
  };
247
394
  }
248
395
  async execute() {
249
- var _a;
396
+ var _a, _b, _c;
250
397
  const resource = this.getNodeParameter('resource', 0);
251
398
  const operation = this.getNodeParameter('operation', 0);
252
- const ship = await this.getCredentials('shipstaticApi')
253
- .then((c) => new ship_1.default({ apiKey: c.apiKey }))
254
- .catch(() => {
255
- if (resource === 'deployment' && operation === 'upload')
256
- return new ship_1.default({});
257
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'This operation requires a ShipStatic API key. Add a ShipStatic credential to use it.');
258
- });
259
399
  const items = this.getInputData();
260
400
  const returnData = [];
261
401
  if (resource === 'deployment' && operation === 'upload') {
262
- const binaryPropertyName = this.getNodeParameter('binaryPropertyName', 0);
263
- const options = this.getNodeParameter('options', 0);
264
- const tempDir = await (0, promises_1.mkdtemp)((0, path_1.join)((0, os_1.tmpdir)(), 'n8n-shipstatic-'));
402
+ let apiKey;
265
403
  try {
266
- for (let i = 0; i < items.length; i++) {
267
- const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
268
- const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
269
- const dir = (binaryData.directory || '').replace(/^\/+/, '');
270
- const fullPath = (0, path_1.join)(tempDir, dir, binaryData.fileName || `file_${i}`);
271
- await (0, promises_1.mkdir)((0, path_1.dirname)(fullPath), { recursive: true });
272
- await (0, promises_1.writeFile)(fullPath, buffer);
273
- }
274
- const result = await ship.deployments.upload(tempDir, {
275
- labels: parseLabels(options.labels),
276
- via: 'n8n',
277
- });
278
- returnData.push({
279
- json: toJson(result),
280
- pairedItem: items.map((_, i) => ({ item: i })),
281
- });
404
+ const credentials = await this.getCredentials('shipstaticApi');
405
+ apiKey = credentials.apiKey;
406
+ }
407
+ catch {
408
+ }
409
+ try {
410
+ const results = await handleUpload(this, items, apiKey);
411
+ returnData.push(...results);
282
412
  }
283
413
  catch (error) {
284
414
  if (this.continueOnFail()) {
@@ -289,18 +419,21 @@ class Shipstatic {
289
419
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), error);
290
420
  }
291
421
  }
292
- finally {
293
- await (0, promises_1.rm)(tempDir, { recursive: true, force: true });
294
- }
295
422
  return [returnData];
296
423
  }
424
+ try {
425
+ await this.getCredentials('shipstaticApi');
426
+ }
427
+ catch {
428
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'This operation requires a ShipStatic API key. Add a ShipStatic credential to use it.');
429
+ }
297
430
  for (let i = 0; i < items.length; i++) {
298
431
  try {
299
432
  if (resource === 'deployment') {
300
433
  if (operation === 'getMany') {
301
434
  const returnAll = this.getNodeParameter('returnAll', i);
302
- const response = await ship.deployments.list();
303
- let results = response.deployments;
435
+ const response = await apiRequest(this, 'GET', '/deployments');
436
+ let results = ((_a = response.deployments) !== null && _a !== void 0 ? _a : []);
304
437
  if (!returnAll) {
305
438
  const limit = this.getNodeParameter('limit', i);
306
439
  results = results.slice(0, limit);
@@ -311,35 +444,35 @@ class Shipstatic {
311
444
  }
312
445
  else if (operation === 'get') {
313
446
  const id = this.getNodeParameter('deploymentId', i);
314
- const result = await ship.deployments.get(id);
447
+ const result = await apiRequest(this, 'GET', `/deployments/${encodeURIComponent(id)}`);
315
448
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
316
449
  }
317
450
  else if (operation === 'update') {
318
451
  const id = this.getNodeParameter('deploymentId', i);
319
- const labels = (_a = parseLabels(this.getNodeParameter('labels', i))) !== null && _a !== void 0 ? _a : [];
320
- const result = await ship.deployments.set(id, { labels });
452
+ const labelValues = (_b = parseLabels(this.getNodeParameter('labels', i))) !== null && _b !== void 0 ? _b : [];
453
+ const result = await apiRequest(this, 'PATCH', `/deployments/${encodeURIComponent(id)}`, { labels: labelValues });
321
454
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
322
455
  }
323
456
  else if (operation === 'delete') {
324
457
  const id = this.getNodeParameter('deploymentId', i);
325
- await ship.deployments.remove(id);
458
+ await apiRequest(this, 'DELETE', `/deployments/${encodeURIComponent(id)}`);
326
459
  returnData.push({ json: { success: true }, pairedItem: { item: i } });
327
460
  }
328
461
  }
329
462
  else if (resource === 'domain') {
330
463
  if (operation === 'set') {
331
464
  const name = this.getNodeParameter('domainName', i);
332
- const options = this.getNodeParameter('options', i);
333
- const result = await ship.domains.set(name, {
334
- deployment: options.deployment || undefined,
335
- labels: parseLabels(options.labels),
465
+ const domainOptions = this.getNodeParameter('options', i);
466
+ const result = await apiRequest(this, 'PUT', `/domains/${encodeURIComponent(name)}`, {
467
+ deployment: domainOptions.deployment || undefined,
468
+ labels: parseLabels(domainOptions.labels),
336
469
  });
337
470
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
338
471
  }
339
472
  else if (operation === 'getMany') {
340
473
  const returnAll = this.getNodeParameter('returnAll', i);
341
- const response = await ship.domains.list();
342
- let results = response.domains;
474
+ const response = await apiRequest(this, 'GET', '/domains');
475
+ let results = ((_c = response.domains) !== null && _c !== void 0 ? _c : []);
343
476
  if (!returnAll) {
344
477
  const limit = this.getNodeParameter('limit', i);
345
478
  results = results.slice(0, limit);
@@ -350,32 +483,34 @@ class Shipstatic {
350
483
  }
351
484
  else if (operation === 'get') {
352
485
  const name = this.getNodeParameter('domainName', i);
353
- const result = await ship.domains.get(name);
486
+ const result = await apiRequest(this, 'GET', `/domains/${encodeURIComponent(name)}`);
354
487
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
355
488
  }
356
489
  else if (operation === 'records') {
357
490
  const name = this.getNodeParameter('domainName', i);
358
- const result = await ship.domains.records(name);
491
+ const result = await apiRequest(this, 'GET', `/domains/${encodeURIComponent(name)}/records`);
359
492
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
360
493
  }
361
494
  else if (operation === 'validate') {
362
495
  const name = this.getNodeParameter('domainName', i);
363
- const result = await ship.domains.validate(name);
496
+ const result = await apiRequest(this, 'POST', '/domains/validate', {
497
+ domain: name,
498
+ });
364
499
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
365
500
  }
366
501
  else if (operation === 'verify') {
367
502
  const name = this.getNodeParameter('domainName', i);
368
- const result = await ship.domains.verify(name);
503
+ const result = await apiRequest(this, 'POST', `/domains/${encodeURIComponent(name)}/verify`);
369
504
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
370
505
  }
371
506
  else if (operation === 'delete') {
372
507
  const name = this.getNodeParameter('domainName', i);
373
- await ship.domains.remove(name);
508
+ await apiRequest(this, 'DELETE', `/domains/${encodeURIComponent(name)}`);
374
509
  returnData.push({ json: { success: true }, pairedItem: { item: i } });
375
510
  }
376
511
  }
377
512
  else if (resource === 'account') {
378
- const result = await ship.whoami();
513
+ const result = await apiRequest(this, 'GET', '/account');
379
514
  returnData.push({ json: toJson(result), pairedItem: { item: i } });
380
515
  }
381
516
  }