@remotion/studio-server 4.0.503 → 4.0.504
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/helpers/open-in-editor.d.ts +1 -0
- package/dist/helpers/open-in-editor.js +18 -12
- package/dist/preview-server/element-install-state.d.ts +6 -2
- package/dist/preview-server/element-install-state.js +12 -5
- package/dist/preview-server/routes/element-install-plan.d.ts +2 -1
- package/dist/preview-server/routes/insert-element.js +2 -0
- package/dist/preview-server/routes/install-dependency.d.ts +2 -1
- package/dist/preview-server/routes/install-dependency.js +33 -44
- package/dist/preview-server/routes/update-public-license.d.ts +4 -0
- package/dist/preview-server/routes/update-public-license.js +9 -5
- package/dist/preview-server/studio-protocol/handle-discovery.js +49 -25
- package/dist/preview-server/studio-protocol/handle-install.js +3 -1
- package/dist/preview-server/studio-protocol/handle-license-key.d.ts +6 -0
- package/dist/preview-server/studio-protocol/handle-license-key.js +129 -0
- package/dist/preview-server/studio-protocol/origin-policy.d.ts +5 -3
- package/dist/preview-server/studio-protocol/origin-policy.js +34 -11
- package/dist/routes.js +11 -2
- package/package.json +8 -8
|
@@ -11,6 +11,7 @@ export type ProcessAndCommand = {
|
|
|
11
11
|
process: string;
|
|
12
12
|
command: Editor;
|
|
13
13
|
};
|
|
14
|
+
export declare const findMacOsEditorsFromProcessOutput: (output: string) => ProcessAndCommand[];
|
|
14
15
|
export declare function guessEditor(): Promise<ProcessAndCommand[]>;
|
|
15
16
|
export declare function launchEditor({ colNumber, editor, fileName, lineNumber, vsCodeNewWindow, logLevel }: {
|
|
16
17
|
fileName: string;
|
|
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.getDisplayNameForEditor = void 0;
|
|
40
|
+
exports.findMacOsEditorsFromProcessOutput = exports.getDisplayNameForEditor = void 0;
|
|
41
41
|
exports.guessEditor = guessEditor;
|
|
42
42
|
exports.launchEditor = launchEditor;
|
|
43
43
|
const node_child_process_1 = __importStar(require("node:child_process"));
|
|
@@ -167,6 +167,7 @@ const COMMON_EDITORS_OSX = {
|
|
|
167
167
|
'/Applications/Sublime Text.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',
|
|
168
168
|
'/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl',
|
|
169
169
|
'/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2': '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',
|
|
170
|
+
'/Applications/Visual Studio Code.app/Contents/MacOS/Code': 'code',
|
|
170
171
|
'/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',
|
|
171
172
|
'/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron': 'code-insiders',
|
|
172
173
|
'/Applications/VSCodium.app/Contents/MacOS/Electron': 'vscodium',
|
|
@@ -323,6 +324,21 @@ function getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber) {
|
|
|
323
324
|
return [fileName];
|
|
324
325
|
}
|
|
325
326
|
}
|
|
327
|
+
const findMacOsEditorsFromProcessOutput = (output) => {
|
|
328
|
+
const availableEditors = [];
|
|
329
|
+
const processNames = Object.keys(COMMON_EDITORS_OSX);
|
|
330
|
+
for (let i = 0; i < processNames.length; i++) {
|
|
331
|
+
const processName = processNames[i];
|
|
332
|
+
if (output.includes(processName)) {
|
|
333
|
+
availableEditors.push({
|
|
334
|
+
process: processName,
|
|
335
|
+
command: COMMON_EDITORS_OSX[processName],
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return availableEditors;
|
|
340
|
+
};
|
|
341
|
+
exports.findMacOsEditorsFromProcessOutput = findMacOsEditorsFromProcessOutput;
|
|
326
342
|
async function guessEditor() {
|
|
327
343
|
// We can find out which editor is currently running by:
|
|
328
344
|
// `ps x` on macOS and Linux
|
|
@@ -331,17 +347,7 @@ async function guessEditor() {
|
|
|
331
347
|
try {
|
|
332
348
|
if (process.platform === 'darwin') {
|
|
333
349
|
const output = (await execProm('ps x')).stdout.toString();
|
|
334
|
-
|
|
335
|
-
for (let i = 0; i < processNames.length; i++) {
|
|
336
|
-
const processName = processNames[i];
|
|
337
|
-
if (output.indexOf(processName) !== -1) {
|
|
338
|
-
availableEditors.push({
|
|
339
|
-
process: processName,
|
|
340
|
-
command: COMMON_EDITORS_OSX[processName],
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return availableEditors;
|
|
350
|
+
return (0, exports.findMacOsEditorsFromProcessOutput)(output);
|
|
345
351
|
}
|
|
346
352
|
if (process.platform === 'win32') {
|
|
347
353
|
// Some processes need elevated rights to get its executable path.
|
|
@@ -11,23 +11,27 @@ export type ElementInstallTarget = {
|
|
|
11
11
|
studioUrl: string;
|
|
12
12
|
updatedAt: number;
|
|
13
13
|
};
|
|
14
|
+
export type StudioProtocolTargetPurpose = 'install-element' | 'set-license-key';
|
|
14
15
|
type StudioProtocolTarget = {
|
|
15
16
|
readonly id: string;
|
|
16
17
|
readonly origin: string;
|
|
18
|
+
readonly purpose: StudioProtocolTargetPurpose;
|
|
17
19
|
readonly target: ElementInstallTarget;
|
|
18
20
|
readonly expiresAt: number;
|
|
19
21
|
};
|
|
20
22
|
export declare const updateElementInstallTarget: (newTarget: Omit<ElementInstallTarget, "updatedAt">) => void;
|
|
21
23
|
export declare const getElementInstallTargetByClientId: (clientId: string) => ElementInstallTarget | null;
|
|
22
24
|
export declare const getElementInstallTarget: (requestId: string | null) => ElementInstallTarget | null;
|
|
23
|
-
export declare const issueStudioProtocolTarget: ({ now, origin, target, }: {
|
|
25
|
+
export declare const issueStudioProtocolTarget: ({ now, origin, purpose, target, }: {
|
|
24
26
|
readonly now: number;
|
|
25
27
|
readonly origin: string;
|
|
28
|
+
readonly purpose: StudioProtocolTargetPurpose;
|
|
26
29
|
readonly target: ElementInstallTarget;
|
|
27
30
|
}) => StudioProtocolTarget;
|
|
28
|
-
export declare const consumeStudioProtocolTarget: ({ now, origin, targetId, }: {
|
|
31
|
+
export declare const consumeStudioProtocolTarget: ({ now, origin, purpose, targetId, }: {
|
|
29
32
|
readonly now: number;
|
|
30
33
|
readonly origin: string;
|
|
34
|
+
readonly purpose: StudioProtocolTargetPurpose;
|
|
31
35
|
readonly targetId: string;
|
|
32
36
|
}) => ElementInstallTarget | null;
|
|
33
37
|
export declare const clearElementInstallStateForTests: () => void;
|
|
@@ -45,7 +45,7 @@ const getElementInstallTarget = (requestId) => {
|
|
|
45
45
|
return bestTarget;
|
|
46
46
|
};
|
|
47
47
|
exports.getElementInstallTarget = getElementInstallTarget;
|
|
48
|
-
const issueStudioProtocolTarget = ({ now, origin, target, }) => {
|
|
48
|
+
const issueStudioProtocolTarget = ({ now, origin, purpose, target, }) => {
|
|
49
49
|
for (const [id, existing] of studioProtocolTargets) {
|
|
50
50
|
if (existing.expiresAt <= now) {
|
|
51
51
|
studioProtocolTargets.delete(id);
|
|
@@ -54,6 +54,7 @@ const issueStudioProtocolTarget = ({ now, origin, target, }) => {
|
|
|
54
54
|
const issued = {
|
|
55
55
|
id: (0, node_crypto_1.randomUUID)(),
|
|
56
56
|
origin,
|
|
57
|
+
purpose,
|
|
57
58
|
target: { ...target },
|
|
58
59
|
expiresAt: now + exports.STUDIO_PROTOCOL_TARGET_MAX_AGE,
|
|
59
60
|
};
|
|
@@ -61,19 +62,25 @@ const issueStudioProtocolTarget = ({ now, origin, target, }) => {
|
|
|
61
62
|
return issued;
|
|
62
63
|
};
|
|
63
64
|
exports.issueStudioProtocolTarget = issueStudioProtocolTarget;
|
|
64
|
-
const consumeStudioProtocolTarget = ({ now, origin, targetId, }) => {
|
|
65
|
+
const consumeStudioProtocolTarget = ({ now, origin, purpose, targetId, }) => {
|
|
65
66
|
const issued = studioProtocolTargets.get(targetId);
|
|
66
67
|
studioProtocolTargets.delete(targetId);
|
|
67
68
|
if (issued === undefined ||
|
|
68
69
|
issued.expiresAt <= now ||
|
|
69
|
-
issued.origin !== origin
|
|
70
|
+
issued.origin !== origin ||
|
|
71
|
+
issued.purpose !== purpose) {
|
|
70
72
|
return null;
|
|
71
73
|
}
|
|
72
74
|
const current = (0, exports.getElementInstallTargetByClientId)(issued.target.clientId);
|
|
73
75
|
if (current === null ||
|
|
74
76
|
now - current.updatedAt >= exports.ELEMENT_INSTALL_TARGET_MAX_AGE ||
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
current.readOnly) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (purpose === 'set-license-key') {
|
|
81
|
+
return issued.target;
|
|
82
|
+
}
|
|
83
|
+
if (!current.canInstall ||
|
|
77
84
|
current.compositionFile !== issued.target.compositionFile ||
|
|
78
85
|
current.compositionId !== issued.target.compositionId) {
|
|
79
86
|
return null;
|
|
@@ -3,7 +3,8 @@ export declare const normalizeElementSourceForComparison: (source: string) => st
|
|
|
3
3
|
export declare const getElementSourceHash: (source: string) => string;
|
|
4
4
|
export declare const validateElementInstallPosition: (position: import("@remotion/studio-shared").InsertableCompositionElementPosition | null) => void;
|
|
5
5
|
export declare const validateElementForInstallation: (element: {
|
|
6
|
-
dependencies:
|
|
6
|
+
dependencies: import("@remotion/studio-protocol").ElementDependency[];
|
|
7
|
+
durationInFrames?: number | undefined;
|
|
7
8
|
slug: string;
|
|
8
9
|
displayName: string;
|
|
9
10
|
sourceCode: string;
|
|
@@ -22,6 +22,7 @@ const hasExpectedFileState = ({ expected, actual, }) => {
|
|
|
22
22
|
return actual.sourceHash === expected.sourceHash;
|
|
23
23
|
};
|
|
24
24
|
const insertElementHandler = ({ input: { compositionFile, compositionId, element, expectedFileState, from, position, overwriteExisting, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
|
|
25
|
+
var _a;
|
|
25
26
|
try {
|
|
26
27
|
(0, element_install_plan_1.validateElementInstallPosition)(position);
|
|
27
28
|
if (from !== null &&
|
|
@@ -87,6 +88,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
|
|
|
87
88
|
prettierConfigOverride: null,
|
|
88
89
|
wrapInSequence: {
|
|
89
90
|
dimensions: element.dimensions,
|
|
91
|
+
durationInFrames: (_a = element.durationInFrames) !== null && _a !== void 0 ? _a : null,
|
|
90
92
|
from,
|
|
91
93
|
name: element.displayName,
|
|
92
94
|
position,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import type { ElementDependency } from '@remotion/studio-protocol';
|
|
1
2
|
import { type InstallPackageRequest, type InstallPackageResponse } from '@remotion/studio-shared';
|
|
2
3
|
import type { ApiHandler } from '../api-types';
|
|
3
|
-
export declare const getPackageInstallSpec: (
|
|
4
|
+
export declare const getPackageInstallSpec: (dependency: string | ElementDependency) => string;
|
|
4
5
|
export declare const handleInstallPackage: ApiHandler<InstallPackageRequest, InstallPackageResponse>;
|
|
@@ -12,21 +12,26 @@ const getExtraPackageVersion = (packageName) => {
|
|
|
12
12
|
const pkg = studio_shared_1.extraPackages.find((p) => p.name === packageName);
|
|
13
13
|
return pkg ? pkg.version : null;
|
|
14
14
|
};
|
|
15
|
-
const getPackageInstallSpec = (
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
return `${
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
const getPackageInstallSpec = (dependency) => {
|
|
16
|
+
const { name, version } = typeof dependency === 'string'
|
|
17
|
+
? { name: dependency, version: null }
|
|
18
|
+
: dependency;
|
|
19
|
+
const extraVersion = getExtraPackageVersion(name);
|
|
20
|
+
if (extraVersion)
|
|
21
|
+
return `${name}@${extraVersion}`;
|
|
22
|
+
if (name === 'remotion' || name.startsWith('@remotion/'))
|
|
23
|
+
return `${name}@${version_1.VERSION}`;
|
|
24
|
+
return version === null ? name : `${name}@${version}`;
|
|
24
25
|
};
|
|
25
26
|
exports.getPackageInstallSpec = getPackageInstallSpec;
|
|
26
|
-
const handleInstallPackage = async ({ logLevel, remotionRoot, input: {
|
|
27
|
-
for (const
|
|
28
|
-
if (!(0, studio_shared_1.isValidPackageName)(
|
|
29
|
-
return Promise.reject(new Error(`Package name ${JSON.stringify(
|
|
27
|
+
const handleInstallPackage = async ({ logLevel, remotionRoot, input: { dependencies } }) => {
|
|
28
|
+
for (const dependency of dependencies) {
|
|
29
|
+
if (!(0, studio_shared_1.isValidPackageName)(dependency.name)) {
|
|
30
|
+
return Promise.reject(new Error(`Package name ${JSON.stringify(dependency.name)} is invalid.`));
|
|
31
|
+
}
|
|
32
|
+
if (dependency.version !== null &&
|
|
33
|
+
!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(dependency.version)) {
|
|
34
|
+
return Promise.reject(new Error(`Package version ${JSON.stringify(dependency.version)} is invalid.`));
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
const manager = (0, get_package_manager_1.getPackageManager)({
|
|
@@ -36,13 +41,9 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNa
|
|
|
36
41
|
logLevel,
|
|
37
42
|
});
|
|
38
43
|
if (manager === 'unknown') {
|
|
39
|
-
throw new Error(`No lockfile was found in your project (one of ${get_package_manager_1.lockFilePaths
|
|
40
|
-
.map((p) => p.path)
|
|
41
|
-
.join(', ')}). Install dependencies using your favorite manager!`);
|
|
44
|
+
throw new Error(`No lockfile was found in your project (one of ${get_package_manager_1.lockFilePaths.map((p) => p.path).join(', ')}). Install dependencies using your favorite manager!`);
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
// packages use their supported version. Other packages resolve normally.
|
|
45
|
-
const packagesWithVersions = packageNames.map(exports.getPackageInstallSpec);
|
|
46
|
+
const packagesWithVersions = dependencies.map(exports.getPackageInstallSpec);
|
|
46
47
|
const command = (0, install_command_1.getInstallCommand)({
|
|
47
48
|
manager: manager.manager,
|
|
48
49
|
packages: packagesWithVersions,
|
|
@@ -54,34 +55,22 @@ const handleInstallPackage = async ({ logLevel, remotionRoot, input: { packageNa
|
|
|
54
55
|
try {
|
|
55
56
|
await new Promise((resolve, reject) => {
|
|
56
57
|
const cmd = (0, node_child_process_1.spawn)(manager.manager, command, (0, package_manager_spawn_options_1.getPackageManagerSpawnOptions)());
|
|
57
|
-
cmd.on('error',
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
resolve();
|
|
68
|
-
});
|
|
69
|
-
cmd.on('close', (code, signal) => {
|
|
70
|
-
if (code === 0) {
|
|
71
|
-
resolve();
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
reject(new Error(`Command exited with code ${code} and signal ${signal}`));
|
|
75
|
-
}
|
|
76
|
-
});
|
|
58
|
+
cmd.on('error', reject);
|
|
59
|
+
cmd.stdout.on('data', (d) => d
|
|
60
|
+
.toString()
|
|
61
|
+
.trim()
|
|
62
|
+
.split('\n')
|
|
63
|
+
.forEach((line) => renderer_1.RenderInternals.Log.info({ indent: true, logLevel }, line)));
|
|
64
|
+
cmd.stdout.on('end', resolve);
|
|
65
|
+
cmd.on('close', (code, signal) => code === 0
|
|
66
|
+
? resolve()
|
|
67
|
+
: reject(new Error(`Command exited with code ${code} and signal ${signal}`)));
|
|
77
68
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return Promise.resolve({});
|
|
69
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), `Done in ${Date.now() - time}ms`);
|
|
70
|
+
return {};
|
|
81
71
|
}
|
|
82
72
|
catch (err) {
|
|
83
|
-
|
|
84
|
-
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), renderer_1.RenderInternals.chalk.red(`Errored in ${timeEnd - time}ms`));
|
|
73
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), renderer_1.RenderInternals.chalk.red(`Errored in ${Date.now() - time}ms`));
|
|
85
74
|
return Promise.reject(err);
|
|
86
75
|
}
|
|
87
76
|
};
|
|
@@ -4,4 +4,8 @@ export declare const updatePublicLicenseInConfig: ({ configContents, publicLicen
|
|
|
4
4
|
configContents: string;
|
|
5
5
|
publicLicenseKey: string;
|
|
6
6
|
}) => string;
|
|
7
|
+
export declare const setPublicLicenseKeyInConfigFile: ({ configFile, publicLicenseKey, }: {
|
|
8
|
+
readonly configFile: string;
|
|
9
|
+
readonly publicLicenseKey: string;
|
|
10
|
+
}) => void;
|
|
7
11
|
export declare const updatePublicLicenseHandler: ApiHandler<UpdatePublicLicenseRequest, UpdatePublicLicenseResponse>;
|
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.updatePublicLicenseHandler = exports.updatePublicLicenseInConfig = void 0;
|
|
36
|
+
exports.updatePublicLicenseHandler = exports.setPublicLicenseKeyInConfigFile = exports.updatePublicLicenseInConfig = void 0;
|
|
37
37
|
const node_fs_1 = require("node:fs");
|
|
38
38
|
const recast = __importStar(require("recast"));
|
|
39
39
|
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
@@ -70,6 +70,11 @@ const updatePublicLicenseInConfig = ({ configContents, publicLicenseKey, }) => {
|
|
|
70
70
|
return `${configWithoutExistingCalls}${separator}Config.setPublicLicenseKey('${escapedPublicLicenseKey}');\n`;
|
|
71
71
|
};
|
|
72
72
|
exports.updatePublicLicenseInConfig = updatePublicLicenseInConfig;
|
|
73
|
+
const setPublicLicenseKeyInConfigFile = ({ configFile, publicLicenseKey, }) => {
|
|
74
|
+
const configContents = (0, node_fs_1.readFileSync)(configFile, 'utf8');
|
|
75
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(configFile, (0, exports.updatePublicLicenseInConfig)({ configContents, publicLicenseKey }), undefined);
|
|
76
|
+
};
|
|
77
|
+
exports.setPublicLicenseKeyInConfigFile = setPublicLicenseKeyInConfigFile;
|
|
73
78
|
const updatePublicLicenseHandler = ({ input, configFile }) => {
|
|
74
79
|
if (configFile === null || configFile === undefined) {
|
|
75
80
|
return Promise.resolve({
|
|
@@ -83,11 +88,10 @@ const updatePublicLicenseHandler = ({ input, configFile }) => {
|
|
|
83
88
|
reason: 'The public license key must not be empty.',
|
|
84
89
|
});
|
|
85
90
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
configContents,
|
|
91
|
+
(0, exports.setPublicLicenseKeyInConfigFile)({
|
|
92
|
+
configFile,
|
|
89
93
|
publicLicenseKey: input.publicLicenseKey,
|
|
90
|
-
})
|
|
94
|
+
});
|
|
91
95
|
return Promise.resolve({ success: true });
|
|
92
96
|
};
|
|
93
97
|
exports.updatePublicLicenseHandler = updatePublicLicenseHandler;
|
|
@@ -10,7 +10,7 @@ const version_1 = require("remotion/version");
|
|
|
10
10
|
const element_install_state_1 = require("../element-install-state");
|
|
11
11
|
const origin_policy_1 = require("./origin-policy");
|
|
12
12
|
const protocol_response_1 = require("./protocol-response");
|
|
13
|
-
const
|
|
13
|
+
const STUDIO_PROTOCOL_FOCUS_MAX_AGE = 5 * 60 * 1000;
|
|
14
14
|
exports.ELEMENT_INSTALL_TARGET_RESPONSE_WAIT = 250;
|
|
15
15
|
const requestInstallTarget = ({ liveEventsServer, }) => {
|
|
16
16
|
const requestId = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
@@ -20,28 +20,30 @@ const requestInstallTarget = ({ liveEventsServer, }) => {
|
|
|
20
20
|
});
|
|
21
21
|
return requestId;
|
|
22
22
|
};
|
|
23
|
-
const
|
|
23
|
+
const getLiveStudioTarget = (requestId) => {
|
|
24
24
|
const target = (0, element_install_state_1.getElementInstallTarget)(requestId);
|
|
25
25
|
const now = Date.now();
|
|
26
26
|
if (target === null ||
|
|
27
27
|
now - target.updatedAt >= element_install_state_1.ELEMENT_INSTALL_TARGET_MAX_AGE ||
|
|
28
28
|
target.lastFocusedAt === null ||
|
|
29
|
-
now - target.lastFocusedAt >=
|
|
30
|
-
|
|
31
|
-
target.readOnly ||
|
|
32
|
-
target.compositionFile === null ||
|
|
33
|
-
target.compositionId === null) {
|
|
29
|
+
now - target.lastFocusedAt >= STUDIO_PROTOCOL_FOCUS_MAX_AGE ||
|
|
30
|
+
target.readOnly) {
|
|
34
31
|
return null;
|
|
35
32
|
}
|
|
36
33
|
return target;
|
|
37
34
|
};
|
|
35
|
+
const isInstallableTarget = (target) => target !== null &&
|
|
36
|
+
target.canInstall &&
|
|
37
|
+
target.compositionFile !== null &&
|
|
38
|
+
target.compositionId !== null &&
|
|
39
|
+
target.lastFocusedAt !== null;
|
|
38
40
|
const getProject = ({ gitSource, remotionRoot, }) => (0, studio_shared_1.getProjectName)({
|
|
39
41
|
basename: node_path_1.default.basename,
|
|
40
42
|
gitSource,
|
|
41
43
|
resolvedRemotionRoot: remotionRoot,
|
|
42
44
|
});
|
|
43
45
|
const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRoot, request, response, }) => {
|
|
44
|
-
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
|
|
46
|
+
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: false, request, response });
|
|
45
47
|
const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
|
|
46
48
|
if (requestOrigin === null) {
|
|
47
49
|
(0, protocol_response_1.writeStudioProtocolError)({
|
|
@@ -65,12 +67,23 @@ const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRo
|
|
|
65
67
|
return new Promise((resolve) => {
|
|
66
68
|
setTimeout(() => {
|
|
67
69
|
const now = Date.now();
|
|
68
|
-
const target =
|
|
69
|
-
const
|
|
70
|
+
const target = getLiveStudioTarget(requestId);
|
|
71
|
+
const installTarget = isInstallableTarget(target) ? target : null;
|
|
72
|
+
const issuedInstallTarget = installTarget === null
|
|
70
73
|
? null
|
|
71
74
|
: (0, element_install_state_1.issueStudioProtocolTarget)({
|
|
72
75
|
now,
|
|
73
76
|
origin: requestOrigin,
|
|
77
|
+
purpose: 'install-element',
|
|
78
|
+
target: installTarget,
|
|
79
|
+
});
|
|
80
|
+
const licenseKeyOrigin = (0, origin_policy_1.getAllowedLicenseKeyOrigin)(request.headers.origin);
|
|
81
|
+
const issuedLicenseKeyTarget = target === null || licenseKeyOrigin === null
|
|
82
|
+
? null
|
|
83
|
+
: (0, element_install_state_1.issueStudioProtocolTarget)({
|
|
84
|
+
now,
|
|
85
|
+
origin: licenseKeyOrigin,
|
|
86
|
+
purpose: 'set-license-key',
|
|
74
87
|
target,
|
|
75
88
|
});
|
|
76
89
|
response.writeHead(200, {
|
|
@@ -81,23 +94,34 @@ const handleStudioProtocolDiscovery = ({ gitSource, liveEventsServer, remotionRo
|
|
|
81
94
|
protocol: 'remotion-studio-protocol',
|
|
82
95
|
protocolVersion: 1,
|
|
83
96
|
studioVersion: version_1.VERSION,
|
|
84
|
-
capabilities: {
|
|
85
|
-
install: [
|
|
86
|
-
{
|
|
87
|
-
payloadType: 'remotion-element',
|
|
88
|
-
payloadVersions: [1],
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
},
|
|
92
97
|
projectName: getProject({ gitSource, remotionRoot }),
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
capabilities: [
|
|
99
|
+
{
|
|
100
|
+
type: 'install-element',
|
|
101
|
+
payloadType: 'remotion-element',
|
|
102
|
+
payloadVersions: [1],
|
|
103
|
+
target: issuedInstallTarget === null || installTarget === null
|
|
104
|
+
? null
|
|
105
|
+
: {
|
|
106
|
+
id: issuedInstallTarget.id,
|
|
107
|
+
expiresAt: issuedInstallTarget.expiresAt,
|
|
108
|
+
compositionId: installTarget.compositionId,
|
|
109
|
+
lastFocusedAt: installTarget.lastFocusedAt,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'set-license-key',
|
|
114
|
+
target: issuedLicenseKeyTarget === null ||
|
|
115
|
+
target === null ||
|
|
116
|
+
target.lastFocusedAt === null
|
|
117
|
+
? null
|
|
118
|
+
: {
|
|
119
|
+
id: issuedLicenseKeyTarget.id,
|
|
120
|
+
expiresAt: issuedLicenseKeyTarget.expiresAt,
|
|
121
|
+
lastFocusedAt: target.lastFocusedAt,
|
|
122
|
+
},
|
|
100
123
|
},
|
|
124
|
+
],
|
|
101
125
|
}));
|
|
102
126
|
resolve();
|
|
103
127
|
}, exports.ELEMENT_INSTALL_TARGET_RESPONSE_WAIT);
|
|
@@ -8,6 +8,7 @@ const parse_body_1 = require("../parse-body");
|
|
|
8
8
|
const origin_policy_1 = require("./origin-policy");
|
|
9
9
|
const protocol_response_1 = require("./protocol-response");
|
|
10
10
|
const studioProtocolInstallRequestSchema = zod_1.z.object({
|
|
11
|
+
operation: zod_1.z.literal('install-element'),
|
|
11
12
|
protocol: zod_1.z.literal('remotion-studio-protocol'),
|
|
12
13
|
protocolVersion: zod_1.z.literal(1),
|
|
13
14
|
targetId: zod_1.z.string(),
|
|
@@ -44,7 +45,7 @@ const deliverElementInstall = ({ element, focusStudioTab, liveEventsServer, orig
|
|
|
44
45
|
return delivered;
|
|
45
46
|
};
|
|
46
47
|
const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, request, response, }) => {
|
|
47
|
-
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ request, response });
|
|
48
|
+
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: false, request, response });
|
|
48
49
|
const requestOrigin = (0, origin_policy_1.getAllowedStudioProtocolOrigin)(request.headers.origin);
|
|
49
50
|
if (requestOrigin === null) {
|
|
50
51
|
(0, protocol_response_1.writeStudioProtocolError)({
|
|
@@ -111,6 +112,7 @@ const handleStudioProtocolInstall = async ({ focusStudioTab, liveEventsServer, r
|
|
|
111
112
|
const target = (0, element_install_state_1.consumeStudioProtocolTarget)({
|
|
112
113
|
now: Date.now(),
|
|
113
114
|
origin: requestOrigin,
|
|
115
|
+
purpose: 'install-element',
|
|
114
116
|
targetId: parsedRequest.data.targetId,
|
|
115
117
|
});
|
|
116
118
|
if (target === null) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
export declare const handleStudioProtocolLicenseKey: ({ configFile, request, response, }: {
|
|
3
|
+
readonly configFile: string | null;
|
|
4
|
+
readonly request: IncomingMessage;
|
|
5
|
+
readonly response: ServerResponse<IncomingMessage>;
|
|
6
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleStudioProtocolLicenseKey = void 0;
|
|
4
|
+
const studio_protocol_1 = require("@remotion/studio-protocol");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const element_install_state_1 = require("../element-install-state");
|
|
7
|
+
const parse_body_1 = require("../parse-body");
|
|
8
|
+
const update_public_license_1 = require("../routes/update-public-license");
|
|
9
|
+
const origin_policy_1 = require("./origin-policy");
|
|
10
|
+
const protocol_response_1 = require("./protocol-response");
|
|
11
|
+
const studioProtocolLicenseKeyRequestSchema = zod_1.z.object({
|
|
12
|
+
operation: zod_1.z.literal('set-license-key'),
|
|
13
|
+
protocol: zod_1.z.literal('remotion-studio-protocol'),
|
|
14
|
+
protocolVersion: zod_1.z.literal(1),
|
|
15
|
+
targetId: zod_1.z.string().min(1),
|
|
16
|
+
licenseKey: zod_1.z.string(),
|
|
17
|
+
});
|
|
18
|
+
const MAX_STUDIO_PROTOCOL_LICENSE_KEY_BODY_SIZE = 4096;
|
|
19
|
+
const handleStudioProtocolLicenseKey = async ({ configFile, request, response, }) => {
|
|
20
|
+
(0, origin_policy_1.setStudioProtocolCorsHeaders)({ licenseKey: true, request, response });
|
|
21
|
+
const requestOrigin = (0, origin_policy_1.getAllowedLicenseKeyOrigin)(request.headers.origin);
|
|
22
|
+
if (requestOrigin === null) {
|
|
23
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
24
|
+
code: 'unsupported-origin',
|
|
25
|
+
message: 'Origin not allowed',
|
|
26
|
+
response,
|
|
27
|
+
status: 403,
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (request.method !== 'POST') {
|
|
32
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
33
|
+
code: 'method-not-allowed',
|
|
34
|
+
message: 'Use POST to set a public license key.',
|
|
35
|
+
response,
|
|
36
|
+
status: 405,
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let body;
|
|
41
|
+
try {
|
|
42
|
+
body = await (0, parse_body_1.parseRequestBody)(request, {
|
|
43
|
+
maxBytes: MAX_STUDIO_PROTOCOL_LICENSE_KEY_BODY_SIZE,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof parse_body_1.RequestBodyTooLargeError) {
|
|
48
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
49
|
+
code: 'request-too-large',
|
|
50
|
+
message: 'The request body is too large.',
|
|
51
|
+
response,
|
|
52
|
+
status: 413,
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
57
|
+
code: 'invalid-request',
|
|
58
|
+
message: 'The request body is not valid JSON.',
|
|
59
|
+
response,
|
|
60
|
+
status: 400,
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const parsedRequest = studioProtocolLicenseKeyRequestSchema.safeParse(body);
|
|
65
|
+
if (!parsedRequest.success) {
|
|
66
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
67
|
+
code: 'unsupported-protocol',
|
|
68
|
+
message: 'Invalid Remotion Studio Protocol request.',
|
|
69
|
+
response,
|
|
70
|
+
status: 400,
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!studio_protocol_1.StudioProtocolInternals.isValidPublicLicenseKey(parsedRequest.data.licenseKey)) {
|
|
75
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
76
|
+
code: 'invalid-license-key',
|
|
77
|
+
message: 'The license key is not a valid public Remotion license key.',
|
|
78
|
+
response,
|
|
79
|
+
status: 400,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const target = (0, element_install_state_1.consumeStudioProtocolTarget)({
|
|
84
|
+
now: Date.now(),
|
|
85
|
+
origin: requestOrigin,
|
|
86
|
+
purpose: 'set-license-key',
|
|
87
|
+
targetId: parsedRequest.data.targetId,
|
|
88
|
+
});
|
|
89
|
+
if (target === null) {
|
|
90
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
91
|
+
code: 'target-expired',
|
|
92
|
+
message: 'The selected Studio target is no longer available.',
|
|
93
|
+
response,
|
|
94
|
+
status: 409,
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (configFile === null) {
|
|
99
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
100
|
+
code: 'no-config-file',
|
|
101
|
+
message: 'The selected Studio did not load a Remotion config file.',
|
|
102
|
+
response,
|
|
103
|
+
status: 409,
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
(0, update_public_license_1.setPublicLicenseKeyInConfigFile)({
|
|
109
|
+
configFile,
|
|
110
|
+
publicLicenseKey: parsedRequest.data.licenseKey,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (_a) {
|
|
114
|
+
(0, protocol_response_1.writeStudioProtocolError)({
|
|
115
|
+
code: 'config-write-failed',
|
|
116
|
+
message: 'Could not update the Remotion config file.',
|
|
117
|
+
response,
|
|
118
|
+
status: 500,
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
123
|
+
response.end(JSON.stringify({
|
|
124
|
+
protocol: 'remotion-studio-protocol',
|
|
125
|
+
protocolVersion: 1,
|
|
126
|
+
status: 'license-key-set',
|
|
127
|
+
}));
|
|
128
|
+
};
|
|
129
|
+
exports.handleStudioProtocolLicenseKey = handleStudioProtocolLicenseKey;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
export declare const getAllowedStudioProtocolOrigin: (origin: string | undefined) => string | null;
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const setStudioProtocolCorsHeaders: ({ request, response, }: {
|
|
3
|
+
export declare const getAllowedLicenseKeyOrigin: (origin: string | undefined) => string | null;
|
|
4
|
+
export declare const setStudioProtocolCorsHeaders: ({ licenseKey, request, response, }: {
|
|
5
|
+
readonly licenseKey: boolean;
|
|
5
6
|
readonly request: IncomingMessage;
|
|
6
7
|
readonly response: ServerResponse<IncomingMessage>;
|
|
7
8
|
}) => void;
|
|
8
|
-
export declare const handleStudioProtocolOptions: ({ request, response, }: {
|
|
9
|
+
export declare const handleStudioProtocolOptions: ({ licenseKey, request, response, }: {
|
|
10
|
+
readonly licenseKey: boolean;
|
|
9
11
|
readonly request: IncomingMessage;
|
|
10
12
|
readonly response: ServerResponse<IncomingMessage>;
|
|
11
13
|
}) => Promise<void>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleStudioProtocolOptions = exports.setStudioProtocolCorsHeaders = exports.
|
|
3
|
+
exports.handleStudioProtocolOptions = exports.setStudioProtocolCorsHeaders = exports.getAllowedLicenseKeyOrigin = exports.getAllowedStudioProtocolOrigin = void 0;
|
|
4
|
+
const isLoopbackHttp = (url) => url.protocol === 'http:' &&
|
|
5
|
+
(url.hostname === 'localhost' || url.hostname === '127.0.0.1');
|
|
4
6
|
const getAllowedStudioProtocolOrigin = (origin) => {
|
|
5
7
|
if (!origin) {
|
|
6
8
|
return null;
|
|
7
9
|
}
|
|
8
10
|
try {
|
|
9
11
|
const url = new URL(origin);
|
|
10
|
-
|
|
11
|
-
(url.hostname === 'localhost' || url.hostname === '127.0.0.1');
|
|
12
|
-
if (url.protocol !== 'https:' && !isLoopbackHttp) {
|
|
12
|
+
if (url.protocol !== 'https:' && !isLoopbackHttp(url)) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
return url.origin;
|
|
@@ -19,10 +19,30 @@ const getAllowedStudioProtocolOrigin = (origin) => {
|
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
exports.getAllowedStudioProtocolOrigin = getAllowedStudioProtocolOrigin;
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const getAllowedLicenseKeyOrigin = (origin) => {
|
|
23
|
+
if (!origin) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const url = new URL(origin);
|
|
28
|
+
if (isLoopbackHttp(url)) {
|
|
29
|
+
return url.origin;
|
|
30
|
+
}
|
|
31
|
+
if (url.origin === 'https://remotion.pro' ||
|
|
32
|
+
url.origin === 'https://www.remotion.pro') {
|
|
33
|
+
return url.origin;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
catch (_a) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
exports.getAllowedLicenseKeyOrigin = getAllowedLicenseKeyOrigin;
|
|
42
|
+
const setStudioProtocolCorsHeaders = ({ licenseKey, request, response, }) => {
|
|
43
|
+
const origin = licenseKey
|
|
44
|
+
? (0, exports.getAllowedLicenseKeyOrigin)(request.headers.origin)
|
|
45
|
+
: (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
|
|
26
46
|
if (origin === null) {
|
|
27
47
|
return;
|
|
28
48
|
}
|
|
@@ -34,9 +54,12 @@ const setStudioProtocolCorsHeaders = ({ request, response, }) => {
|
|
|
34
54
|
response.setHeader('Access-Control-Allow-Private-Network', 'true');
|
|
35
55
|
};
|
|
36
56
|
exports.setStudioProtocolCorsHeaders = setStudioProtocolCorsHeaders;
|
|
37
|
-
const handleStudioProtocolOptions = ({ request, response, }) => {
|
|
38
|
-
(0, exports.setStudioProtocolCorsHeaders)({ request, response });
|
|
39
|
-
|
|
57
|
+
const handleStudioProtocolOptions = ({ licenseKey, request, response, }) => {
|
|
58
|
+
(0, exports.setStudioProtocolCorsHeaders)({ licenseKey, request, response });
|
|
59
|
+
const origin = licenseKey
|
|
60
|
+
? (0, exports.getAllowedLicenseKeyOrigin)(request.headers.origin)
|
|
61
|
+
: (0, exports.getAllowedStudioProtocolOrigin)(request.headers.origin);
|
|
62
|
+
response.writeHead(origin === null ? 403 : 204);
|
|
40
63
|
response.end();
|
|
41
64
|
return Promise.resolve();
|
|
42
65
|
};
|
package/dist/routes.js
CHANGED
|
@@ -55,6 +55,7 @@ const open_in_editor_1 = require("./preview-server/routes/open-in-editor");
|
|
|
55
55
|
const serve_static_1 = require("./preview-server/serve-static");
|
|
56
56
|
const handle_discovery_1 = require("./preview-server/studio-protocol/handle-discovery");
|
|
57
57
|
const handle_install_1 = require("./preview-server/studio-protocol/handle-install");
|
|
58
|
+
const handle_license_key_1 = require("./preview-server/studio-protocol/handle-license-key");
|
|
58
59
|
const origin_policy_1 = require("./preview-server/studio-protocol/origin-policy");
|
|
59
60
|
const validate_same_origin_1 = require("./preview-server/validate-same-origin");
|
|
60
61
|
const watch_ignore_next_change_1 = require("./preview-server/watch-ignore-next-change");
|
|
@@ -279,9 +280,14 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
279
280
|
});
|
|
280
281
|
}
|
|
281
282
|
if (url.pathname === '/api/studio-protocol' ||
|
|
282
|
-
url.pathname === '/api/studio-protocol/install'
|
|
283
|
+
url.pathname === '/api/studio-protocol/install' ||
|
|
284
|
+
url.pathname === '/api/studio-protocol/license-key') {
|
|
283
285
|
if (request.method === 'OPTIONS') {
|
|
284
|
-
return (0, origin_policy_1.handleStudioProtocolOptions)({
|
|
286
|
+
return (0, origin_policy_1.handleStudioProtocolOptions)({
|
|
287
|
+
licenseKey: url.pathname === '/api/studio-protocol/license-key',
|
|
288
|
+
request,
|
|
289
|
+
response,
|
|
290
|
+
});
|
|
285
291
|
}
|
|
286
292
|
if (url.pathname === '/api/studio-protocol') {
|
|
287
293
|
return (0, handle_discovery_1.handleStudioProtocolDiscovery)({
|
|
@@ -292,6 +298,9 @@ const handleRoutes = ({ staticHash, staticHashPrefix, outputHash, outputHashPref
|
|
|
292
298
|
response,
|
|
293
299
|
});
|
|
294
300
|
}
|
|
301
|
+
if (url.pathname === '/api/studio-protocol/license-key') {
|
|
302
|
+
return (0, handle_license_key_1.handleStudioProtocolLicenseKey)({ configFile, request, response });
|
|
303
|
+
}
|
|
295
304
|
return (0, handle_install_1.handleStudioProtocolInstall)({
|
|
296
305
|
focusStudioTab: (studioUrl) => {
|
|
297
306
|
(0, better_opn_1.focusBrowserTab)({ url: studioUrl }).catch(() => undefined);
|
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.504",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@remotion/studio-protocol": "4.0.
|
|
26
|
+
"@remotion/studio-protocol": "4.0.504",
|
|
27
27
|
"@babel/types": "7.24.0",
|
|
28
28
|
"@babel/parser": "7.24.1",
|
|
29
29
|
"@svgr/core": "8.1.0",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"semver": "7.5.3",
|
|
33
33
|
"zod": "4.4.3",
|
|
34
34
|
"prettier": "3.8.1",
|
|
35
|
-
"remotion": "4.0.
|
|
35
|
+
"remotion": "4.0.504",
|
|
36
36
|
"recast": "0.23.11",
|
|
37
|
-
"@remotion/bundler": "4.0.
|
|
38
|
-
"@remotion/renderer": "4.0.
|
|
39
|
-
"@remotion/studio-codemods": "4.0.
|
|
40
|
-
"@remotion/studio-shared": "4.0.
|
|
37
|
+
"@remotion/bundler": "4.0.504",
|
|
38
|
+
"@remotion/renderer": "4.0.504",
|
|
39
|
+
"@remotion/studio-codemods": "4.0.504",
|
|
40
|
+
"@remotion/studio-shared": "4.0.504",
|
|
41
41
|
"memfs": "3.4.3",
|
|
42
42
|
"open": "8.4.2"
|
|
43
43
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"ast-types": "0.16.1",
|
|
46
46
|
"react": "19.2.3",
|
|
47
47
|
"@types/semver": "7.5.3",
|
|
48
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
48
|
+
"@remotion/eslint-config-internal": "4.0.504",
|
|
49
49
|
"eslint": "9.19.0",
|
|
50
50
|
"@types/node": "20.12.14",
|
|
51
51
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|