@twick/render-server 0.14.2 → 0.14.4
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 +32 -7
- package/dist/renderer.d.ts +18 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +18 -0
- package/dist/renderer.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +57 -3
- package/dist/server.js.map +1 -1
- package/package.json +8 -8
- package/package.json.bak +8 -8
- package/src/renderer.ts +18 -0
- package/src/server.ts +57 -3
- package/test.js +6 -6
package/README.md
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
A simple Node.js server for rendering videos using Twick.
|
|
4
4
|
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides a server-side rendering solution for Twick video projects. It allows you to render video projects on the server and download the resulting video files.
|
|
8
|
+
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
|
|
12
|
+
npm install @twick/render-server
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @twick/render-server
|
|
9
15
|
```
|
|
10
16
|
|
|
11
|
-
##
|
|
17
|
+
## Quick Start
|
|
12
18
|
|
|
13
19
|
### Starting the server
|
|
14
20
|
|
|
@@ -23,9 +29,9 @@ pnpm start
|
|
|
23
29
|
|
|
24
30
|
The server will start on port 3001 by default. You can change this by setting the `PORT` environment variable.
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
## API Endpoints
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
### POST /api/render-video
|
|
29
35
|
|
|
30
36
|
Renders a video using Twick.
|
|
31
37
|
|
|
@@ -75,11 +81,11 @@ Renders a video using Twick.
|
|
|
75
81
|
}
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
|
|
84
|
+
### GET /download/:outFile
|
|
79
85
|
|
|
80
86
|
Downloads a rendered video file.
|
|
81
87
|
|
|
82
|
-
|
|
88
|
+
### GET /health
|
|
83
89
|
|
|
84
90
|
Health check endpoint.
|
|
85
91
|
|
|
@@ -111,6 +117,25 @@ node test.js
|
|
|
111
117
|
|
|
112
118
|
> **Note:** This server will work on Linux and macOS only. Windows is not supported.
|
|
113
119
|
|
|
120
|
+
## Browser Support
|
|
121
|
+
|
|
122
|
+
This package requires a Node.js environment with support for:
|
|
123
|
+
- Node.js 18 or higher
|
|
124
|
+
- Puppeteer for video rendering
|
|
125
|
+
- File system operations
|
|
126
|
+
|
|
127
|
+
## Documentation
|
|
128
|
+
|
|
129
|
+
For complete documentation, refer to the project documentation site.
|
|
130
|
+
|
|
114
131
|
## License
|
|
115
132
|
|
|
116
|
-
|
|
133
|
+
This package is licensed under the **Sustainable Use License (SUL) Version 1.0**.
|
|
134
|
+
|
|
135
|
+
- Free for use in commercial and non-commercial apps
|
|
136
|
+
- Can be modified and self-hosted
|
|
137
|
+
- Cannot be sold, rebranded, or distributed as a standalone SDK
|
|
138
|
+
|
|
139
|
+
For commercial licensing inquiries, contact: contact@kifferai.com
|
|
140
|
+
|
|
141
|
+
For full license terms, see the main LICENSE.md file in the project root.
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a Twick video with the provided variables and settings.
|
|
3
|
+
* Processes project variables, merges settings with defaults, and
|
|
4
|
+
* generates a video file using the Twick renderer.
|
|
5
|
+
*
|
|
6
|
+
* @param variables - Project variables containing input configuration
|
|
7
|
+
* @param settings - Optional render settings to override defaults
|
|
8
|
+
* @returns Promise resolving to the path of the rendered video file
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```js
|
|
12
|
+
* const videoPath = await renderTwickVideo(
|
|
13
|
+
* { input: { properties: { width: 1920, height: 1080 } } },
|
|
14
|
+
* { quality: "high", outFile: "my-video.mp4" }
|
|
15
|
+
* );
|
|
16
|
+
* // videoPath = "./output/my-video.mp4"
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
1
19
|
declare const renderTwickVideo: (variables: any, settings: any) => Promise<string>;
|
|
2
20
|
export default renderTwickVideo;
|
|
3
21
|
//# sourceMappingURL=renderer.d.ts.map
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,gBAAgB,GAAU,WAAW,GAAG,EAAE,UAAU,GAAG,oBAiC5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,gBAAgB,GAAU,WAAW,GAAG,EAAE,UAAU,GAAG,oBAiC5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/renderer.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { renderVideo } from "@twick/renderer";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a Twick video with the provided variables and settings.
|
|
4
|
+
* Processes project variables, merges settings with defaults, and
|
|
5
|
+
* generates a video file using the Twick renderer.
|
|
6
|
+
*
|
|
7
|
+
* @param variables - Project variables containing input configuration
|
|
8
|
+
* @param settings - Optional render settings to override defaults
|
|
9
|
+
* @returns Promise resolving to the path of the rendered video file
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```js
|
|
13
|
+
* const videoPath = await renderTwickVideo(
|
|
14
|
+
* { input: { properties: { width: 1920, height: 1080 } } },
|
|
15
|
+
* { quality: "high", outFile: "my-video.mp4" }
|
|
16
|
+
* );
|
|
17
|
+
* // videoPath = "./output/my-video.mp4"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
2
20
|
const renderTwickVideo = async (variables, settings) => {
|
|
3
21
|
try {
|
|
4
22
|
const { input } = variables;
|
package/dist/renderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,gBAAgB,GAAG,KAAK,EAAE,SAAc,EAAE,QAAa,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAC7B,oCAAoC;QACpC,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,UAAU,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM;YAC/D,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE;gBACf,QAAQ,EAAE;oBACR,IAAI,EAAE,kBAAkB;iBACzB;gBACD,IAAI,EAAE;oBACJ,CAAC,EAAE,UAAU,CAAC,KAAK;oBACnB,CAAC,EAAE,UAAU,CAAC,MAAM;iBACrB;aACF;YACD,GAAG,QAAQ,EAAE,2CAA2C;SACzD,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC;YAC7B,WAAW,EAAE,mCAAmC;YAChD,SAAS,EAAE,SAAS;YACpB,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,gBAAgB,GAAG,KAAK,EAAE,SAAc,EAAE,QAAa,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAC7B,oCAAoC;QACpC,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,UAAU,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM;YAC/D,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE;gBACf,QAAQ,EAAE;oBACR,IAAI,EAAE,kBAAkB;iBACzB;gBACD,IAAI,EAAE;oBACJ,CAAC,EAAE,UAAU,CAAC,KAAK;oBACnB,CAAC,EAAE,UAAU,CAAC,MAAM;iBACrB;aACF;YACD,GAAG,QAAQ,EAAE,2CAA2C;SACzD,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC;YAC7B,WAAW,EAAE,mCAAmC;YAChD,SAAS,EAAE,SAAS;YACpB,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA6FA,QAAA,MAAM,OAAO,EAAE,OAAO,SAAS,EAAE,OAAmB,CAAC;AAiGrD,eAAe,OAAO,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -21,7 +21,21 @@ setInterval(() => {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}, RATE_LIMIT_CLEANUP_INTERVAL_MS);
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Rate limiting middleware for API endpoints.
|
|
26
|
+
* Tracks request counts per IP address and enforces rate limits
|
|
27
|
+
* to prevent abuse of the render server.
|
|
28
|
+
*
|
|
29
|
+
* @param req - Express request object
|
|
30
|
+
* @param res - Express response object
|
|
31
|
+
* @param next - Express next function
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```js
|
|
35
|
+
* app.use('/api', rateLimitMiddleware);
|
|
36
|
+
* // Applies rate limiting to all /api routes
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
25
39
|
const rateLimitMiddleware = (req, res, next) => {
|
|
26
40
|
const clientIP = req.ip || req.connection.remoteAddress || 'unknown';
|
|
27
41
|
const now = Date.now();
|
|
@@ -64,6 +78,21 @@ nodeApp.use(cors());
|
|
|
64
78
|
nodeApp.use(express.json());
|
|
65
79
|
// Serve static files from output directory
|
|
66
80
|
nodeApp.use("/output", express.static(path.join(__dirname, "../output")));
|
|
81
|
+
/**
|
|
82
|
+
* POST endpoint for video rendering requests.
|
|
83
|
+
* Accepts project variables and settings, renders the video,
|
|
84
|
+
* and returns a download URL for the completed video.
|
|
85
|
+
*
|
|
86
|
+
* @param req - Express request object containing variables and settings
|
|
87
|
+
* @param res - Express response object
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```js
|
|
91
|
+
* POST /api/render-video
|
|
92
|
+
* Body: { variables: {...}, settings: {...} }
|
|
93
|
+
* Response: { success: true, downloadUrl: "..." }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
67
96
|
nodeApp.post("/api/render-video", async (req, res) => {
|
|
68
97
|
const { variables, settings } = req.body;
|
|
69
98
|
try {
|
|
@@ -81,7 +110,20 @@ nodeApp.post("/api/render-video", async (req, res) => {
|
|
|
81
110
|
});
|
|
82
111
|
}
|
|
83
112
|
});
|
|
84
|
-
|
|
113
|
+
/**
|
|
114
|
+
* GET endpoint for downloading rendered videos.
|
|
115
|
+
* Serves video files with rate limiting and security checks
|
|
116
|
+
* to prevent path traversal attacks.
|
|
117
|
+
*
|
|
118
|
+
* @param req - Express request object with filename parameter
|
|
119
|
+
* @param res - Express response object
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```js
|
|
123
|
+
* GET /download/video-123.mp4
|
|
124
|
+
* // Downloads the specified video file
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
85
127
|
nodeApp.get("/download/:filename", rateLimitMiddleware, (req, res) => {
|
|
86
128
|
const outputDir = path.resolve(__dirname, "../output");
|
|
87
129
|
const requestedPath = path.resolve(outputDir, req.params.filename);
|
|
@@ -102,7 +144,19 @@ nodeApp.get("/download/:filename", rateLimitMiddleware, (req, res) => {
|
|
|
102
144
|
}
|
|
103
145
|
});
|
|
104
146
|
});
|
|
105
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Health check endpoint for monitoring server status.
|
|
149
|
+
* Returns server status and current timestamp for health monitoring.
|
|
150
|
+
*
|
|
151
|
+
* @param req - Express request object
|
|
152
|
+
* @param res - Express response object
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```js
|
|
156
|
+
* GET /health
|
|
157
|
+
* Response: { status: "ok", timestamp: "2024-01-01T00:00:00.000Z" }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
106
160
|
nodeApp.get("/health", (req, res) => {
|
|
107
161
|
res.json({
|
|
108
162
|
status: "ok",
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,gBAAgB,MAAM,eAAe,CAAC;AAE7C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AACtC,MAAM,SAAS,GAAG,oBAAoB,IAAI,EAAE,CAAC;AAE7C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,8BAA8B;AAC9B,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAC1D,MAAM,uBAAuB,GAAG,GAAG,CAAC,CAAC,8BAA8B;AACnE,MAAM,8BAA8B,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,uBAAuB;AAQzE,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEzD,uCAAuC;AACvC,WAAW,CAAC,GAAG,EAAE;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YAC1B,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC,EAAE,8BAA8B,CAAC,CAAC;AAEnC
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twick/render-server",
|
|
3
|
-
"version": "0.14.
|
|
4
|
-
"license": "
|
|
3
|
+
"version": "0.14.4",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/server.js",
|
|
7
7
|
"scripts": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twick/2d": "0.14.
|
|
18
|
-
"@twick/core": "0.14.
|
|
19
|
-
"@twick/ffmpeg": "0.14.
|
|
20
|
-
"@twick/renderer": "0.14.
|
|
21
|
-
"@twick/ui": "0.14.
|
|
22
|
-
"@twick/visualizer": "0.14.
|
|
17
|
+
"@twick/2d": "0.14.4",
|
|
18
|
+
"@twick/core": "0.14.4",
|
|
19
|
+
"@twick/ffmpeg": "0.14.4",
|
|
20
|
+
"@twick/renderer": "0.14.4",
|
|
21
|
+
"@twick/ui": "0.14.4",
|
|
22
|
+
"@twick/visualizer": "0.14.4",
|
|
23
23
|
"@types/express-rate-limit": "^6.0.2",
|
|
24
24
|
"cors": "^2.8.5",
|
|
25
25
|
"express": "^4.18.2",
|
package/package.json.bak
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twick/render-server",
|
|
3
|
-
"version": "0.14.
|
|
4
|
-
"license": "
|
|
3
|
+
"version": "0.14.4",
|
|
4
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/server.js",
|
|
7
7
|
"scripts": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twick/2d": "0.14.
|
|
18
|
-
"@twick/core": "0.14.
|
|
19
|
-
"@twick/ffmpeg": "0.14.
|
|
20
|
-
"@twick/renderer": "0.14.
|
|
21
|
-
"@twick/ui": "0.14.
|
|
22
|
-
"@twick/visualizer": "0.14.
|
|
17
|
+
"@twick/2d": "0.14.4",
|
|
18
|
+
"@twick/core": "0.14.4",
|
|
19
|
+
"@twick/ffmpeg": "0.14.4",
|
|
20
|
+
"@twick/renderer": "0.14.4",
|
|
21
|
+
"@twick/ui": "0.14.4",
|
|
22
|
+
"@twick/visualizer": "0.14.4",
|
|
23
23
|
"@types/express-rate-limit": "^6.0.2",
|
|
24
24
|
"cors": "^2.8.5",
|
|
25
25
|
"express": "^4.18.2",
|
package/src/renderer.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { renderVideo } from "@twick/renderer";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Renders a Twick video with the provided variables and settings.
|
|
5
|
+
* Processes project variables, merges settings with defaults, and
|
|
6
|
+
* generates a video file using the Twick renderer.
|
|
7
|
+
*
|
|
8
|
+
* @param variables - Project variables containing input configuration
|
|
9
|
+
* @param settings - Optional render settings to override defaults
|
|
10
|
+
* @returns Promise resolving to the path of the rendered video file
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```js
|
|
14
|
+
* const videoPath = await renderTwickVideo(
|
|
15
|
+
* { input: { properties: { width: 1920, height: 1080 } } },
|
|
16
|
+
* { quality: "high", outFile: "my-video.mp4" }
|
|
17
|
+
* );
|
|
18
|
+
* // videoPath = "./output/my-video.mp4"
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
3
21
|
const renderTwickVideo = async (variables: any, settings: any) => {
|
|
4
22
|
try {
|
|
5
23
|
const { input } = variables;
|
package/src/server.ts
CHANGED
|
@@ -33,7 +33,21 @@ setInterval(() => {
|
|
|
33
33
|
}
|
|
34
34
|
}, RATE_LIMIT_CLEANUP_INTERVAL_MS);
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Rate limiting middleware for API endpoints.
|
|
38
|
+
* Tracks request counts per IP address and enforces rate limits
|
|
39
|
+
* to prevent abuse of the render server.
|
|
40
|
+
*
|
|
41
|
+
* @param req - Express request object
|
|
42
|
+
* @param res - Express response object
|
|
43
|
+
* @param next - Express next function
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```js
|
|
47
|
+
* app.use('/api', rateLimitMiddleware);
|
|
48
|
+
* // Applies rate limiting to all /api routes
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
37
51
|
const rateLimitMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
38
52
|
const clientIP = req.ip || req.connection.remoteAddress || 'unknown';
|
|
39
53
|
const now = Date.now();
|
|
@@ -85,6 +99,21 @@ nodeApp.use(express.json());
|
|
|
85
99
|
// Serve static files from output directory
|
|
86
100
|
nodeApp.use("/output", express.static(path.join(__dirname, "../output")));
|
|
87
101
|
|
|
102
|
+
/**
|
|
103
|
+
* POST endpoint for video rendering requests.
|
|
104
|
+
* Accepts project variables and settings, renders the video,
|
|
105
|
+
* and returns a download URL for the completed video.
|
|
106
|
+
*
|
|
107
|
+
* @param req - Express request object containing variables and settings
|
|
108
|
+
* @param res - Express response object
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```js
|
|
112
|
+
* POST /api/render-video
|
|
113
|
+
* Body: { variables: {...}, settings: {...} }
|
|
114
|
+
* Response: { success: true, downloadUrl: "..." }
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
88
117
|
nodeApp.post("/api/render-video", async (req, res) => {
|
|
89
118
|
const { variables, settings } = req.body;
|
|
90
119
|
|
|
@@ -103,7 +132,20 @@ nodeApp.post("/api/render-video", async (req, res) => {
|
|
|
103
132
|
}
|
|
104
133
|
});
|
|
105
134
|
|
|
106
|
-
|
|
135
|
+
/**
|
|
136
|
+
* GET endpoint for downloading rendered videos.
|
|
137
|
+
* Serves video files with rate limiting and security checks
|
|
138
|
+
* to prevent path traversal attacks.
|
|
139
|
+
*
|
|
140
|
+
* @param req - Express request object with filename parameter
|
|
141
|
+
* @param res - Express response object
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```js
|
|
145
|
+
* GET /download/video-123.mp4
|
|
146
|
+
* // Downloads the specified video file
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
107
149
|
nodeApp.get("/download/:filename", rateLimitMiddleware, (req, res) => {
|
|
108
150
|
const outputDir = path.resolve(__dirname, "../output");
|
|
109
151
|
const requestedPath = path.resolve(outputDir, req.params.filename);
|
|
@@ -125,7 +167,19 @@ nodeApp.get("/download/:filename", rateLimitMiddleware, (req, res) => {
|
|
|
125
167
|
});
|
|
126
168
|
});
|
|
127
169
|
|
|
128
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Health check endpoint for monitoring server status.
|
|
172
|
+
* Returns server status and current timestamp for health monitoring.
|
|
173
|
+
*
|
|
174
|
+
* @param req - Express request object
|
|
175
|
+
* @param res - Express response object
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```js
|
|
179
|
+
* GET /health
|
|
180
|
+
* Response: { status: "ok", timestamp: "2024-01-01T00:00:00.000Z" }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
129
183
|
nodeApp.get("/health", (req, res) => {
|
|
130
184
|
res.json({
|
|
131
185
|
status: "ok",
|
package/test.js
CHANGED
|
@@ -104,10 +104,10 @@ async function testHealth() {
|
|
|
104
104
|
try {
|
|
105
105
|
const response = await fetch(`${API_URL}/health`);
|
|
106
106
|
const result = await response.json();
|
|
107
|
-
console.log('
|
|
107
|
+
console.log('Health check passed:', result);
|
|
108
108
|
return true;
|
|
109
109
|
} catch (error) {
|
|
110
|
-
console.error('
|
|
110
|
+
console.error('Health check failed:', error.message);
|
|
111
111
|
return false;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -132,15 +132,15 @@ async function testRender() {
|
|
|
132
132
|
const result = await response.json();
|
|
133
133
|
|
|
134
134
|
if (result.success) {
|
|
135
|
-
console.log('
|
|
135
|
+
console.log('Render test passed!');
|
|
136
136
|
console.log('📁 Output:', result.downloadUrl);
|
|
137
137
|
return true;
|
|
138
138
|
} else {
|
|
139
|
-
console.error('
|
|
139
|
+
console.error('Render test failed:', result.error);
|
|
140
140
|
return false;
|
|
141
141
|
}
|
|
142
142
|
} catch (error) {
|
|
143
|
-
console.error('
|
|
143
|
+
console.error('Render test failed:', error.message);
|
|
144
144
|
return false;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
@@ -154,7 +154,7 @@ async function runTests() {
|
|
|
154
154
|
if (healthPassed) {
|
|
155
155
|
await testRender();
|
|
156
156
|
} else {
|
|
157
|
-
console.log('
|
|
157
|
+
console.log('Skipping render test due to health check failure');
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
console.log('\n🏁 Tests completed');
|