@remotion/studio-server 4.0.502 → 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.
Files changed (60) hide show
  1. package/dist/detect-outdated-remotion-skills.d.ts +25 -0
  2. package/dist/detect-outdated-remotion-skills.js +73 -0
  3. package/dist/helpers/custom-editor.d.ts +37 -0
  4. package/dist/helpers/custom-editor.js +167 -0
  5. package/dist/helpers/editor-registry.d.ts +18 -0
  6. package/dist/helpers/editor-registry.js +500 -0
  7. package/dist/helpers/open-in-editor.d.ts +4 -4
  8. package/dist/helpers/open-in-editor.js +23 -87
  9. package/dist/helpers/resolve-editor.d.ts +27 -0
  10. package/dist/helpers/resolve-editor.js +90 -0
  11. package/dist/helpers/resolve-file-inside-project.d.ts +2 -0
  12. package/dist/helpers/resolve-file-inside-project.js +5 -2
  13. package/dist/index.d.ts +17 -1
  14. package/dist/index.js +9 -1
  15. package/dist/preview-server/api-routes.js +6 -1
  16. package/dist/preview-server/api-types.d.ts +2 -1
  17. package/dist/preview-server/element-install-state.d.ts +9 -2
  18. package/dist/preview-server/element-install-state.js +15 -5
  19. package/dist/preview-server/handler.d.ts +3 -1
  20. package/dist/preview-server/handler.js +2 -1
  21. package/dist/preview-server/routes/can-update-sequence-props.js +2 -1
  22. package/dist/preview-server/routes/default-editor.d.ts +8 -0
  23. package/dist/preview-server/routes/default-editor.js +131 -0
  24. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +3 -0
  25. package/dist/preview-server/routes/delete-effect-keyframe.js +89 -0
  26. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +3 -0
  27. package/dist/preview-server/routes/delete-sequence-keyframe.js +82 -0
  28. package/dist/preview-server/routes/element-install-plan.d.ts +33 -0
  29. package/dist/preview-server/routes/element-install-plan.js +122 -0
  30. package/dist/preview-server/routes/insert-element.d.ts +1 -1
  31. package/dist/preview-server/routes/insert-element.js +70 -107
  32. package/dist/preview-server/routes/install-dependency.d.ts +2 -1
  33. package/dist/preview-server/routes/install-dependency.js +33 -44
  34. package/dist/preview-server/routes/open-in-editor.d.ts +5 -1
  35. package/dist/preview-server/routes/open-in-editor.js +42 -12
  36. package/dist/preview-server/routes/prepare-element-install.d.ts +3 -0
  37. package/dist/preview-server/routes/prepare-element-install.js +25 -0
  38. package/dist/preview-server/routes/safe-element-install-path.d.ts +9 -0
  39. package/dist/preview-server/routes/safe-element-install-path.js +58 -0
  40. package/dist/preview-server/routes/save-props-mutex.d.ts +1 -0
  41. package/dist/preview-server/routes/save-props-mutex.js +11 -0
  42. package/dist/preview-server/routes/update-public-license.d.ts +4 -0
  43. package/dist/preview-server/routes/update-public-license.js +9 -5
  44. package/dist/preview-server/start-server.d.ts +2 -0
  45. package/dist/preview-server/start-server.js +1 -0
  46. package/dist/preview-server/studio-protocol/handle-discovery.js +57 -26
  47. package/dist/preview-server/studio-protocol/handle-install.js +13 -3
  48. package/dist/preview-server/studio-protocol/handle-license-key.d.ts +6 -0
  49. package/dist/preview-server/studio-protocol/handle-license-key.js +129 -0
  50. package/dist/preview-server/studio-protocol/origin-policy.d.ts +6 -3
  51. package/dist/preview-server/studio-protocol/origin-policy.js +43 -17
  52. package/dist/preview-server/update-available.d.ts +6 -0
  53. package/dist/preview-server/update-available.js +30 -4
  54. package/dist/remotion-skill-names.d.ts +2 -0
  55. package/dist/remotion-skill-names.js +16 -0
  56. package/dist/routes.d.ts +3 -1
  57. package/dist/routes.js +16 -5
  58. package/dist/start-studio.d.ts +3 -1
  59. package/dist/start-studio.js +2 -1
  60. package/package.json +8 -8
@@ -0,0 +1,27 @@
1
+ import type { BuiltInEditor, CustomEditor, DefaultEditor } from '@remotion/renderer';
2
+ import { type ResolvedCustomEditorExecutable } from './custom-editor';
3
+ import type { InstalledEditor } from './editor-registry';
4
+ import type { ProcessAndCommand } from './open-in-editor';
5
+ export type ResolvedEditor = (ProcessAndCommand & {
6
+ type: 'built-in';
7
+ id: BuiltInEditor | null;
8
+ name: string;
9
+ }) | (ResolvedCustomEditorExecutable & {
10
+ type: 'custom';
11
+ id: 'custom';
12
+ name: string;
13
+ editor: CustomEditor;
14
+ });
15
+ type ResolveEditorDependencies = {
16
+ getInstalledEditors: () => Promise<readonly InstalledEditor[]>;
17
+ getLegacyEditors: () => Promise<readonly ProcessAndCommand[]>;
18
+ resolveCustomEditor: (editor: CustomEditor) => ResolvedCustomEditorExecutable | null;
19
+ warn: (message: string) => void;
20
+ warnedEditors: Set<string>;
21
+ };
22
+ export declare const resolveEditor: ({ defaultEditor, logLevel, preferredEditor, }: {
23
+ defaultEditor: DefaultEditor | null;
24
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
25
+ preferredEditor: "cursor" | "custom" | "sublime-text" | "vscode" | "vscodium" | "webstorm" | "windsurf" | "zed" | null;
26
+ }, overrides?: Partial<ResolveEditorDependencies>) => Promise<ResolvedEditor | null>;
27
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveEditor = void 0;
4
+ const renderer_1 = require("@remotion/renderer");
5
+ const custom_editor_1 = require("./custom-editor");
6
+ const editor_registry_1 = require("./editor-registry");
7
+ const open_in_editor_1 = require("./open-in-editor");
8
+ let legacyEditors = null;
9
+ const getLegacyEditors = () => {
10
+ legacyEditors !== null && legacyEditors !== void 0 ? legacyEditors : (legacyEditors = (0, open_in_editor_1.guessEditor)());
11
+ return legacyEditors;
12
+ };
13
+ const warnedEditors = new Set();
14
+ const defaultDependencies = {
15
+ getInstalledEditors: editor_registry_1.getAvailableEditors,
16
+ getLegacyEditors,
17
+ resolveCustomEditor: custom_editor_1.resolveCustomEditorExecutable,
18
+ warn: () => undefined,
19
+ warnedEditors,
20
+ };
21
+ const resolveEditor = async ({ defaultEditor, logLevel, preferredEditor, }, overrides = {}) => {
22
+ var _a;
23
+ const dependencies = {
24
+ ...defaultDependencies,
25
+ warn: (message) => {
26
+ renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, message);
27
+ },
28
+ ...overrides,
29
+ };
30
+ if (preferredEditor === 'custom') {
31
+ if (!defaultEditor || typeof defaultEditor !== 'object') {
32
+ return null;
33
+ }
34
+ const resolvedExecutable = dependencies.resolveCustomEditor(defaultEditor);
35
+ if (!resolvedExecutable) {
36
+ return null;
37
+ }
38
+ return {
39
+ ...resolvedExecutable,
40
+ type: 'custom',
41
+ id: 'custom',
42
+ name: defaultEditor.name,
43
+ editor: defaultEditor,
44
+ };
45
+ }
46
+ if (preferredEditor !== null) {
47
+ const installedEditors = await dependencies.getInstalledEditors();
48
+ const installedEditor = installedEditors.find((editor) => editor.id === preferredEditor);
49
+ return installedEditor ? { ...installedEditor, type: 'built-in' } : null;
50
+ }
51
+ if (defaultEditor && typeof defaultEditor === 'object') {
52
+ const resolvedExecutable = dependencies.resolveCustomEditor(defaultEditor);
53
+ if (resolvedExecutable) {
54
+ return {
55
+ ...resolvedExecutable,
56
+ type: 'custom',
57
+ id: 'custom',
58
+ name: defaultEditor.name,
59
+ editor: defaultEditor,
60
+ };
61
+ }
62
+ const warningId = `custom:${defaultEditor.executable}`;
63
+ if (!dependencies.warnedEditors.has(warningId)) {
64
+ dependencies.warnedEditors.add(warningId);
65
+ dependencies.warn(`The executable for custom editor ${defaultEditor.name} (${defaultEditor.executable}) was not found or is not executable. Falling back to automatic editor detection.`);
66
+ }
67
+ }
68
+ if (typeof defaultEditor === 'string') {
69
+ const installedEditors = await dependencies.getInstalledEditors();
70
+ const installedEditor = installedEditors.find((editor) => editor.id === defaultEditor);
71
+ if (installedEditor) {
72
+ return { ...installedEditor, type: 'built-in' };
73
+ }
74
+ if (!dependencies.warnedEditors.has(defaultEditor)) {
75
+ dependencies.warnedEditors.add(defaultEditor);
76
+ dependencies.warn(`The default editor ${(0, editor_registry_1.getDefaultEditorName)(defaultEditor)} (${defaultEditor}) is not installed. Falling back to automatic editor detection.`);
77
+ }
78
+ }
79
+ const [legacyEditor] = await dependencies.getLegacyEditors();
80
+ if (!legacyEditor) {
81
+ return null;
82
+ }
83
+ return {
84
+ ...legacyEditor,
85
+ type: 'built-in',
86
+ id: null,
87
+ name: (_a = (0, open_in_editor_1.getDisplayNameForEditor)(legacyEditor.command)) !== null && _a !== void 0 ? _a : legacyEditor.command,
88
+ };
89
+ };
90
+ exports.resolveEditor = resolveEditor;
@@ -1,3 +1,5 @@
1
+ export declare class FileOutsideProjectError extends Error {
2
+ }
1
3
  export declare const resolveFileInsideProject: ({ remotionRoot, fileName, action, }: {
2
4
  remotionRoot: string;
3
5
  fileName: string;
@@ -3,9 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.resolveFileInsideProject = void 0;
6
+ exports.resolveFileInsideProject = exports.FileOutsideProjectError = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
8
  const formatOutsideProjectError = ({ action, fileName, absolutePath, remotionRoot, }) => `Cannot ${action} a file outside the project: "${fileName}" resolves to "${absolutePath}", but the project root is "${remotionRoot}".`;
9
+ class FileOutsideProjectError extends Error {
10
+ }
11
+ exports.FileOutsideProjectError = FileOutsideProjectError;
9
12
  const resolveFileInsideProject = ({ remotionRoot, fileName, action, }) => {
10
13
  const resolvedRemotionRoot = node_path_1.default.resolve(remotionRoot);
11
14
  const absolutePath = node_path_1.default.resolve(resolvedRemotionRoot, fileName);
@@ -13,7 +16,7 @@ const resolveFileInsideProject = ({ remotionRoot, fileName, action, }) => {
13
16
  if (fileRelativeToRoot === '..' ||
14
17
  fileRelativeToRoot.startsWith(`..${node_path_1.default.sep}`) ||
15
18
  node_path_1.default.isAbsolute(fileRelativeToRoot)) {
16
- throw new Error(formatOutsideProjectError({
19
+ throw new FileOutsideProjectError(formatOutsideProjectError({
17
20
  action,
18
21
  fileName,
19
22
  absolutePath,
package/dist/index.d.ts CHANGED
@@ -1,8 +1,13 @@
1
1
  export { ApiRoutes, CopyStillToClipboardRequest, getDefaultOutLocation, OpenInFileExplorerRequest, } from '@remotion/studio-shared';
2
2
  export type { AggregateRenderProgress, BundlingState, CopyingState, DownloadProgress, HotMiddlewareOptions, JobProgressCallback, ModuleMap, PackageManager, ProjectInfo, RenderingProgressInput, RenderJob, RenderJobWithCleanup, RequiredChromiumOptions, StitchingProgressInput, UiOpenGlOptions, } from '@remotion/studio-shared';
3
3
  import { AnsiDiff } from './ansi-diff';
4
+ import { detectOutdatedRemotionSkills, parseRemotionSkillVersion } from './detect-outdated-remotion-skills';
5
+ import { remotionSkillNames } from './remotion-skill-names';
6
+ export type { RemotionSkillsScope, RemotionSkillsStatus, } from './detect-outdated-remotion-skills';
7
+ export type { RemotionSkillName } from './remotion-skill-names';
8
+ export { detectOutdatedRemotionSkills, parseRemotionSkillVersion, remotionSkillNames, };
4
9
  export declare const StudioServerInternals: {
5
- startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, remotionRoot, relativePublicDir, bundlerOverride, rspackOverride, webpackOverride, poll, getRenderDefaults, getRenderQueue, getNumberOfAudioTags, queueMethods, previewEntry, gitSource, binariesDirectory, forceIPv4, getAudioLatencyHint, getPreviewSampleRate, enableCrossSiteIsolation, forceNew, rspack, getStudioRuntimeConfig, configFile, }: {
10
+ startStudio: ({ browserArgs, browserFlag, shouldOpenBrowser, fullEntryPath, logLevel, getCurrentInputProps, getEnvVariables, desiredPort, remotionRoot, relativePublicDir, bundlerOverride, rspackOverride, webpackOverride, poll, getRenderDefaults, getRenderQueue, getNumberOfAudioTags, queueMethods, previewEntry, gitSource, binariesDirectory, forceIPv4, getAudioLatencyHint, getPreviewSampleRate, enableCrossSiteIsolation, forceNew, rspack, getStudioRuntimeConfig, getDefaultEditor, configFile, }: {
6
11
  browserArgs: string;
7
12
  browserFlag: string;
8
13
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
@@ -31,6 +36,7 @@ export declare const StudioServerInternals: {
31
36
  forceNew: boolean;
32
37
  rspack: boolean;
33
38
  getStudioRuntimeConfig: () => import("@remotion/studio-shared").StudioRuntimeConfig;
39
+ getDefaultEditor: () => import("@remotion/renderer").DefaultEditor | null;
34
40
  configFile: string | null;
35
41
  }) => Promise<import("./start-studio").StartStudioResult>;
36
42
  getRemotionVersion: () => any;
@@ -120,4 +126,14 @@ export declare const StudioServerInternals: {
120
126
  }) => void;
121
127
  getCompletedClientRenders: () => import("@remotion/studio-shared").CompletedClientRender[];
122
128
  removeCompletedClientRender: (id: string) => void;
129
+ detectOutdatedRemotionSkills: ({ currentVersion, cwd, homeDirectory, }?: {
130
+ currentVersion?: string | undefined;
131
+ cwd?: string | undefined;
132
+ homeDirectory?: string | undefined;
133
+ }) => {
134
+ project: import("./detect-outdated-remotion-skills").RemotionSkillsStatus;
135
+ global: import("./detect-outdated-remotion-skills").RemotionSkillsStatus;
136
+ };
137
+ parseRemotionSkillVersion: (contents: string) => string | null;
138
+ remotionSkillNames: readonly ["remotion-best-practices", "remotion-captions", "remotion-create", "remotion-docs", "remotion-interactivity", "remotion-maps", "remotion-markup", "remotion-multimedia", "remotion-render", "remotion-saas", "remotion-upgrade"];
123
139
  };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StudioServerInternals = exports.getDefaultOutLocation = void 0;
3
+ exports.StudioServerInternals = exports.remotionSkillNames = exports.parseRemotionSkillVersion = exports.detectOutdatedRemotionSkills = exports.getDefaultOutLocation = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const studio_shared_2 = require("@remotion/studio-shared");
6
6
  Object.defineProperty(exports, "getDefaultOutLocation", { enumerable: true, get: function () { return studio_shared_2.getDefaultOutLocation; } });
@@ -9,6 +9,9 @@ const client_render_queue_1 = require("./client-render-queue");
9
9
  const apply_codemod_to_file_1 = require("./codemods/apply-codemod-to-file");
10
10
  const duplicate_composition_1 = require("./codemods/duplicate-composition");
11
11
  const update_default_props_1 = require("./codemods/update-default-props");
12
+ const detect_outdated_remotion_skills_1 = require("./detect-outdated-remotion-skills");
13
+ Object.defineProperty(exports, "detectOutdatedRemotionSkills", { enumerable: true, get: function () { return detect_outdated_remotion_skills_1.detectOutdatedRemotionSkills; } });
14
+ Object.defineProperty(exports, "parseRemotionSkillVersion", { enumerable: true, get: function () { return detect_outdated_remotion_skills_1.parseRemotionSkillVersion; } });
12
15
  const file_watcher_1 = require("./file-watcher");
13
16
  const get_latest_remotion_version_1 = require("./get-latest-remotion-version");
14
17
  const get_installed_dependencies_1 = require("./helpers/get-installed-dependencies");
@@ -18,6 +21,8 @@ const max_timeline_tracks_1 = require("./max-timeline-tracks");
18
21
  const get_package_manager_1 = require("./preview-server/get-package-manager");
19
22
  const live_events_1 = require("./preview-server/live-events");
20
23
  const update_available_1 = require("./preview-server/update-available");
24
+ const remotion_skill_names_1 = require("./remotion-skill-names");
25
+ Object.defineProperty(exports, "remotionSkillNames", { enumerable: true, get: function () { return remotion_skill_names_1.remotionSkillNames; } });
21
26
  const start_studio_1 = require("./start-studio");
22
27
  exports.StudioServerInternals = {
23
28
  startStudio: start_studio_1.startStudio,
@@ -46,4 +51,7 @@ exports.StudioServerInternals = {
46
51
  addCompletedClientRender: client_render_queue_1.addCompletedClientRender,
47
52
  getCompletedClientRenders: client_render_queue_1.getCompletedClientRenders,
48
53
  removeCompletedClientRender: client_render_queue_1.removeCompletedClientRender,
54
+ detectOutdatedRemotionSkills: detect_outdated_remotion_skills_1.detectOutdatedRemotionSkills,
55
+ parseRemotionSkillVersion: detect_outdated_remotion_skills_1.parseRemotionSkillVersion,
56
+ remotionSkillNames: remotion_skill_names_1.remotionSkillNames,
49
57
  };
@@ -12,6 +12,7 @@ const batch_update_keyframe_settings_1 = require("./routes/batch-update-keyframe
12
12
  const cancel_render_1 = require("./routes/cancel-render");
13
13
  const composition_component_info_1 = require("./routes/composition-component-info");
14
14
  const convert_figma_clipboard_to_svg_1 = require("./routes/convert-figma-clipboard-to-svg");
15
+ const default_editor_1 = require("./routes/default-editor");
15
16
  const delete_effect_1 = require("./routes/delete-effect");
16
17
  const delete_jsx_node_1 = require("./routes/delete-jsx-node");
17
18
  const delete_keyframes_1 = require("./routes/delete-keyframes");
@@ -28,6 +29,7 @@ const move_keyframes_1 = require("./routes/move-keyframes");
28
29
  const open_in_editor_1 = require("./routes/open-in-editor");
29
30
  const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
30
31
  const paste_effects_1 = require("./routes/paste-effects");
32
+ const prepare_element_install_1 = require("./routes/prepare-element-install");
31
33
  const project_info_1 = require("./routes/project-info");
32
34
  const redo_1 = require("./routes/redo");
33
35
  const register_client_render_1 = require("./routes/register-client-render");
@@ -62,9 +64,9 @@ exports.allApiRoutes = {
62
64
  '/api/unsubscribe-from-file-existence': unsubscribe_from_file_existence_1.unsubscribeFromFileExistence,
63
65
  '/api/subscribe-to-file-existence': subscribe_to_file_existence_1.subscribeToFileExistence,
64
66
  '/api/remove-render': remove_render_1.handleRemoveRender,
65
- '/api/open-in-editor': open_in_editor_1.openInEditorHandler,
66
67
  '/api/find-in-file': find_in_file_1.findInFileHandler,
67
68
  '/api/open-in-file-explorer': open_in_file_explorer_1.handleOpenInFileExplorer,
69
+ '/api/open-in-editor': open_in_editor_1.openInEditorHandler,
68
70
  '/api/register-client-render': register_client_render_1.registerClientRenderHandler,
69
71
  '/api/unregister-client-render': unregister_client_render_1.unregisterClientRenderHandler,
70
72
  '/api/update-default-props': update_default_props_1.updateDefaultPropsHandler,
@@ -100,9 +102,12 @@ exports.allApiRoutes = {
100
102
  '/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
101
103
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
102
104
  '/api/update-public-license': update_public_license_1.updatePublicLicenseHandler,
105
+ '/api/default-editor-info': default_editor_1.getDefaultEditorInfoHandler,
106
+ '/api/update-default-editor': default_editor_1.updateDefaultEditorHandler,
103
107
  '/api/install-package': install_dependency_1.handleInstallPackage,
104
108
  '/api/insert-jsx-element': insert_jsx_element_1.insertJsxElementHandler,
105
109
  '/api/insert-element': insert_element_1.insertElementHandler,
110
+ '/api/prepare-element-install': prepare_element_install_1.prepareElementInstallHandler,
106
111
  '/api/update-element-install-target': update_element_install_target_1.updateElementInstallTargetHandler,
107
112
  '/api/download-remote-asset': download_remote_asset_1.downloadRemoteAssetHandler,
108
113
  '/api/undo': undo_1.undoHandler,
@@ -1,5 +1,5 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import type { LogLevel } from '@remotion/renderer';
2
+ import type { DefaultEditor, LogLevel } from '@remotion/renderer';
3
3
  import type { RenderJobWithCleanup } from '@remotion/studio-shared';
4
4
  export type QueueMethods = {
5
5
  removeJob: (jobId: string) => void;
@@ -22,4 +22,5 @@ export type ApiHandler<ReqData, ResData> = (params: {
22
22
  publicDir: string;
23
23
  binariesDirectory: string | null;
24
24
  configFile: string | null;
25
+ getDefaultEditor: () => DefaultEditor | null;
25
26
  }) => Promise<ResData>;
@@ -11,20 +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;
17
+ readonly origin: string;
18
+ readonly purpose: StudioProtocolTargetPurpose;
16
19
  readonly target: ElementInstallTarget;
17
20
  readonly expiresAt: number;
18
21
  };
19
22
  export declare const updateElementInstallTarget: (newTarget: Omit<ElementInstallTarget, "updatedAt">) => void;
20
23
  export declare const getElementInstallTargetByClientId: (clientId: string) => ElementInstallTarget | null;
21
24
  export declare const getElementInstallTarget: (requestId: string | null) => ElementInstallTarget | null;
22
- export declare const issueStudioProtocolTarget: ({ now, target, }: {
25
+ export declare const issueStudioProtocolTarget: ({ now, origin, purpose, target, }: {
23
26
  readonly now: number;
27
+ readonly origin: string;
28
+ readonly purpose: StudioProtocolTargetPurpose;
24
29
  readonly target: ElementInstallTarget;
25
30
  }) => StudioProtocolTarget;
26
- export declare const consumeStudioProtocolTarget: ({ now, targetId, }: {
31
+ export declare const consumeStudioProtocolTarget: ({ now, origin, purpose, targetId, }: {
27
32
  readonly now: number;
33
+ readonly origin: string;
34
+ readonly purpose: StudioProtocolTargetPurpose;
28
35
  readonly targetId: string;
29
36
  }) => ElementInstallTarget | null;
30
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, 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);
@@ -53,6 +53,8 @@ const issueStudioProtocolTarget = ({ now, target, }) => {
53
53
  }
54
54
  const issued = {
55
55
  id: (0, node_crypto_1.randomUUID)(),
56
+ origin,
57
+ purpose,
56
58
  target: { ...target },
57
59
  expiresAt: now + exports.STUDIO_PROTOCOL_TARGET_MAX_AGE,
58
60
  };
@@ -60,17 +62,25 @@ const issueStudioProtocolTarget = ({ now, target, }) => {
60
62
  return issued;
61
63
  };
62
64
  exports.issueStudioProtocolTarget = issueStudioProtocolTarget;
63
- const consumeStudioProtocolTarget = ({ now, targetId, }) => {
65
+ const consumeStudioProtocolTarget = ({ now, origin, purpose, targetId, }) => {
64
66
  const issued = studioProtocolTargets.get(targetId);
65
67
  studioProtocolTargets.delete(targetId);
66
- if (issued === undefined || issued.expiresAt <= now) {
68
+ if (issued === undefined ||
69
+ issued.expiresAt <= now ||
70
+ issued.origin !== origin ||
71
+ issued.purpose !== purpose) {
67
72
  return null;
68
73
  }
69
74
  const current = (0, exports.getElementInstallTargetByClientId)(issued.target.clientId);
70
75
  if (current === null ||
71
76
  now - current.updatedAt >= exports.ELEMENT_INSTALL_TARGET_MAX_AGE ||
72
- !current.canInstall ||
73
- current.readOnly ||
77
+ current.readOnly) {
78
+ return null;
79
+ }
80
+ if (purpose === 'set-license-key') {
81
+ return issued.target;
82
+ }
83
+ if (!current.canInstall ||
74
84
  current.compositionFile !== issued.target.compositionFile ||
75
85
  current.compositionId !== issued.target.compositionId) {
76
86
  return null;
@@ -1,6 +1,7 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { DefaultEditor } from '@remotion/renderer';
2
3
  import type { ApiHandler, QueueMethods } from './api-types';
3
- export declare const handleRequest: <Req, Res>({ remotionRoot, request, response, entryPoint, handler, logLevel, methods, binariesDirectory, publicDir, configFile, }: {
4
+ export declare const handleRequest: <Req, Res>({ remotionRoot, request, response, entryPoint, handler, logLevel, methods, binariesDirectory, publicDir, configFile, getDefaultEditor, }: {
4
5
  remotionRoot: string;
5
6
  publicDir: string;
6
7
  request: IncomingMessage;
@@ -8,6 +9,7 @@ export declare const handleRequest: <Req, Res>({ remotionRoot, request, response
8
9
  entryPoint: string;
9
10
  binariesDirectory: string | null;
10
11
  configFile: string | null;
12
+ getDefaultEditor: () => DefaultEditor | null;
11
13
  handler: ApiHandler<Req, Res>;
12
14
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
13
15
  methods: QueueMethods;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleRequest = void 0;
4
4
  const parse_body_1 = require("./parse-body");
5
5
  const validate_same_origin_1 = require("./validate-same-origin");
6
- const handleRequest = async ({ remotionRoot, request, response, entryPoint, handler, logLevel, methods, binariesDirectory, publicDir, configFile, }) => {
6
+ const handleRequest = async ({ remotionRoot, request, response, entryPoint, handler, logLevel, methods, binariesDirectory, publicDir, configFile, getDefaultEditor, }) => {
7
7
  if (request.method === 'OPTIONS') {
8
8
  response.statusCode = 200;
9
9
  response.end();
@@ -25,6 +25,7 @@ const handleRequest = async ({ remotionRoot, request, response, entryPoint, hand
25
25
  binariesDirectory,
26
26
  publicDir,
27
27
  configFile,
28
+ getDefaultEditor,
28
29
  });
29
30
  response.end(JSON.stringify({
30
31
  success: true,
@@ -1017,7 +1017,8 @@ const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, colu
1017
1017
  };
1018
1018
  }
1019
1019
  catch (err) {
1020
- if (err instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
1020
+ if (err instanceof resolve_file_inside_project_1.FileOutsideProjectError ||
1021
+ err instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
1021
1022
  err instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
1022
1023
  return {
1023
1024
  status: {
@@ -0,0 +1,8 @@
1
+ import type { GetDefaultEditorInfoRequest, GetDefaultEditorInfoResponse, UpdateDefaultEditorRequest, UpdateDefaultEditorResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const updateDefaultEditorInConfig: ({ configContents, defaultEditor, }: {
4
+ configContents: string;
5
+ defaultEditor: "cursor" | "sublime-text" | "vscode" | "vscodium" | "webstorm" | "windsurf" | "zed" | null;
6
+ }) => string;
7
+ export declare const getDefaultEditorInfoHandler: ApiHandler<GetDefaultEditorInfoRequest, GetDefaultEditorInfoResponse>;
8
+ export declare const updateDefaultEditorHandler: ApiHandler<UpdateDefaultEditorRequest, UpdateDefaultEditorResponse>;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.updateDefaultEditorHandler = exports.getDefaultEditorInfoHandler = exports.updateDefaultEditorInConfig = void 0;
37
+ const node_fs_1 = require("node:fs");
38
+ const renderer_1 = require("@remotion/renderer");
39
+ const recast = __importStar(require("recast"));
40
+ const parse_ast_1 = require("../../codemods/parse-ast");
41
+ const file_watcher_1 = require("../../file-watcher");
42
+ const editor_registry_1 = require("../../helpers/editor-registry");
43
+ const updateDefaultEditorInConfig = ({ configContents, defaultEditor, }) => {
44
+ const ast = (0, parse_ast_1.parseAst)(configContents);
45
+ recast.types.visit(ast.program, {
46
+ visitExpressionStatement(path) {
47
+ const { expression } = path.node;
48
+ if (expression.type === 'CallExpression' &&
49
+ expression.callee.type === 'MemberExpression' &&
50
+ !expression.callee.computed &&
51
+ expression.callee.object.type === 'Identifier' &&
52
+ expression.callee.object.name === 'Config' &&
53
+ expression.callee.property.type === 'Identifier' &&
54
+ expression.callee.property.name === 'setDefaultEditor') {
55
+ path.prune();
56
+ return false;
57
+ }
58
+ this.traverse(path);
59
+ },
60
+ });
61
+ const configWithoutExistingCalls = recast.print(ast, {
62
+ lineTerminator: '\n',
63
+ }).code;
64
+ if (defaultEditor === null) {
65
+ return configWithoutExistingCalls;
66
+ }
67
+ const separator = configWithoutExistingCalls.endsWith('\n') ? '' : '\n';
68
+ return `${configWithoutExistingCalls}${separator}Config.setDefaultEditor('${defaultEditor}');\n`;
69
+ };
70
+ exports.updateDefaultEditorInConfig = updateDefaultEditorInConfig;
71
+ const getDefaultEditorInfoHandler = async ({ getDefaultEditor }) => {
72
+ const installedEditors = await (0, editor_registry_1.getAvailableEditors)();
73
+ const configuredEditor = getDefaultEditor();
74
+ const customEditor = configuredEditor && typeof configuredEditor === 'object'
75
+ ? configuredEditor
76
+ : null;
77
+ return {
78
+ defaultEditor: typeof configuredEditor === 'object' ? 'custom' : configuredEditor,
79
+ installedEditors: [
80
+ ...installedEditors.map(({ id, name }) => ({ id, name })),
81
+ ...(customEditor
82
+ ? [{ id: 'custom', name: customEditor.name }]
83
+ : []),
84
+ ],
85
+ };
86
+ };
87
+ exports.getDefaultEditorInfoHandler = getDefaultEditorInfoHandler;
88
+ const updateDefaultEditorHandler = async ({ input, configFile, getDefaultEditor }) => {
89
+ if (configFile === null || configFile === undefined) {
90
+ return {
91
+ success: false,
92
+ reason: 'No Remotion config file was loaded.',
93
+ };
94
+ }
95
+ if (input.defaultEditor === 'custom') {
96
+ const configuredEditor = getDefaultEditor();
97
+ if (!configuredEditor || typeof configuredEditor !== 'object') {
98
+ return {
99
+ success: false,
100
+ reason: 'No custom editor is configured.',
101
+ };
102
+ }
103
+ // The browser only knows the opaque "custom" ID. Keeping the existing
104
+ // config call untouched avoids exposing or rewriting its executable and
105
+ // arguments, which may have come from environment variables.
106
+ return { success: true };
107
+ }
108
+ if (input.defaultEditor !== null &&
109
+ !renderer_1.defaultEditorIds.includes(input.defaultEditor)) {
110
+ return {
111
+ success: false,
112
+ reason: `Unknown editor: ${input.defaultEditor}`,
113
+ };
114
+ }
115
+ if (input.defaultEditor !== null) {
116
+ const installedEditors = await (0, editor_registry_1.getAvailableEditors)();
117
+ if (!installedEditors.some(({ id }) => id === input.defaultEditor)) {
118
+ return {
119
+ success: false,
120
+ reason: 'The selected editor is not installed.',
121
+ };
122
+ }
123
+ }
124
+ const configContents = (0, node_fs_1.readFileSync)(configFile, 'utf8');
125
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(configFile, (0, exports.updateDefaultEditorInConfig)({
126
+ configContents,
127
+ defaultEditor: input.defaultEditor,
128
+ }), undefined);
129
+ return { success: true };
130
+ };
131
+ exports.updateDefaultEditorHandler = updateDefaultEditorHandler;
@@ -0,0 +1,3 @@
1
+ import type { DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteEffectKeyframeHandler: ApiHandler<DeleteEffectKeyframeRequest, DeleteEffectKeyframeResponse>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteEffectKeyframeHandler = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const renderer_1 = require("@remotion/renderer");
6
+ const studio_shared_1 = require("@remotion/studio-shared");
7
+ const parse_ast_1 = require("../../codemods/parse-ast");
8
+ const update_keyframes_1 = require("../../codemods/update-keyframes/update-keyframes");
9
+ const file_watcher_1 = require("../../file-watcher");
10
+ const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
11
+ const undo_stack_1 = require("../undo-stack");
12
+ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
+ const can_update_effect_props_1 = require("./can-update-effect-props");
14
+ const can_update_sequence_props_1 = require("./can-update-sequence-props");
15
+ const log_effect_update_1 = require("./log-updates/log-effect-update");
16
+ const save_props_mutex_1 = require("./save-props-mutex");
17
+ const deleteEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
18
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-effect-keyframe] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}" frame=${frame}`);
19
+ const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
+ remotionRoot,
21
+ fileName,
22
+ action: 'modify',
23
+ });
24
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
+ const { output, oldValueStrings, newValueStrings, formatted, logLine, effectCallee, } = await (0, update_keyframes_1.updateEffectKeyframes)({
26
+ input: fileContents,
27
+ sequenceNodePath: sequenceNodePath.nodePath,
28
+ effectIndex,
29
+ updates: [
30
+ {
31
+ key,
32
+ operation: {
33
+ type: 'remove',
34
+ frame,
35
+ },
36
+ },
37
+ ],
38
+ });
39
+ const oldValueString = oldValueStrings[0];
40
+ const newValueString = newValueStrings[0];
41
+ const undoPropChange = `${key} keyframe restored at frame ${frame}`;
42
+ const redoPropChange = `${key} keyframe deleted at frame ${frame}`;
43
+ (0, undo_stack_1.pushToUndoStack)({
44
+ filePath: absolutePath,
45
+ oldContents: fileContents,
46
+ newContents: null,
47
+ logLevel,
48
+ remotionRoot,
49
+ logLine,
50
+ description: {
51
+ undoMessage: `↩️ ${undoPropChange}`,
52
+ redoMessage: `↪️ ${redoPropChange}`,
53
+ },
54
+ entryType: 'effect-props',
55
+ suppressHmrOnFileRestore: true,
56
+ });
57
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
58
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
59
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
60
+ (0, log_effect_update_1.logEffectUpdate)({
61
+ fileRelativeToRoot,
62
+ line: logLine,
63
+ effectName: effectCallee,
64
+ propKey: key,
65
+ oldValueString,
66
+ newValueString,
67
+ defaultValueString: null,
68
+ formatted,
69
+ logLevel,
70
+ removedProps: [],
71
+ addedProps: [],
72
+ });
73
+ (0, undo_stack_1.printUndoHint)(logLevel);
74
+ const ast = (0, parse_ast_1.parseAst)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
75
+ const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath.nodePath);
76
+ if (!jsx) {
77
+ return {
78
+ canUpdate: false,
79
+ effectIndex,
80
+ reason: 'not-found',
81
+ };
82
+ }
83
+ return (0, can_update_effect_props_1.computeEffectPropStatus)({
84
+ jsx,
85
+ effectIndex,
86
+ keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
87
+ });
88
+ });
89
+ exports.deleteEffectKeyframeHandler = deleteEffectKeyframeHandler;
@@ -0,0 +1,3 @@
1
+ import type { DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteSequenceKeyframeHandler: ApiHandler<DeleteSequenceKeyframeRequest, DeleteSequenceKeyframeResponse>;