@remotion/studio-server 4.0.422 → 4.0.423
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/dist/client-render-queue.d.ts +7 -0
- package/dist/client-render-queue.js +59 -0
- package/dist/helpers/resolve-output-path.d.ts +1 -0
- package/dist/helpers/resolve-output-path.js +16 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/routes.js +93 -8
- package/package.json +6 -6
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompletedClientRender } from '@remotion/studio-shared';
|
|
2
|
+
export declare const getCompletedClientRenders: () => CompletedClientRender[];
|
|
3
|
+
export declare const addCompletedClientRender: ({ render, remotionRoot, }: {
|
|
4
|
+
render: CompletedClientRender;
|
|
5
|
+
remotionRoot: string;
|
|
6
|
+
}) => void;
|
|
7
|
+
export declare const removeCompletedClientRender: (id: string) => void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeCompletedClientRender = exports.addCompletedClientRender = exports.getCompletedClientRenders = void 0;
|
|
4
|
+
const file_watcher_1 = require("./file-watcher");
|
|
5
|
+
const resolve_output_path_1 = require("./helpers/resolve-output-path");
|
|
6
|
+
const live_events_1 = require("./preview-server/live-events");
|
|
7
|
+
let completedClientRenders = [];
|
|
8
|
+
const cleanupFns = new Map();
|
|
9
|
+
const notifyClientsOfUpdate = () => {
|
|
10
|
+
(0, live_events_1.waitForLiveEventsListener)().then((listener) => {
|
|
11
|
+
listener.sendEventToClient({
|
|
12
|
+
type: 'client-renders-updated',
|
|
13
|
+
renders: (0, exports.getCompletedClientRenders)(),
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
const getCompletedClientRenders = () => {
|
|
18
|
+
return completedClientRenders;
|
|
19
|
+
};
|
|
20
|
+
exports.getCompletedClientRenders = getCompletedClientRenders;
|
|
21
|
+
const addCompletedClientRender = ({ render, remotionRoot, }) => {
|
|
22
|
+
if (completedClientRenders.some((r) => r.id === render.id)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
completedClientRenders.push(render);
|
|
26
|
+
const filePath = (0, resolve_output_path_1.resolveOutputPath)(remotionRoot, render.outName);
|
|
27
|
+
const { unwatch } = (0, file_watcher_1.installFileWatcher)({
|
|
28
|
+
file: filePath,
|
|
29
|
+
onChange: (type) => {
|
|
30
|
+
if (type === 'created' || type === 'deleted') {
|
|
31
|
+
updateCompletedClientRender(render.id, {
|
|
32
|
+
deletedOutputLocation: type === 'deleted',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
cleanupFns.set(render.id, unwatch);
|
|
38
|
+
notifyClientsOfUpdate();
|
|
39
|
+
};
|
|
40
|
+
exports.addCompletedClientRender = addCompletedClientRender;
|
|
41
|
+
const removeCompletedClientRender = (id) => {
|
|
42
|
+
const cleanup = cleanupFns.get(id);
|
|
43
|
+
if (cleanup) {
|
|
44
|
+
cleanup();
|
|
45
|
+
cleanupFns.delete(id);
|
|
46
|
+
}
|
|
47
|
+
completedClientRenders = completedClientRenders.filter((r) => r.id !== id);
|
|
48
|
+
notifyClientsOfUpdate();
|
|
49
|
+
};
|
|
50
|
+
exports.removeCompletedClientRender = removeCompletedClientRender;
|
|
51
|
+
const updateCompletedClientRender = (id, updates) => {
|
|
52
|
+
completedClientRenders = completedClientRenders.map((r) => {
|
|
53
|
+
if (r.id === id) {
|
|
54
|
+
return { ...r, ...updates };
|
|
55
|
+
}
|
|
56
|
+
return r;
|
|
57
|
+
});
|
|
58
|
+
notifyClientsOfUpdate();
|
|
59
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const resolveOutputPath: (remotionRoot: string, filePath: string) => string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveOutputPath = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const resolveOutputPath = (remotionRoot, filePath) => {
|
|
9
|
+
const absolutePath = node_path_1.default.join(remotionRoot, filePath);
|
|
10
|
+
const relativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
11
|
+
if (relativeToRoot.startsWith('..')) {
|
|
12
|
+
throw new Error(`Not allowed to write to ${relativeToRoot}`);
|
|
13
|
+
}
|
|
14
|
+
return absolutePath;
|
|
15
|
+
};
|
|
16
|
+
exports.resolveOutputPath = resolveOutputPath;
|
package/dist/index.d.ts
CHANGED
|
@@ -88,4 +88,10 @@ export declare const StudioServerInternals: {
|
|
|
88
88
|
version: string;
|
|
89
89
|
additionalArgs: string[];
|
|
90
90
|
}) => string[];
|
|
91
|
+
addCompletedClientRender: ({ render, remotionRoot, }: {
|
|
92
|
+
render: import("@remotion/studio-shared").CompletedClientRender;
|
|
93
|
+
remotionRoot: string;
|
|
94
|
+
}) => void;
|
|
95
|
+
getCompletedClientRenders: () => import("@remotion/studio-shared").CompletedClientRender[];
|
|
96
|
+
removeCompletedClientRender: (id: string) => void;
|
|
91
97
|
};
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const studio_shared_1 = require("@remotion/studio-shared");
|
|
|
5
5
|
var studio_shared_2 = require("@remotion/studio-shared");
|
|
6
6
|
Object.defineProperty(exports, "getDefaultOutLocation", { enumerable: true, get: function () { return studio_shared_2.getDefaultOutLocation; } });
|
|
7
7
|
const ansi_diff_1 = require("./ansi-diff");
|
|
8
|
+
const client_render_queue_1 = require("./client-render-queue");
|
|
8
9
|
const duplicate_composition_1 = require("./codemods/duplicate-composition");
|
|
9
10
|
const file_watcher_1 = require("./file-watcher");
|
|
10
11
|
const get_latest_remotion_version_1 = require("./get-latest-remotion-version");
|
|
@@ -30,4 +31,7 @@ exports.StudioServerInternals = {
|
|
|
30
31
|
parseAndApplyCodemod: duplicate_composition_1.parseAndApplyCodemod,
|
|
31
32
|
getInstalledDependencies: get_installed_dependencies_1.getInstalledDependencies,
|
|
32
33
|
getInstallCommand: install_command_1.getInstallCommand,
|
|
34
|
+
addCompletedClientRender: client_render_queue_1.addCompletedClientRender,
|
|
35
|
+
getCompletedClientRenders: client_render_queue_1.getCompletedClientRenders,
|
|
36
|
+
removeCompletedClientRender: client_render_queue_1.removeCompletedClientRender,
|
|
33
37
|
};
|
package/dist/routes.js
CHANGED
|
@@ -40,9 +40,11 @@ const fs_1 = __importStar(require("fs"));
|
|
|
40
40
|
const node_fs_1 = require("node:fs");
|
|
41
41
|
const node_path_1 = __importStar(require("node:path"));
|
|
42
42
|
const node_url_1 = require("node:url");
|
|
43
|
+
const client_render_queue_1 = require("./client-render-queue");
|
|
43
44
|
const get_file_source_1 = require("./helpers/get-file-source");
|
|
44
45
|
const get_installed_installable_packages_1 = require("./helpers/get-installed-installable-packages");
|
|
45
46
|
const open_in_editor_1 = require("./helpers/open-in-editor");
|
|
47
|
+
const resolve_output_path_1 = require("./helpers/resolve-output-path");
|
|
46
48
|
const api_routes_1 = require("./preview-server/api-routes");
|
|
47
49
|
const get_package_manager_1 = require("./preview-server/get-package-manager");
|
|
48
50
|
const handler_1 = require("./preview-server/handler");
|
|
@@ -98,6 +100,7 @@ const handleFallback = async ({ remotionRoot, hash, response, getCurrentInputPro
|
|
|
98
100
|
remotionRoot,
|
|
99
101
|
studioServerCommand: packageManager === 'unknown' ? null : packageManager.startCommand,
|
|
100
102
|
renderQueue: getRenderQueue(),
|
|
103
|
+
completedClientRenders: (0, client_render_queue_1.getCompletedClientRenders)(),
|
|
101
104
|
numberOfAudioTags,
|
|
102
105
|
publicFiles: (0, public_folder_1.getFiles)(),
|
|
103
106
|
includeFavicon: true,
|
|
@@ -172,16 +175,18 @@ const handleOpenInEditor = async (remotionRoot, req, res, logLevel) => {
|
|
|
172
175
|
}));
|
|
173
176
|
}
|
|
174
177
|
};
|
|
178
|
+
const validateSameOrigin = (req) => {
|
|
179
|
+
const { origin, host } = req.headers;
|
|
180
|
+
if (origin) {
|
|
181
|
+
const originUrl = new URL(origin);
|
|
182
|
+
if (originUrl.host !== host) {
|
|
183
|
+
throw new Error('Request from different origin not allowed');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
175
187
|
const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
176
188
|
try {
|
|
177
|
-
|
|
178
|
-
const { host } = req.headers;
|
|
179
|
-
if (origin) {
|
|
180
|
-
const originUrl = new URL(origin);
|
|
181
|
-
if (originUrl.host !== host) {
|
|
182
|
-
throw new Error('Request from different origin not allowed');
|
|
183
|
-
}
|
|
184
|
-
}
|
|
189
|
+
validateSameOrigin(req);
|
|
185
190
|
const query = new node_url_1.URLSearchParams(search);
|
|
186
191
|
const filePath = query.get('filePath');
|
|
187
192
|
if (typeof filePath !== 'string') {
|
|
@@ -205,6 +210,65 @@ const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
|
205
210
|
}
|
|
206
211
|
return Promise.resolve();
|
|
207
212
|
};
|
|
213
|
+
const handleUploadOutput = ({ req, res, search, remotionRoot, }) => {
|
|
214
|
+
try {
|
|
215
|
+
validateSameOrigin(req);
|
|
216
|
+
const query = new node_url_1.URLSearchParams(search);
|
|
217
|
+
const filePath = query.get('filePath');
|
|
218
|
+
if (typeof filePath !== 'string') {
|
|
219
|
+
throw new Error('No `filePath` provided');
|
|
220
|
+
}
|
|
221
|
+
const absolutePath = (0, resolve_output_path_1.resolveOutputPath)(remotionRoot, filePath);
|
|
222
|
+
fs_1.default.mkdirSync(node_path_1.default.dirname(absolutePath), { recursive: true });
|
|
223
|
+
const writeStream = (0, fs_1.createWriteStream)(absolutePath);
|
|
224
|
+
writeStream.on('close', () => {
|
|
225
|
+
res.end(JSON.stringify({ success: true }));
|
|
226
|
+
});
|
|
227
|
+
writeStream.on('error', (err) => {
|
|
228
|
+
res.statusCode = 500;
|
|
229
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
230
|
+
});
|
|
231
|
+
req.on('error', (err) => {
|
|
232
|
+
writeStream.destroy();
|
|
233
|
+
res.statusCode = 500;
|
|
234
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
235
|
+
});
|
|
236
|
+
req.pipe(writeStream);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
res.statusCode = 500;
|
|
240
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
241
|
+
}
|
|
242
|
+
return Promise.resolve();
|
|
243
|
+
};
|
|
244
|
+
const handleRegisterClientRender = async ({ req, res, remotionRoot, }) => {
|
|
245
|
+
try {
|
|
246
|
+
validateSameOrigin(req);
|
|
247
|
+
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
248
|
+
(0, client_render_queue_1.addCompletedClientRender)({ render: body, remotionRoot });
|
|
249
|
+
res.setHeader('content-type', 'application/json');
|
|
250
|
+
res.writeHead(200);
|
|
251
|
+
res.end(JSON.stringify({ success: true }));
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
res.statusCode = 500;
|
|
255
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
const handleUnregisterClientRender = async ({ req, res, }) => {
|
|
259
|
+
try {
|
|
260
|
+
validateSameOrigin(req);
|
|
261
|
+
const body = (await (0, parse_body_1.parseRequestBody)(req));
|
|
262
|
+
(0, client_render_queue_1.removeCompletedClientRender)(body.id);
|
|
263
|
+
res.setHeader('content-type', 'application/json');
|
|
264
|
+
res.writeHead(200);
|
|
265
|
+
res.end(JSON.stringify({ success: true }));
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
res.statusCode = 500;
|
|
269
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
270
|
+
}
|
|
271
|
+
};
|
|
208
272
|
const handleFavicon = (_, response) => {
|
|
209
273
|
const filePath = node_path_1.default.join(__dirname, '..', 'web', 'favicon.png');
|
|
210
274
|
const stat = (0, node_fs_1.statSync)(filePath);
|
|
@@ -259,6 +323,27 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
259
323
|
publicDir,
|
|
260
324
|
});
|
|
261
325
|
}
|
|
326
|
+
if (url.pathname === '/api/upload-output') {
|
|
327
|
+
return handleUploadOutput({
|
|
328
|
+
req: request,
|
|
329
|
+
res: response,
|
|
330
|
+
search: url.search,
|
|
331
|
+
remotionRoot,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
if (url.pathname === '/api/register-client-render') {
|
|
335
|
+
return handleRegisterClientRender({
|
|
336
|
+
req: request,
|
|
337
|
+
res: response,
|
|
338
|
+
remotionRoot,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
if (url.pathname === '/api/unregister-client-render') {
|
|
342
|
+
return handleUnregisterClientRender({
|
|
343
|
+
req: request,
|
|
344
|
+
res: response,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
262
347
|
for (const [key, value] of Object.entries(api_routes_1.allApiRoutes)) {
|
|
263
348
|
if (url.pathname === key) {
|
|
264
349
|
return (0, handler_1.handleRequest)({
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/studio-server",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.423",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/parser": "7.24.1",
|
|
27
27
|
"semver": "7.5.3",
|
|
28
|
-
"remotion": "4.0.
|
|
28
|
+
"remotion": "4.0.423",
|
|
29
29
|
"recast": "0.23.11",
|
|
30
|
-
"@remotion/bundler": "4.0.
|
|
31
|
-
"@remotion/renderer": "4.0.
|
|
32
|
-
"@remotion/studio-shared": "4.0.
|
|
30
|
+
"@remotion/bundler": "4.0.423",
|
|
31
|
+
"@remotion/renderer": "4.0.423",
|
|
32
|
+
"@remotion/studio-shared": "4.0.423",
|
|
33
33
|
"memfs": "3.4.3",
|
|
34
34
|
"source-map": "0.7.3",
|
|
35
35
|
"open": "^8.4.2"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react": "19.2.3",
|
|
40
40
|
"@babel/types": "7.24.0",
|
|
41
41
|
"@types/semver": "^7.3.4",
|
|
42
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
42
|
+
"@remotion/eslint-config-internal": "4.0.423",
|
|
43
43
|
"eslint": "9.19.0",
|
|
44
44
|
"@types/node": "20.12.14"
|
|
45
45
|
},
|