n8n-nodes-janction-render 0.0.0-stage → 0.1.1

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,3 +1,27 @@
1
- # Temporary Holding Version
1
+ # n8n-nodes-janction-render
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An [n8n](https://n8n.io) community node for [JANCTION Render](https://render.janction.jp): render Blender scenes and 3D models (GLB, glTF, FBX, USD, OBJ, STL, .blend, or a bpy script) on cloud GPUs. Turn a product model into studio shots or a 360-degree turntable MP4 inside a workflow, with no local Blender or GPU.
4
+
5
+ ## Install
6
+
7
+ In n8n: **Settings > Community Nodes > Install**, then enter `n8n-nodes-janction-render`.
8
+
9
+ ## Credentials
10
+
11
+ Create a key at https://render.janction.jp/start (a new key comes with free GPU time) and paste it into **JANCTION Render API** (`jr_...`, sent as `X-API-Key`).
12
+
13
+ ## Operations
14
+
15
+ - **Render**: start a preview (up to 4 frames tiled in one image, seconds) or a final render. The scene is a file URL, a bpy script or a `scene_id` from an earlier job. Presets: `product` (4 studio shots), `turntable` (one full turn as MP4), `animation`. Returns `job_id`.
16
+ - **Estimate**: GPU seconds, wall time, queue wait and the cost in JPY before rendering.
17
+ - **Get Job**: status, ETA and, when done, the image or MP4 links (no key needed, about 24 hours).
18
+
19
+ A typical workflow: trigger (new product in your shop) > **Render** (File URL = the GLB, Preset = Product Shots, Kind = Final) > **Wait** 60 s > **Get Job** > loop until `status` is `done` > send the links.
20
+
21
+ ## Pricing
22
+
23
+ Free GPU time for a new key, then 0.1 JPY per GPU-second from prepaid credit. Current numbers: https://render.janction.jp/pricing
24
+
25
+ ## License
26
+
27
+ MIT. Operated by JasmyLab Inc. (Tokyo, Japan).
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JanctionRenderApi = void 0;
4
+ class JanctionRenderApi {
5
+ constructor() {
6
+ this.name = 'janctionRenderApi';
7
+ this.displayName = 'JANCTION Render API';
8
+ this.documentationUrl = 'https://github.com/JasmyLab-JANCTION/janction-render/tree/main/integrations/n8n';
9
+ this.properties = [
10
+ {
11
+ displayName: 'API Key',
12
+ name: 'apiKey',
13
+ type: 'string',
14
+ typeOptions: { password: true },
15
+ default: '',
16
+ description: 'A key that starts with jr_. Create one at https://render.janction.jp/start (free GPU time to start).',
17
+ },
18
+ ];
19
+ this.authenticate = {
20
+ type: 'generic',
21
+ properties: { headers: { 'X-API-Key': '={{$credentials.apiKey}}' } },
22
+ };
23
+ this.test = {
24
+ request: { baseURL: 'https://render.janction.jp', url: '/v1/me?src=n8n' },
25
+ };
26
+ }
27
+ }
28
+ exports.JanctionRenderApi = JanctionRenderApi;
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JanctionRender = void 0;
4
+ // The scene to render: one of a link (.blend, .py, GLB/glTF, FBX, USD, OBJ, STL) or bpy code. Shared by Render and Estimate.
5
+ const sceneFields = [
6
+ {
7
+ displayName: 'Scene Source',
8
+ name: 'source',
9
+ type: 'options',
10
+ default: 'url',
11
+ options: [
12
+ { name: 'File URL', value: 'url', description: 'An https link to a .blend, .py or 3D file (GLB, glTF, FBX, USD, OBJ, STL)' },
13
+ { name: 'Bpy Script', value: 'script', description: 'Blender Python code that builds the scene' },
14
+ { name: 'Scene ID', value: 'id', description: 'A scene_id returned by an earlier job (kept 24 hours after last use)' },
15
+ ],
16
+ },
17
+ {
18
+ displayName: 'File URL',
19
+ name: 'sceneUrl',
20
+ type: 'string',
21
+ default: '',
22
+ placeholder: 'https://example.com/product.glb',
23
+ displayOptions: { show: { source: ['url'] } },
24
+ routing: { send: { type: 'body', property: 'scene_url' } },
25
+ },
26
+ {
27
+ displayName: 'Bpy Script',
28
+ name: 'sceneScript',
29
+ type: 'string',
30
+ typeOptions: { rows: 8 },
31
+ default: '',
32
+ displayOptions: { show: { source: ['script'] } },
33
+ routing: { send: { type: 'body', property: 'scene_script' } },
34
+ },
35
+ {
36
+ displayName: 'Scene ID',
37
+ name: 'sceneId',
38
+ type: 'string',
39
+ default: '',
40
+ placeholder: 'f_0123456789abcdef',
41
+ displayOptions: { show: { source: ['id'] } },
42
+ routing: { send: { type: 'body', property: 'scene_id' } },
43
+ },
44
+ {
45
+ displayName: 'Kind',
46
+ name: 'kind',
47
+ type: 'options',
48
+ default: 'preview',
49
+ options: [
50
+ { name: 'Preview', value: 'preview', description: 'Up to 4 frames tiled in one image, back in seconds' },
51
+ { name: 'Final', value: 'final', description: 'Full-size frames or a video' },
52
+ ],
53
+ routing: { send: { type: 'body', property: 'kind' } },
54
+ },
55
+ {
56
+ displayName: 'Preset',
57
+ name: 'preset',
58
+ type: 'options',
59
+ default: '',
60
+ options: [
61
+ { name: 'None', value: '' },
62
+ { name: 'Product Shots', value: 'product', description: '4 studio shots at 0/90/180/270 degrees on a plain backdrop' },
63
+ { name: 'Turntable', value: 'turntable', description: 'One full turn as an MP4 on a plain backdrop' },
64
+ { name: 'Animation', value: 'animation', description: "The scene's own camera, lights and frame range" },
65
+ ],
66
+ routing: { send: { type: 'body', property: 'preset', value: '={{ $value || undefined }}' } },
67
+ },
68
+ {
69
+ displayName: 'Additional Fields',
70
+ name: 'additionalFields',
71
+ type: 'collection',
72
+ placeholder: 'Add Field',
73
+ default: {},
74
+ options: [
75
+ { displayName: 'Frame Start', name: 'frame_start', type: 'number', default: 1, routing: { send: { type: 'body', property: 'frame_start' } } },
76
+ { displayName: 'Frame End', name: 'frame_end', type: 'number', default: 1, routing: { send: { type: 'body', property: 'frame_end' } } },
77
+ { displayName: 'Width', name: 'width', type: 'number', default: 1920, routing: { send: { type: 'body', property: 'width' } } },
78
+ { displayName: 'Height', name: 'height', type: 'number', default: 1080, routing: { send: { type: 'body', property: 'height' } } },
79
+ { displayName: 'Samples', name: 'samples', type: 'number', default: 128, routing: { send: { type: 'body', property: 'samples' } } },
80
+ {
81
+ displayName: 'Output',
82
+ name: 'output',
83
+ type: 'options',
84
+ default: 'auto',
85
+ options: ['auto', 'png', 'exr', 'mp4', 'webm', 'gif', 'webp'].map((v) => ({ name: v.toUpperCase(), value: v })),
86
+ routing: { send: { type: 'body', property: 'output' } },
87
+ },
88
+ {
89
+ displayName: 'Environment',
90
+ name: 'environment',
91
+ type: 'options',
92
+ default: 'studio',
93
+ options: ['studio', 'sunset', 'overcast', 'night'].map((v) => ({ name: v[0].toUpperCase() + v.slice(1), value: v })),
94
+ routing: { send: { type: 'body', property: 'environment' } },
95
+ },
96
+ { displayName: 'Transparent Background', name: 'transparent', type: 'boolean', default: false, routing: { send: { type: 'body', property: 'transparent' } } },
97
+ {
98
+ displayName: 'Max JPY',
99
+ name: 'max_yen',
100
+ type: 'number',
101
+ default: 0,
102
+ description: 'Refuse the job if it would cost more than this (0 = only when the free GPU time covers it)',
103
+ routing: { send: { type: 'body', property: 'max_yen' } },
104
+ },
105
+ ],
106
+ },
107
+ ];
108
+ class JanctionRender {
109
+ constructor() {
110
+ this.description = {
111
+ displayName: 'JANCTION Render',
112
+ name: 'janctionRender',
113
+ icon: 'file:janction.png',
114
+ group: ['transform'],
115
+ version: 1,
116
+ subtitle: '={{$parameter["operation"]}}',
117
+ description: 'Render Blender scenes and 3D models on cloud GPUs: product shots, turntables, animations and stills',
118
+ defaults: { name: 'JANCTION Render' },
119
+ inputs: ['main'],
120
+ outputs: ['main'],
121
+ credentials: [{ name: 'janctionRenderApi', required: true }],
122
+ requestDefaults: {
123
+ baseURL: 'https://render.janction.jp',
124
+ headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
125
+ qs: { src: 'n8n' },
126
+ },
127
+ properties: [
128
+ {
129
+ displayName: 'Operation',
130
+ name: 'operation',
131
+ type: 'options',
132
+ noDataExpression: true,
133
+ default: 'render',
134
+ options: [
135
+ {
136
+ name: 'Render',
137
+ value: 'render',
138
+ action: 'Start a render',
139
+ description: 'Start a preview or final render. Returns job_id; use Get Job (after a Wait node) for the links.',
140
+ routing: { request: { method: 'POST', url: '/v1/jobs' } },
141
+ },
142
+ {
143
+ name: 'Estimate',
144
+ value: 'estimate',
145
+ action: 'Estimate a render',
146
+ description: 'GPU seconds, wall time, queue wait and cost in JPY before rendering',
147
+ routing: { request: { method: 'POST', url: '/v1/estimate' } },
148
+ },
149
+ {
150
+ name: 'Get Job',
151
+ value: 'getJob',
152
+ action: 'Get a render job',
153
+ description: 'Status, ETA and, when done, the image or MP4 links (no key needed, about 24 hours)',
154
+ routing: { request: { method: 'GET', url: '=/v1/jobs/{{$parameter["jobId"]}}' } },
155
+ },
156
+ ],
157
+ },
158
+ ...sceneFields.map((f) => { var _a, _b; return ({ ...f, displayOptions: { show: { ...((_b = (_a = f.displayOptions) === null || _a === void 0 ? void 0 : _a.show) !== null && _b !== void 0 ? _b : {}), operation: ['render', 'estimate'] } } }); }),
159
+ {
160
+ displayName: 'Job ID',
161
+ name: 'jobId',
162
+ type: 'string',
163
+ default: '',
164
+ required: true,
165
+ placeholder: 'j_0123456789abcdef',
166
+ displayOptions: { show: { operation: ['getJob'] } },
167
+ },
168
+ ],
169
+ };
170
+ }
171
+ }
172
+ exports.JanctionRender = JanctionRender;
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "n8n-nodes-janction-render",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "n8n node for JANCTION Render: render Blender scenes and 3D models (GLB, FBX, USD, OBJ, STL) on cloud GPUs. Product shots, 360-degree turntables, animations and stills as PNG or MP4.",
5
+ "keywords": ["n8n-community-node-package", "blender", "3d", "rendering", "gpu", "glb", "product-photos", "turntable"],
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/JasmyLab-JANCTION/janction-render/tree/main/integrations/n8n",
8
+ "author": { "name": "JasmyLab Inc.", "email": "contact@jasmylab.com" },
9
+ "repository": { "type": "git", "url": "git+https://github.com/JasmyLab-JANCTION/janction-render.git", "directory": "integrations/n8n" },
10
+ "main": "index.js",
11
+ "scripts": {
12
+ "build": "tsc && node -e \"require('fs').cpSync('nodes/JanctionRender/janction.png','dist/nodes/JanctionRender/janction.png')\"",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "files": ["dist"],
16
+ "n8n": {
17
+ "n8nNodesApiVersion": 1,
18
+ "credentials": ["dist/credentials/JanctionRenderApi.credentials.js"],
19
+ "nodes": ["dist/nodes/JanctionRender/JanctionRender.node.js"]
20
+ },
21
+ "devDependencies": {
22
+ "n8n-workflow": "*",
23
+ "typescript": "^5.6.0"
24
+ },
25
+ "peerDependencies": {
26
+ "n8n-workflow": "*"
27
+ }
28
+ }