n8n-nodes-supermachine 0.8.0 → 0.10.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.
@@ -1183,6 +1183,154 @@ class Supermachine {
1183
1183
  });
1184
1184
  }
1185
1185
  }
1186
+ else if (operation === 'upscale') {
1187
+ const imageSource = this.getNodeParameter('imageSource', i);
1188
+ const upscaler = this.getNodeParameter('upscaler', i);
1189
+ const factor = this.getNodeParameter('factor', i);
1190
+ const additionalOptions = this.getNodeParameter('additionalOptions', i, {});
1191
+ let imageUrl = '';
1192
+ if (imageSource === 'imageId') {
1193
+ const imageId = this.getNodeParameter('imageId', i);
1194
+ const imageDetails = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
1195
+ method: 'GET',
1196
+ url: `https://dev.supermachine.art/v1/images/${imageId}`,
1197
+ json: true,
1198
+ });
1199
+ imageUrl = imageDetails.url;
1200
+ if (!imageUrl) {
1201
+ throw new Error(`Image ID ${imageId} does not have a valid URL`);
1202
+ }
1203
+ }
1204
+ else if (imageSource === 'imageUrl') {
1205
+ imageUrl = this.getNodeParameter('imageUrl', i);
1206
+ }
1207
+ const imageBuffer = await this.helpers.httpRequest({
1208
+ method: 'GET',
1209
+ url: imageUrl,
1210
+ encoding: 'arraybuffer',
1211
+ returnFullResponse: false,
1212
+ });
1213
+ const base64Image = Buffer.from(imageBuffer).toString('base64');
1214
+ let mimeType = 'image/jpeg';
1215
+ if (imageUrl.toLowerCase().includes('.png')) {
1216
+ mimeType = 'image/png';
1217
+ }
1218
+ else if (imageUrl.toLowerCase().includes('.webp')) {
1219
+ mimeType = 'image/webp';
1220
+ }
1221
+ const dataUri = `data:${mimeType};base64,${base64Image}`;
1222
+ const body = {
1223
+ image: dataUri,
1224
+ upscaler: upscaler,
1225
+ factor: factor,
1226
+ faceEnhance: additionalOptions.faceEnhance || false,
1227
+ };
1228
+ if (additionalOptions.folderId) {
1229
+ body.folderId = parseInt(additionalOptions.folderId, 10) || 0;
1230
+ }
1231
+ let upscaleResponse;
1232
+ try {
1233
+ upscaleResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
1234
+ method: 'POST',
1235
+ url: 'https://dev.supermachine.art/v1/tools/upscale',
1236
+ json: true,
1237
+ body,
1238
+ });
1239
+ }
1240
+ catch (error) {
1241
+ throw new Error(`Failed to upscale image: ${error.message}`);
1242
+ }
1243
+ const batchId = upscaleResponse.batchId;
1244
+ if (!batchId) {
1245
+ if (upscaleResponse.url || upscaleResponse.imageUrl) {
1246
+ returnData.push({
1247
+ json: {
1248
+ success: true,
1249
+ imageUrl: upscaleResponse.url || upscaleResponse.imageUrl,
1250
+ imageId: upscaleResponse.id || upscaleResponse.imageId,
1251
+ creditsCost: upscaleResponse.creditsCost,
1252
+ creditsRemaining: upscaleResponse.creditsRemaining,
1253
+ upscaler,
1254
+ factor,
1255
+ faceEnhance: body.faceEnhance,
1256
+ processedAt: new Date().toISOString(),
1257
+ ...upscaleResponse,
1258
+ }
1259
+ });
1260
+ continue;
1261
+ }
1262
+ throw new Error('No batchId or result returned from upscale API');
1263
+ }
1264
+ const skipPolling = additionalOptions.skipPolling;
1265
+ if (skipPolling) {
1266
+ returnData.push({
1267
+ json: {
1268
+ batchId,
1269
+ tool: upscaleResponse.tool || 'upscale',
1270
+ creditsCost: upscaleResponse.creditsCost,
1271
+ creditsRemaining: upscaleResponse.creditsRemaining,
1272
+ upscaler,
1273
+ factor,
1274
+ faceEnhance: body.faceEnhance,
1275
+ status: 'submitted',
1276
+ message: 'Image upscaling submitted. Use List Images with this batchId to check status.',
1277
+ submittedAt: new Date().toISOString(),
1278
+ ...upscaleResponse,
1279
+ }
1280
+ });
1281
+ continue;
1282
+ }
1283
+ const pollingInterval = additionalOptions.pollingInterval || 2;
1284
+ const maxPollingTime = additionalOptions.maxPollingTime || 120;
1285
+ const startTime = Date.now();
1286
+ let completedResult = null;
1287
+ await new Promise((resolve) => setTimeout(resolve, 2000));
1288
+ while (!completedResult) {
1289
+ if ((Date.now() - startTime) / 1000 > maxPollingTime) {
1290
+ throw new Error(`Image upscaling timed out after ${maxPollingTime} seconds. Batch ID: ${batchId}`);
1291
+ }
1292
+ let pollResponse;
1293
+ try {
1294
+ pollResponse = await this.helpers.requestWithAuthentication.call(this, 'supermachineApi', {
1295
+ method: 'GET',
1296
+ url: `https://dev.supermachine.art/v1/images?batchId=${batchId}`,
1297
+ json: true,
1298
+ });
1299
+ }
1300
+ catch (error) {
1301
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval * 1000));
1302
+ continue;
1303
+ }
1304
+ const pollItems = pollResponse.items;
1305
+ if (Array.isArray(pollItems) && pollItems.length > 0) {
1306
+ const firstItem = pollItems[0];
1307
+ const status = firstItem.status;
1308
+ if (status === 'completed') {
1309
+ completedResult = firstItem;
1310
+ break;
1311
+ }
1312
+ else if (status === 'failed') {
1313
+ throw new Error(`Image upscaling failed. Batch ID: ${batchId}. Error: ${firstItem.error || 'Unknown error'}`);
1314
+ }
1315
+ }
1316
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval * 1000));
1317
+ }
1318
+ returnData.push({
1319
+ json: {
1320
+ batchId,
1321
+ success: true,
1322
+ operation: 'upscale',
1323
+ tool: 'upscale',
1324
+ upscaler,
1325
+ factor,
1326
+ faceEnhance: body.faceEnhance,
1327
+ creditsCost: upscaleResponse.creditsCost,
1328
+ creditsRemaining: upscaleResponse.creditsRemaining,
1329
+ processedAt: new Date().toISOString(),
1330
+ ...completedResult,
1331
+ }
1332
+ });
1333
+ }
1186
1334
  else {
1187
1335
  throw new Error(`⚠️ Operation "${operation}" is coming soon.`);
1188
1336
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-supermachine",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "n8n community node for Supermachine AI Image API — Generate images, manage models, LoRAs, and characters",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -54,6 +54,7 @@
54
54
  "gulp": "^5.0.1",
55
55
  "gulp-sourcemaps": "^3.0.0",
56
56
  "gulp-typescript": "^6.0.0-alpha.1",
57
+ "merge-stream": "^2.0.0",
57
58
  "n8n-workflow": "*",
58
59
  "prettier": "^2.8.8",
59
60
  "typescript": "^5.3.3"