@remotion/studio-server 4.0.421 → 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 +12 -1
- package/dist/index.js +4 -0
- package/dist/preview-server/__tests__/multiple-lockfiles.test.d.ts +1 -0
- package/dist/preview-server/__tests__/multiple-lockfiles.test.js +37 -0
- package/dist/preview-server/get-package-manager.d.ts +7 -1
- package/dist/preview-server/get-package-manager.js +17 -12
- package/dist/preview-server/routes/install-dependency.js +6 -1
- package/dist/preview-server/routes/update-available.js +2 -2
- package/dist/preview-server/update-available.d.ts +2 -1
- package/dist/preview-server/update-available.js +15 -5
- package/dist/routes.js +99 -9
- 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
|
@@ -41,7 +41,12 @@ export declare const StudioServerInternals: {
|
|
|
41
41
|
installCommand: string;
|
|
42
42
|
startCommand: string;
|
|
43
43
|
}[];
|
|
44
|
-
getPackageManager: (remotionRoot
|
|
44
|
+
getPackageManager: ({ remotionRoot, packageManager, dirUp, logLevel, }: {
|
|
45
|
+
remotionRoot: string;
|
|
46
|
+
packageManager: string | undefined;
|
|
47
|
+
dirUp: number;
|
|
48
|
+
logLevel: import("@remotion/renderer").LogLevel;
|
|
49
|
+
}) => {
|
|
45
50
|
manager: import("@remotion/studio-shared").PackageManager;
|
|
46
51
|
path: string;
|
|
47
52
|
installCommand: string;
|
|
@@ -83,4 +88,10 @@ export declare const StudioServerInternals: {
|
|
|
83
88
|
version: string;
|
|
84
89
|
additionalArgs: string[];
|
|
85
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;
|
|
86
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
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
const bun_test_1 = require("bun:test");
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const get_package_manager_1 = require("../get-package-manager");
|
|
11
|
+
(0, bun_test_1.describe)('getPackageManager multiple lockfiles', () => {
|
|
12
|
+
let tempDir;
|
|
13
|
+
(0, bun_test_1.beforeEach)(() => {
|
|
14
|
+
tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'remotion-test-'));
|
|
15
|
+
});
|
|
16
|
+
(0, bun_test_1.afterEach)(() => {
|
|
17
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
(0, bun_test_1.test)('should not throw error when multiple lockfiles are detected', () => {
|
|
20
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'package-lock.json'), '{}');
|
|
21
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'bun.lock'), '');
|
|
22
|
+
// Should not throw
|
|
23
|
+
const manager = (0, get_package_manager_1.getPackageManager)(tempDir, undefined, 0);
|
|
24
|
+
// Should return one of them (usually the first one in the list, which is npm)
|
|
25
|
+
(0, bun_test_1.expect)(manager).not.toBe('unknown');
|
|
26
|
+
if (typeof manager !== 'string') {
|
|
27
|
+
(0, bun_test_1.expect)(['npm', 'bun']).toContain(manager.manager);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
(0, bun_test_1.test)('should return npm if only package-lock.json exists', () => {
|
|
31
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, 'package-lock.json'), '{}');
|
|
32
|
+
const manager = (0, get_package_manager_1.getPackageManager)(tempDir, undefined, 0);
|
|
33
|
+
if (typeof manager !== 'string') {
|
|
34
|
+
(0, bun_test_1.expect)(manager.manager).toBe('npm');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LogLevel } from '@remotion/renderer';
|
|
1
2
|
import type { PackageManager } from '@remotion/studio-shared';
|
|
2
3
|
type LockfilePath = {
|
|
3
4
|
manager: PackageManager;
|
|
@@ -6,5 +7,10 @@ type LockfilePath = {
|
|
|
6
7
|
startCommand: string;
|
|
7
8
|
};
|
|
8
9
|
export declare const lockFilePaths: LockfilePath[];
|
|
9
|
-
export declare const getPackageManager: (remotionRoot
|
|
10
|
+
export declare const getPackageManager: ({ remotionRoot, packageManager, dirUp, logLevel, }: {
|
|
11
|
+
remotionRoot: string;
|
|
12
|
+
packageManager: string | undefined;
|
|
13
|
+
dirUp: number;
|
|
14
|
+
logLevel: LogLevel;
|
|
15
|
+
}) => LockfilePath | "unknown";
|
|
10
16
|
export {};
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getPackageManager = exports.lockFilePaths = void 0;
|
|
7
|
+
const renderer_1 = require("@remotion/renderer");
|
|
7
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
10
|
exports.lockFilePaths = [
|
|
@@ -38,7 +39,8 @@ exports.lockFilePaths = [
|
|
|
38
39
|
startCommand: 'bunx remotion studio',
|
|
39
40
|
},
|
|
40
41
|
];
|
|
41
|
-
|
|
42
|
+
let warnedAboutMultipleLockfiles = false;
|
|
43
|
+
const getPackageManager = ({ remotionRoot, packageManager, dirUp, logLevel, }) => {
|
|
42
44
|
if (packageManager) {
|
|
43
45
|
const manager = exports.lockFilePaths.find((p) => p.manager === packageManager);
|
|
44
46
|
if (!manager) {
|
|
@@ -53,18 +55,21 @@ const getPackageManager = (remotionRoot, packageManager, dirUp) => {
|
|
|
53
55
|
return 'unknown';
|
|
54
56
|
}
|
|
55
57
|
if (existingPkgManagers.length === 0) {
|
|
56
|
-
return (0, exports.getPackageManager)(
|
|
58
|
+
return (0, exports.getPackageManager)({
|
|
59
|
+
remotionRoot,
|
|
60
|
+
packageManager,
|
|
61
|
+
dirUp: dirUp + 1,
|
|
62
|
+
logLevel,
|
|
63
|
+
});
|
|
57
64
|
}
|
|
58
|
-
if (existingPkgManagers.length > 1) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
].join('\n');
|
|
67
|
-
throw new Error(error);
|
|
65
|
+
if (existingPkgManagers.length > 1 && !warnedAboutMultipleLockfiles) {
|
|
66
|
+
warnedAboutMultipleLockfiles = true;
|
|
67
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, '⚠️ Multiple lockfiles detected:');
|
|
68
|
+
for (const pkgManager of existingPkgManagers) {
|
|
69
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, ` - ${pkgManager.path}`);
|
|
70
|
+
}
|
|
71
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, '');
|
|
72
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, 'This can lead to bugs, delete all but one of these files.');
|
|
68
73
|
}
|
|
69
74
|
return existingPkgManagers[0];
|
|
70
75
|
};
|
|
@@ -21,7 +21,12 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNa
|
|
|
21
21
|
return Promise.reject(new Error(`Package ${packageName} is not allowed to be installed.`));
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
const manager = (0, get_package_manager_1.getPackageManager)(
|
|
24
|
+
const manager = (0, get_package_manager_1.getPackageManager)({
|
|
25
|
+
remotionRoot,
|
|
26
|
+
packageManager: undefined,
|
|
27
|
+
dirUp: 0,
|
|
28
|
+
logLevel,
|
|
29
|
+
});
|
|
25
30
|
if (manager === 'unknown') {
|
|
26
31
|
throw new Error(`No lockfile was found in your project (one of ${get_package_manager_1.lockFilePaths
|
|
27
32
|
.map((p) => p.path)
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleUpdate = void 0;
|
|
4
4
|
const update_available_1 = require("../update-available");
|
|
5
|
-
const handleUpdate = async ({ remotionRoot }) => {
|
|
6
|
-
const data = await (0, update_available_1.isUpdateAvailableWithTimeout)(remotionRoot);
|
|
5
|
+
const handleUpdate = async ({ remotionRoot, logLevel }) => {
|
|
6
|
+
const data = await (0, update_available_1.isUpdateAvailableWithTimeout)(remotionRoot, logLevel);
|
|
7
7
|
return data;
|
|
8
8
|
};
|
|
9
9
|
exports.handleUpdate = handleUpdate;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LogLevel } from '@remotion/renderer';
|
|
1
2
|
import type { UpdateAvailableResponse } from '@remotion/studio-shared';
|
|
2
3
|
export declare const getRemotionVersion: () => any;
|
|
3
|
-
export declare const isUpdateAvailableWithTimeout: (remotionRoot: string) => Promise<UpdateAvailableResponse>;
|
|
4
|
+
export declare const isUpdateAvailableWithTimeout: (remotionRoot: string, logLevel: LogLevel) => Promise<UpdateAvailableResponse>;
|
|
@@ -7,9 +7,14 @@ exports.isUpdateAvailableWithTimeout = exports.getRemotionVersion = void 0;
|
|
|
7
7
|
const semver_1 = __importDefault(require("semver"));
|
|
8
8
|
const get_latest_remotion_version_1 = require("../get-latest-remotion-version");
|
|
9
9
|
const get_package_manager_1 = require("./get-package-manager");
|
|
10
|
-
const isUpdateAvailable = async ({ remotionRoot, currentVersion, }) => {
|
|
10
|
+
const isUpdateAvailable = async ({ remotionRoot, currentVersion, logLevel, }) => {
|
|
11
11
|
const latest = await (0, get_latest_remotion_version_1.getLatestRemotionVersion)();
|
|
12
|
-
const pkgManager = (0, get_package_manager_1.getPackageManager)(
|
|
12
|
+
const pkgManager = (0, get_package_manager_1.getPackageManager)({
|
|
13
|
+
remotionRoot,
|
|
14
|
+
packageManager: undefined,
|
|
15
|
+
dirUp: 0,
|
|
16
|
+
logLevel,
|
|
17
|
+
});
|
|
13
18
|
return {
|
|
14
19
|
updateAvailable: semver_1.default.lt(currentVersion, latest),
|
|
15
20
|
currentVersion,
|
|
@@ -25,10 +30,15 @@ const getRemotionVersion = () => {
|
|
|
25
30
|
return version;
|
|
26
31
|
};
|
|
27
32
|
exports.getRemotionVersion = getRemotionVersion;
|
|
28
|
-
const isUpdateAvailableWithTimeout = (remotionRoot) => {
|
|
33
|
+
const isUpdateAvailableWithTimeout = (remotionRoot, logLevel) => {
|
|
29
34
|
const version = (0, exports.getRemotionVersion)();
|
|
30
35
|
const threeSecTimeout = new Promise((resolve) => {
|
|
31
|
-
const pkgManager = (0, get_package_manager_1.getPackageManager)(
|
|
36
|
+
const pkgManager = (0, get_package_manager_1.getPackageManager)({
|
|
37
|
+
remotionRoot,
|
|
38
|
+
packageManager: undefined,
|
|
39
|
+
dirUp: 0,
|
|
40
|
+
logLevel,
|
|
41
|
+
});
|
|
32
42
|
setTimeout(() => {
|
|
33
43
|
resolve({
|
|
34
44
|
currentVersion: version,
|
|
@@ -41,7 +51,7 @@ const isUpdateAvailableWithTimeout = (remotionRoot) => {
|
|
|
41
51
|
});
|
|
42
52
|
return Promise.race([
|
|
43
53
|
threeSecTimeout,
|
|
44
|
-
isUpdateAvailable({ remotionRoot, currentVersion: version }),
|
|
54
|
+
isUpdateAvailable({ remotionRoot, currentVersion: version, logLevel }),
|
|
45
55
|
]);
|
|
46
56
|
};
|
|
47
57
|
exports.isUpdateAvailableWithTimeout = isUpdateAvailableWithTimeout;
|
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");
|
|
@@ -81,7 +83,12 @@ const handleFallback = async ({ remotionRoot, hash, response, getCurrentInputPro
|
|
|
81
83
|
response.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
|
82
84
|
response.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
|
|
83
85
|
}
|
|
84
|
-
const packageManager = (0, get_package_manager_1.getPackageManager)(
|
|
86
|
+
const packageManager = (0, get_package_manager_1.getPackageManager)({
|
|
87
|
+
remotionRoot,
|
|
88
|
+
packageManager: undefined,
|
|
89
|
+
dirUp: 0,
|
|
90
|
+
logLevel,
|
|
91
|
+
});
|
|
85
92
|
(0, public_folder_1.fetchFolder)({ publicDir, staticHash: hash });
|
|
86
93
|
const installedDependencies = (0, get_installed_installable_packages_1.getInstalledInstallablePackages)(remotionRoot);
|
|
87
94
|
response.end(bundler_1.BundlerInternals.indexHtml({
|
|
@@ -93,6 +100,7 @@ const handleFallback = async ({ remotionRoot, hash, response, getCurrentInputPro
|
|
|
93
100
|
remotionRoot,
|
|
94
101
|
studioServerCommand: packageManager === 'unknown' ? null : packageManager.startCommand,
|
|
95
102
|
renderQueue: getRenderQueue(),
|
|
103
|
+
completedClientRenders: (0, client_render_queue_1.getCompletedClientRenders)(),
|
|
96
104
|
numberOfAudioTags,
|
|
97
105
|
publicFiles: (0, public_folder_1.getFiles)(),
|
|
98
106
|
includeFavicon: true,
|
|
@@ -167,16 +175,18 @@ const handleOpenInEditor = async (remotionRoot, req, res, logLevel) => {
|
|
|
167
175
|
}));
|
|
168
176
|
}
|
|
169
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
|
+
};
|
|
170
187
|
const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
171
188
|
try {
|
|
172
|
-
|
|
173
|
-
const { host } = req.headers;
|
|
174
|
-
if (origin) {
|
|
175
|
-
const originUrl = new URL(origin);
|
|
176
|
-
if (originUrl.host !== host) {
|
|
177
|
-
throw new Error('Request from different origin not allowed');
|
|
178
|
-
}
|
|
179
|
-
}
|
|
189
|
+
validateSameOrigin(req);
|
|
180
190
|
const query = new node_url_1.URLSearchParams(search);
|
|
181
191
|
const filePath = query.get('filePath');
|
|
182
192
|
if (typeof filePath !== 'string') {
|
|
@@ -200,6 +210,65 @@ const handleAddAsset = ({ req, res, search, publicDir, }) => {
|
|
|
200
210
|
}
|
|
201
211
|
return Promise.resolve();
|
|
202
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
|
+
};
|
|
203
272
|
const handleFavicon = (_, response) => {
|
|
204
273
|
const filePath = node_path_1.default.join(__dirname, '..', 'web', 'favicon.png');
|
|
205
274
|
const stat = (0, node_fs_1.statSync)(filePath);
|
|
@@ -254,6 +323,27 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
254
323
|
publicDir,
|
|
255
324
|
});
|
|
256
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
|
+
}
|
|
257
347
|
for (const [key, value] of Object.entries(api_routes_1.allApiRoutes)) {
|
|
258
348
|
if (url.pathname === key) {
|
|
259
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
|
},
|