@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,25 @@
1
+ import type { RemotionSkillName } from './remotion-skill-names';
2
+ export type RemotionSkillsScope = 'project' | 'global';
3
+ export type RemotionSkillsStatus = {
4
+ type: 'not-installed';
5
+ scope: RemotionSkillsScope;
6
+ skillsDirectory: string;
7
+ } | {
8
+ type: 'up-to-date';
9
+ scope: RemotionSkillsScope;
10
+ skillsDirectory: string;
11
+ } | {
12
+ type: 'outdated';
13
+ scope: RemotionSkillsScope;
14
+ skillsDirectory: string;
15
+ outdatedSkillNames: RemotionSkillName[];
16
+ };
17
+ export declare const parseRemotionSkillVersion: (contents: string) => string | null;
18
+ export declare const detectOutdatedRemotionSkills: ({ currentVersion, cwd, homeDirectory, }?: {
19
+ currentVersion?: string | undefined;
20
+ cwd?: string | undefined;
21
+ homeDirectory?: string | undefined;
22
+ }) => {
23
+ project: RemotionSkillsStatus;
24
+ global: RemotionSkillsStatus;
25
+ };
@@ -0,0 +1,73 @@
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.detectOutdatedRemotionSkills = exports.parseRemotionSkillVersion = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const version_1 = require("remotion/version");
11
+ const semver_1 = __importDefault(require("semver"));
12
+ const remotion_skill_names_1 = require("./remotion-skill-names");
13
+ const parseRemotionSkillVersion = (contents) => {
14
+ var _a, _b, _c, _d;
15
+ var _e;
16
+ const frontmatter = (_b = (_a = contents.match(/^---\r?\n(?<frontmatter>[\s\S]*?)\r?\n---(?:\r?\n|$)/)) === null || _a === void 0 ? void 0 : _a.groups) === null || _b === void 0 ? void 0 : _b.frontmatter;
17
+ if (!frontmatter) {
18
+ return null;
19
+ }
20
+ return ((_e = (_d = (_c = frontmatter.match(/^version:\s*(?<quote>['"]?)(?<version>[^\s'"]+)\k<quote>\s*$/m)) === null || _c === void 0 ? void 0 : _c.groups) === null || _d === void 0 ? void 0 : _d.version) !== null && _e !== void 0 ? _e : null);
21
+ };
22
+ exports.parseRemotionSkillVersion = parseRemotionSkillVersion;
23
+ const readRemotionSkill = (skillFile) => {
24
+ if (!(0, node_fs_1.existsSync)(skillFile)) {
25
+ return { installed: false, version: null };
26
+ }
27
+ try {
28
+ return {
29
+ installed: true,
30
+ version: (0, exports.parseRemotionSkillVersion)((0, node_fs_1.readFileSync)(skillFile, 'utf8')),
31
+ };
32
+ }
33
+ catch (_a) {
34
+ return { installed: true, version: null };
35
+ }
36
+ };
37
+ const getStatusForSkillsDirectory = ({ currentVersion, scope, skillsDirectory, }) => {
38
+ const installedSkills = new Map();
39
+ for (const skillName of remotion_skill_names_1.remotionSkillNames) {
40
+ installedSkills.set(skillName, readRemotionSkill(node_path_1.default.join(skillsDirectory, skillName, 'SKILL.md')));
41
+ }
42
+ if ([...installedSkills.values()].every((skill) => !skill.installed)) {
43
+ return { type: 'not-installed', scope, skillsDirectory };
44
+ }
45
+ const outdatedSkillNames = remotion_skill_names_1.remotionSkillNames.filter((skillName) => {
46
+ const skill = installedSkills.get(skillName);
47
+ return (!(skill === null || skill === void 0 ? void 0 : skill.installed) ||
48
+ skill.version === null ||
49
+ semver_1.default.valid(skill.version) === null ||
50
+ semver_1.default.lt(skill.version, currentVersion));
51
+ });
52
+ if (outdatedSkillNames.length > 0) {
53
+ return { type: 'outdated', scope, skillsDirectory, outdatedSkillNames };
54
+ }
55
+ return { type: 'up-to-date', scope, skillsDirectory };
56
+ };
57
+ const detectOutdatedRemotionSkills = ({ currentVersion = version_1.VERSION, cwd = process.cwd(), homeDirectory = (0, node_os_1.homedir)(), } = {}) => {
58
+ const projectSkillsDirectory = node_path_1.default.join(cwd, '.agents', 'skills');
59
+ const globalSkillsDirectory = node_path_1.default.join(homeDirectory, '.agents', 'skills');
60
+ return {
61
+ project: getStatusForSkillsDirectory({
62
+ currentVersion,
63
+ scope: 'project',
64
+ skillsDirectory: projectSkillsDirectory,
65
+ }),
66
+ global: getStatusForSkillsDirectory({
67
+ currentVersion,
68
+ scope: 'global',
69
+ skillsDirectory: globalSkillsDirectory,
70
+ }),
71
+ };
72
+ };
73
+ exports.detectOutdatedRemotionSkills = detectOutdatedRemotionSkills;
@@ -0,0 +1,37 @@
1
+ import { spawn } from 'node:child_process';
2
+ import type { CustomEditor } from '@remotion/renderer';
3
+ type CustomEditorPathType = 'file' | 'directory' | 'symbolic-link' | null;
4
+ export type CustomEditorResolutionContext = {
5
+ platform: NodeJS.Platform;
6
+ env: NodeJS.ProcessEnv;
7
+ currentWorkingDirectory: string;
8
+ inspectPath: (filePath: string) => CustomEditorPathType;
9
+ canExecute: (filePath: string) => boolean;
10
+ };
11
+ export type ResolvedCustomEditorExecutable = {
12
+ executable: string;
13
+ spawnAsMacApplication: boolean;
14
+ };
15
+ export declare const resolveCustomEditorExecutable: (editor: CustomEditor, context?: CustomEditorResolutionContext) => ResolvedCustomEditorExecutable | null;
16
+ export declare const normalizeCustomEditorTargetPath: ({ targetPath, platform, release, currentWorkingDirectory, }: {
17
+ targetPath: string;
18
+ platform: NodeJS.Platform;
19
+ release: string;
20
+ currentWorkingDirectory: string;
21
+ }) => string;
22
+ export declare const expandCustomEditorArguments: ({ argumentTemplates, targetPath, lineNumber, columnNumber, }: {
23
+ argumentTemplates: readonly string[];
24
+ targetPath: string;
25
+ lineNumber: number;
26
+ columnNumber: number;
27
+ }) => string[];
28
+ export declare const launchCustomEditor: ({ editor, resolvedExecutable, targetPath, lineNumber, columnNumber, logLevel, spawnProcess, }: {
29
+ editor: CustomEditor;
30
+ resolvedExecutable: ResolvedCustomEditorExecutable;
31
+ targetPath: string;
32
+ lineNumber: number;
33
+ columnNumber: number;
34
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
35
+ spawnProcess: typeof spawn | null;
36
+ }) => Promise<boolean>;
37
+ export {};
@@ -0,0 +1,167 @@
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.launchCustomEditor = exports.expandCustomEditorArguments = exports.normalizeCustomEditorTargetPath = exports.resolveCustomEditorExecutable = void 0;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_fs_1 = require("node:fs");
9
+ const node_os_1 = __importDefault(require("node:os"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const renderer_1 = require("@remotion/renderer");
12
+ const defaultResolutionContext = {
13
+ platform: process.platform,
14
+ env: process.env,
15
+ currentWorkingDirectory: process.cwd(),
16
+ inspectPath: (filePath) => {
17
+ try {
18
+ const stat = (0, node_fs_1.lstatSync)(filePath);
19
+ if (stat.isSymbolicLink()) {
20
+ return 'symbolic-link';
21
+ }
22
+ if (stat.isFile()) {
23
+ return 'file';
24
+ }
25
+ return stat.isDirectory() ? 'directory' : null;
26
+ }
27
+ catch (_a) {
28
+ return null;
29
+ }
30
+ },
31
+ canExecute: (filePath) => {
32
+ try {
33
+ (0, node_fs_1.accessSync)(filePath, node_fs_1.constants.X_OK);
34
+ return true;
35
+ }
36
+ catch (_a) {
37
+ return false;
38
+ }
39
+ },
40
+ };
41
+ const getExecutableCandidates = ({ executable, context, }) => {
42
+ var _a, _b;
43
+ const pathApi = context.platform === 'win32' ? node_path_1.default.win32 : node_path_1.default.posix;
44
+ const hasDirectory = pathApi.isAbsolute(executable) ||
45
+ executable.includes('/') ||
46
+ executable.includes('\\');
47
+ if (hasDirectory) {
48
+ return [
49
+ pathApi.isAbsolute(executable)
50
+ ? executable
51
+ : pathApi.resolve(context.currentWorkingDirectory, executable),
52
+ ];
53
+ }
54
+ const pathDirectories = ((_a = context.env.PATH) !== null && _a !== void 0 ? _a : '')
55
+ .split(context.platform === 'win32' ? ';' : ':')
56
+ .filter(Boolean);
57
+ if (context.platform !== 'win32') {
58
+ return pathDirectories.map((directory) => pathApi.join(directory, executable));
59
+ }
60
+ const currentExtension = node_path_1.default.win32.extname(executable).toLowerCase();
61
+ const extensions = currentExtension
62
+ ? ['']
63
+ : ((_b = context.env.PATHEXT) !== null && _b !== void 0 ? _b : '.COM;.EXE')
64
+ .split(';')
65
+ .map((extension) => extension.toLowerCase())
66
+ .filter((extension) => extension === '.com' || extension === '.exe');
67
+ return pathDirectories.flatMap((directory) => extensions.map((extension) => pathApi.join(directory, `${executable}${extension}`)));
68
+ };
69
+ const resolveCustomEditorExecutable = (editor, context = defaultResolutionContext) => {
70
+ for (const candidate of getExecutableCandidates({
71
+ executable: editor.executable,
72
+ context,
73
+ })) {
74
+ const pathType = context.inspectPath(candidate);
75
+ if (context.platform === 'darwin' &&
76
+ (pathType === 'directory' || pathType === 'symbolic-link') &&
77
+ candidate.toLowerCase().endsWith('.app')) {
78
+ return { executable: candidate, spawnAsMacApplication: true };
79
+ }
80
+ if (pathType !== 'file' && pathType !== 'symbolic-link') {
81
+ continue;
82
+ }
83
+ if (context.platform === 'win32') {
84
+ const extension = node_path_1.default.win32.extname(candidate).toLowerCase();
85
+ if (extension !== '.exe' && extension !== '.com') {
86
+ continue;
87
+ }
88
+ }
89
+ else if (!context.canExecute(candidate)) {
90
+ continue;
91
+ }
92
+ return { executable: candidate, spawnAsMacApplication: false };
93
+ }
94
+ return null;
95
+ };
96
+ exports.resolveCustomEditorExecutable = resolveCustomEditorExecutable;
97
+ const normalizeCustomEditorTargetPath = ({ targetPath, platform, release, currentWorkingDirectory, }) => {
98
+ if (platform === 'linux' &&
99
+ targetPath.startsWith('/mnt/') &&
100
+ /Microsoft/i.test(release)) {
101
+ return node_path_1.default.posix.relative(currentWorkingDirectory, targetPath);
102
+ }
103
+ return targetPath;
104
+ };
105
+ exports.normalizeCustomEditorTargetPath = normalizeCustomEditorTargetPath;
106
+ const expandCustomEditorArguments = ({ argumentTemplates, targetPath, lineNumber, columnNumber, }) => {
107
+ return argumentTemplates.map((argument) => argument
108
+ .replaceAll(renderer_1.customEditorTargetPathPlaceholder, targetPath)
109
+ .replaceAll(renderer_1.customEditorLineNumberPlaceholder, String(lineNumber))
110
+ .replaceAll(renderer_1.customEditorColumnNumberPlaceholder, String(columnNumber)));
111
+ };
112
+ exports.expandCustomEditorArguments = expandCustomEditorArguments;
113
+ const launchCustomEditor = ({ editor, resolvedExecutable, targetPath, lineNumber, columnNumber, logLevel, spawnProcess, }) => {
114
+ if (!(0, node_fs_1.existsSync)(targetPath) ||
115
+ !Number.isInteger(lineNumber) ||
116
+ lineNumber <= 0) {
117
+ return Promise.resolve(false);
118
+ }
119
+ const safeColumnNumber = Number.isInteger(columnNumber) && columnNumber > 0 ? columnNumber : 1;
120
+ const normalizedTargetPath = (0, exports.normalizeCustomEditorTargetPath)({
121
+ targetPath,
122
+ platform: process.platform,
123
+ release: node_os_1.default.release(),
124
+ currentWorkingDirectory: process.cwd(),
125
+ });
126
+ const editorArguments = (0, exports.expandCustomEditorArguments)({
127
+ argumentTemplates: editor.arguments,
128
+ targetPath: normalizedTargetPath,
129
+ lineNumber,
130
+ columnNumber: safeColumnNumber,
131
+ });
132
+ const command = resolvedExecutable.spawnAsMacApplication
133
+ ? 'open'
134
+ : resolvedExecutable.executable;
135
+ const args = resolvedExecutable.spawnAsMacApplication
136
+ ? ['-a', resolvedExecutable.executable, ...editorArguments]
137
+ : editorArguments;
138
+ return new Promise((resolve) => {
139
+ let child;
140
+ try {
141
+ child = (spawnProcess !== null && spawnProcess !== void 0 ? spawnProcess : node_child_process_1.spawn)(command, args, {
142
+ detached: true,
143
+ shell: false,
144
+ stdio: 'ignore',
145
+ });
146
+ }
147
+ catch (error) {
148
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, `Could not launch custom editor ${editor.name}:`, error);
149
+ resolve(false);
150
+ return;
151
+ }
152
+ child.once('error', (error) => {
153
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, `Could not launch custom editor ${editor.name}:`, error);
154
+ resolve(false);
155
+ });
156
+ child.once('spawn', () => {
157
+ child.unref();
158
+ resolve(true);
159
+ });
160
+ child.on('exit', (exitCode) => {
161
+ if (exitCode) {
162
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, `Custom editor ${editor.name} exited with code ${exitCode}.`);
163
+ }
164
+ });
165
+ });
166
+ };
167
+ exports.launchCustomEditor = launchCustomEditor;
@@ -0,0 +1,18 @@
1
+ import type { BuiltInEditor } from '@remotion/renderer';
2
+ export type InstalledEditor = {
3
+ id: BuiltInEditor;
4
+ name: string;
5
+ process: string;
6
+ command: string;
7
+ };
8
+ export type EditorDiscoveryContext = {
9
+ platform: NodeJS.Platform;
10
+ env: NodeJS.ProcessEnv;
11
+ homeDirectory: string;
12
+ pathExists: (filePath: string) => boolean;
13
+ findMacApplications: (bundleIdentifier: string) => Promise<readonly string[]>;
14
+ findWindowsApplications: (editor: BuiltInEditor) => Promise<readonly string[]>;
15
+ };
16
+ export declare const getDefaultEditorName: (id: "cursor" | "sublime-text" | "vscode" | "vscodium" | "webstorm" | "windsurf" | "zed") => string;
17
+ export declare const discoverAvailableEditors: (context: EditorDiscoveryContext) => Promise<readonly InstalledEditor[]>;
18
+ export declare const getAvailableEditors: () => Promise<readonly InstalledEditor[]>;