@remotion/studio-server 4.0.533 → 4.0.535

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 (68) hide show
  1. package/dist/detect-outdated-remotion-skills.d.ts +4 -0
  2. package/dist/detect-outdated-remotion-skills.js +3 -2
  3. package/dist/file-watcher.js +2 -0
  4. package/dist/helpers/app-discovery.d.ts +9 -0
  5. package/dist/helpers/app-discovery.js +61 -0
  6. package/dist/helpers/coding-agent-registry.d.ts +1 -0
  7. package/dist/helpers/coding-agent-registry.js +22 -1
  8. package/dist/helpers/editor-registry.d.ts +1 -0
  9. package/dist/helpers/editor-registry.js +24 -1
  10. package/dist/helpers/open-in-app.d.ts +13 -0
  11. package/dist/helpers/open-in-app.js +72 -0
  12. package/dist/helpers/open-in-editor.d.ts +1 -1
  13. package/dist/helpers/open-in-editor.js +67 -84
  14. package/dist/helpers/recently-used-apps.d.ts +9 -0
  15. package/dist/helpers/recently-used-apps.js +63 -0
  16. package/dist/helpers/running-processes.d.ts +12 -0
  17. package/dist/helpers/running-processes.js +88 -0
  18. package/dist/helpers/video-config-numeric-expression.js +29 -20
  19. package/dist/helpers/video-config-values.d.ts +6 -3
  20. package/dist/helpers/video-config-values.js +42 -26
  21. package/dist/preview-server/api-routes.js +8 -5
  22. package/dist/preview-server/live-events.d.ts +1 -0
  23. package/dist/preview-server/live-events.js +12 -1
  24. package/dist/preview-server/routes/add-sequence-keyframe.js +0 -1
  25. package/dist/preview-server/routes/app-info.d.ts +3 -0
  26. package/dist/preview-server/routes/app-info.js +16 -0
  27. package/dist/preview-server/routes/can-update-effect-props.d.ts +4 -6
  28. package/dist/preview-server/routes/can-update-effect-props.js +5 -28
  29. package/dist/preview-server/routes/can-update-sequence-props.d.ts +6 -8
  30. package/dist/preview-server/routes/can-update-sequence-props.js +11 -12
  31. package/dist/preview-server/routes/default-coding-agent.d.ts +1 -2
  32. package/dist/preview-server/routes/default-coding-agent.js +11 -19
  33. package/dist/preview-server/routes/default-editor.js +9 -29
  34. package/dist/preview-server/routes/delete-keyframes.d.ts +2 -2
  35. package/dist/preview-server/routes/delete-keyframes.js +0 -1
  36. package/dist/preview-server/routes/element-install-plan.js +5 -0
  37. package/dist/preview-server/routes/insert-basic-captions.js +1 -0
  38. package/dist/preview-server/routes/insert-element.js +63 -20
  39. package/dist/preview-server/routes/install-remotion-skill.d.ts +2 -1
  40. package/dist/preview-server/routes/install-remotion-skill.js +87 -56
  41. package/dist/preview-server/routes/open-in-editor.d.ts +1 -1
  42. package/dist/preview-server/routes/open-in-editor.js +2 -56
  43. package/dist/preview-server/routes/redo.js +2 -1
  44. package/dist/preview-server/routes/remotion-skills-info.d.ts +2 -1
  45. package/dist/preview-server/routes/remotion-skills-info.js +57 -3
  46. package/dist/preview-server/routes/save-sequence-props.js +0 -1
  47. package/dist/preview-server/routes/shared-memory-capture-support.d.ts +3 -0
  48. package/dist/preview-server/routes/shared-memory-capture-support.js +13 -0
  49. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -1
  50. package/dist/preview-server/routes/subscribe-to-sequence-props.js +1 -2
  51. package/dist/preview-server/routes/undo.js +2 -1
  52. package/dist/preview-server/routes/unsubscribe-from-sequence-props.js +0 -1
  53. package/dist/preview-server/routes/update-config.js +12 -5
  54. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +0 -1
  55. package/dist/preview-server/routes/wrap-node.js +13 -4
  56. package/dist/preview-server/sequence-props-watchers.d.ts +3 -5
  57. package/dist/preview-server/sequence-props-watchers.js +9 -17
  58. package/dist/preview-server/studio-protocol/handle-element-library.js +14 -0
  59. package/dist/preview-server/studio-protocol/handle-install.js +2 -1
  60. package/dist/preview-server/undo-stack.js +1 -0
  61. package/dist/preview-server/update-available.js +17 -0
  62. package/dist/preview-server/watch-ignore-next-change.d.ts +1 -0
  63. package/dist/preview-server/watch-ignore-next-change.js +15 -2
  64. package/dist/routes.js +3 -1
  65. package/dist/start-studio.js +13 -6
  66. package/dist/studio-shortcuts.d.ts +13 -0
  67. package/dist/studio-shortcuts.js +257 -0
  68. package/package.json +8 -8
@@ -439,7 +439,7 @@ const getInterpolationKeyframes = (node, ast, videoConfigValues) => {
439
439
  return undefined;
440
440
  }
441
441
  keyframes.push({
442
- frame: frameExpression.value,
442
+ frame: no_react_1.NoReactInternals.evaluateSourceNumericValue(frameExpression, null),
443
443
  value: (0, exports.extractStaticValue)(outputElement),
444
444
  ...(frameExpression.type === 'literal' ? {} : { frameExpression }),
445
445
  });
@@ -521,8 +521,7 @@ const findNodePath = (ast, target) => {
521
521
  return found;
522
522
  };
523
523
  const getJsxNumericAttribute = ({ openingElement, name, defaultValue, videoConfigValues, }) => {
524
- var _a, _b;
525
- var _c;
524
+ var _a;
526
525
  if (openingElement.attributes.some((attribute) => attribute.type === 'JSXSpreadAttribute')) {
527
526
  return null;
528
527
  }
@@ -537,10 +536,13 @@ const getJsxNumericAttribute = ({ openingElement, name, defaultValue, videoConfi
537
536
  attribute.value.expression.type === 'JSXEmptyExpression') {
538
537
  return null;
539
538
  }
540
- return ((_c = (_b = (0, video_config_numeric_expression_1.parseVideoConfigNumericExpression)({
539
+ const numericExpression = (0, video_config_numeric_expression_1.parseVideoConfigNumericExpression)({
541
540
  node: attribute.value.expression,
542
541
  videoConfigValues,
543
- })) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : null);
542
+ });
543
+ return numericExpression === null
544
+ ? null
545
+ : no_react_1.NoReactInternals.evaluateSourceNumericValue(numericExpression, null);
544
546
  }
545
547
  return defaultValue;
546
548
  };
@@ -975,7 +977,7 @@ const resolveSequencePropsNodePathsFromFilename = ({ fileName, targets, remotion
975
977
  });
976
978
  };
977
979
  exports.resolveSequencePropsNodePathsFromFilename = resolveSequencePropsNodePathsFromFilename;
978
- const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, componentIdentity, keys, assetKeys = [], effects, videoConfigValues, }) => {
980
+ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, componentIdentity, keys, assetKeys = [], effects, }) => {
979
981
  try {
980
982
  return (0, codemods_1.getNodeProps)({
981
983
  project: { rootDir: '/', files: { 'source.tsx': fileContents } },
@@ -984,7 +986,6 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, compone
984
986
  keys,
985
987
  assetKeys,
986
988
  effectKeys: effects,
987
- videoConfig: videoConfigValues !== null && videoConfigValues !== void 0 ? videoConfigValues : undefined,
988
989
  });
989
990
  }
990
991
  catch (error) {
@@ -998,7 +999,7 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, compone
998
999
  }
999
1000
  };
1000
1001
  exports.computeSequencePropsStatusFromContent = computeSequencePropsStatusFromContent;
1001
- const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, keys, assetKeys = [], effects, remotionRoot, videoConfigValues, }) => {
1002
+ const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, keys, assetKeys = [], effects, remotionRoot, }) => {
1002
1003
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
1003
1004
  remotionRoot,
1004
1005
  fileName,
@@ -1012,11 +1013,10 @@ const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, key
1012
1013
  keys,
1013
1014
  assetKeys,
1014
1015
  effects,
1015
- videoConfigValues,
1016
1016
  });
1017
1017
  };
1018
1018
  exports.computeSequencePropsStatus = computeSequencePropsStatus;
1019
- const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, column, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, videoConfigValues, }) => {
1019
+ const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, column, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, }) => {
1020
1020
  try {
1021
1021
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
1022
1022
  remotionRoot,
@@ -1046,14 +1046,13 @@ const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, colu
1046
1046
  assetKeys,
1047
1047
  effects,
1048
1048
  remotionRoot,
1049
- videoConfigValues,
1050
1049
  }),
1051
1050
  nodePath: {
1052
1051
  absolutePath,
1053
1052
  nodePath: resolvedNodePath,
1054
1053
  sequenceKeys: keys,
1055
1054
  effectKeys: effects,
1056
- videoConfigValues,
1055
+ videoConfigValues: null,
1057
1056
  },
1058
1057
  success: true,
1059
1058
  };
@@ -1,4 +1,3 @@
1
- import type { GetDefaultCodingAgentInfoRequest, GetDefaultCodingAgentInfoResponse, OpenInCodingAgentRequest, OpenInCodingAgentResponse } from '@remotion/studio-shared';
1
+ import type { GetDefaultCodingAgentInfoRequest, GetDefaultCodingAgentInfoResponse } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
3
  export declare const getDefaultCodingAgentInfoHandler: ApiHandler<GetDefaultCodingAgentInfoRequest, GetDefaultCodingAgentInfoResponse>;
4
- export declare const openInCodingAgentHandler: ApiHandler<OpenInCodingAgentRequest, OpenInCodingAgentResponse>;
@@ -1,15 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.openInCodingAgentHandler = exports.getDefaultCodingAgentInfoHandler = void 0;
4
- const coding_agent_registry_1 = require("../../helpers/coding-agent-registry");
3
+ exports.getDefaultCodingAgentInfoHandler = void 0;
4
+ const app_discovery_1 = require("../../helpers/app-discovery");
5
5
  const git_client_registry_1 = require("../../helpers/git-client-registry");
6
+ const recently_used_apps_1 = require("../../helpers/recently-used-apps");
6
7
  const terminal_registry_1 = require("../../helpers/terminal-registry");
7
- const getDefaultCodingAgentInfoHandler = async ({ getDefaultCodingAgent }) => {
8
- const installedCodingAgents = await (0, coding_agent_registry_1.getAvailableCodingAgents)();
8
+ const getDefaultCodingAgentInfoHandler = async ({ getDefaultCodingAgent, input, remotionRoot }) => {
9
+ await (0, recently_used_apps_1.getRecentlyUsedApps)({
10
+ remotionRoot,
11
+ type: 'coding-agent',
12
+ recentlyUsedIds: input.recentlyUsedIds,
13
+ });
14
+ const { installedCodingAgents, runningCodingAgents } = await (0, app_discovery_1.getAppDiscovery)();
9
15
  const installedTerminals = await (0, terminal_registry_1.getAvailableTerminals)();
10
16
  const installedGitClients = await (0, git_client_registry_1.getAvailableGitClients)();
11
17
  return {
12
18
  defaultCodingAgent: getDefaultCodingAgent(),
19
+ runningCodingAgents,
13
20
  installedCodingAgents: installedCodingAgents.map(({ id, name, nameWithType }) => ({
14
21
  id,
15
22
  name,
@@ -20,18 +27,3 @@ const getDefaultCodingAgentInfoHandler = async ({ getDefaultCodingAgent }) => {
20
27
  };
21
28
  };
22
29
  exports.getDefaultCodingAgentInfoHandler = getDefaultCodingAgentInfoHandler;
23
- const openInCodingAgentHandler = async ({ input, logLevel, remotionRoot }) => {
24
- const codingAgent = (await (0, coding_agent_registry_1.getAvailableCodingAgents)()).find((agent) => agent.id === input.codingAgentId);
25
- if (!codingAgent) {
26
- return { success: false };
27
- }
28
- return {
29
- success: await (0, coding_agent_registry_1.launchCodingAgent)({
30
- codingAgent,
31
- projectPath: remotionRoot,
32
- logLevel,
33
- prompt: input.prompt,
34
- }),
35
- };
36
- };
37
- exports.openInCodingAgentHandler = openInCodingAgentHandler;
@@ -1,34 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDefaultEditorInfoHandler = void 0;
4
- const custom_editor_1 = require("../../helpers/custom-editor");
5
- const editor_registry_1 = require("../../helpers/editor-registry");
6
- const getDefaultEditorInfoHandler = async ({ getDefaultEditor }) => {
7
- const installedEditors = await (0, editor_registry_1.getAvailableEditors)();
8
- const configuredEditor = getDefaultEditor();
9
- const customEditor = configuredEditor &&
10
- typeof configuredEditor === 'object' &&
11
- (0, custom_editor_1.resolveCustomEditorExecutable)(configuredEditor)
12
- ? configuredEditor
13
- : null;
14
- return {
15
- defaultEditor: typeof configuredEditor === 'object' ? 'custom' : configuredEditor,
16
- installedEditors: [
17
- ...installedEditors.map(({ id, name, nameWithType }) => ({
18
- id,
19
- name,
20
- nameWithType,
21
- })),
22
- ...(customEditor
23
- ? [
24
- {
25
- id: 'custom',
26
- name: customEditor.name,
27
- nameWithType: customEditor.name,
28
- },
29
- ]
30
- : []),
31
- ],
32
- };
4
+ const app_discovery_1 = require("../../helpers/app-discovery");
5
+ const recently_used_apps_1 = require("../../helpers/recently-used-apps");
6
+ const getDefaultEditorInfoHandler = async ({ getDefaultEditor, input, remotionRoot }) => {
7
+ await (0, recently_used_apps_1.getRecentlyUsedApps)({
8
+ remotionRoot,
9
+ type: 'editor',
10
+ recentlyUsedIds: input.recentlyUsedIds,
11
+ });
12
+ return (0, app_discovery_1.getEditorInfo)(getDefaultEditor());
33
13
  };
34
14
  exports.getDefaultEditorInfoHandler = getDefaultEditorInfoHandler;
@@ -1,4 +1,4 @@
1
- import type { DeleteEffectKeyframe, DeleteKeyframesRequest, DeleteKeyframesResponse, DeleteSequenceKeyframe, SaveSequencePropsResult } from '@remotion/studio-shared';
1
+ import type { DeleteEffectKeyframe, DeleteKeyframesRequest, DeleteKeyframesResponse, DeleteSequenceKeyframe, SaveEffectPropsResponse, SaveSequencePropsResult } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
3
  export declare const deleteKeyframes: ({ sequenceKeyframes, effectKeyframes, clientId, remotionRoot, logLevel, }: {
4
4
  sequenceKeyframes: DeleteSequenceKeyframe[];
@@ -8,6 +8,6 @@ export declare const deleteKeyframes: ({ sequenceKeyframes, effectKeyframes, cli
8
8
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
9
9
  }) => Promise<{
10
10
  sequenceResults: SaveSequencePropsResult[];
11
- effectResults: import("remotion").CanUpdateEffectPropsResponse[];
11
+ effectResults: SaveEffectPropsResponse[];
12
12
  }>;
13
13
  export declare const deleteKeyframesHandler: ApiHandler<DeleteKeyframesRequest, DeleteKeyframesResponse>;
@@ -239,7 +239,6 @@ const deleteKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, r
239
239
  nodePath: keyframe.nodePath.nodePath,
240
240
  componentIdentity: null,
241
241
  effects: [],
242
- videoConfigValues: keyframe.nodePath.videoConfigValues,
243
242
  });
244
243
  return {
245
244
  fileName: keyframe.fileName,
@@ -74,6 +74,11 @@ const getExpectedFileState = (existingSource) => {
74
74
  const getElementInstallPlan = async ({ destination, element, installationName, entryPoint, remotionRoot, }) => {
75
75
  var _a;
76
76
  (0, exports.validateElementForInstallation)(element);
77
+ if (destination.type === 'selected-media' &&
78
+ (element.isCaptionStyle !== true ||
79
+ element.installationMode !== 'component-owned-sequence')) {
80
+ throw new Error('The Element must be a component-owned caption style');
81
+ }
77
82
  const componentName = studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(element.sourceCode);
78
83
  if (componentName === null) {
79
84
  throw new Error('Element source must export exactly one named component');
@@ -45,6 +45,7 @@ const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, dur
45
45
  },
46
46
  });
47
47
  const { output, logLine, nodePathRemappings } = insertBasicCaptions({
48
+ element: null,
48
49
  input: fileContents,
49
50
  nodePath,
50
51
  captions,
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertElementHandler = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const codemods_1 = require("@remotion/codemods");
9
10
  const renderer_1 = require("@remotion/renderer");
10
11
  const studio_protocol_1 = require("@remotion/studio-protocol");
11
12
  const add_composition_to_file_1 = require("../../codemods/add-composition-to-file");
@@ -33,10 +34,18 @@ const hasExpectedFileState = ({ expected, actual, }) => {
33
34
  }
34
35
  return actual.sourceHash === expected.sourceHash;
35
36
  };
36
- const insertElementHandler = async ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, premountFor, position, overwriteExisting, undoRedoNavigation, newComposition, }, entryPoint, remotionRoot, logLevel, publicDir, }) => {
37
+ const insertElementHandler = async ({ input: { compositionFile, compositionId, captionTarget, element, installationName, expectedFileState, from, premountFor, position, overwriteExisting, undoRedoNavigation, newComposition, }, entryPoint, remotionRoot, logLevel, publicDir, }) => {
37
38
  var _a;
38
39
  let resolvedAssets;
39
40
  try {
41
+ if (captionTarget !== null &&
42
+ (element.isCaptionStyle !== true ||
43
+ element.installationMode !== 'component-owned-sequence' ||
44
+ newComposition !== null ||
45
+ compositionFile !== null ||
46
+ compositionId !== null)) {
47
+ throw new Error('Invalid caption style installation target');
48
+ }
40
49
  studio_protocol_1.StudioProtocolInternals.assertElementAssets(element.assets);
41
50
  studio_protocol_1.StudioProtocolInternals.assertElementAssetReferences(element);
42
51
  resolvedAssets = await studio_protocol_1.StudioProtocolInternals.resolveElementAssets({
@@ -54,7 +63,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
54
63
  }
55
64
  return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
56
65
  var _a, _b, _c, _d, _e, _f;
57
- var _g, _h, _j, _k;
66
+ var _g, _h, _j;
58
67
  const createdAssets = [];
59
68
  const changedSources = [];
60
69
  let undoEntryPushed = false;
@@ -132,16 +141,21 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
132
141
  [componentFilePath, componentFileContents],
133
142
  ]);
134
143
  }
135
- const installDestination = newComposition === null
144
+ const installDestination = captionTarget !== null
136
145
  ? {
137
- type: 'current-composition',
138
- compositionFile,
139
- compositionId,
146
+ type: 'selected-media',
147
+ compositionFile: captionTarget.fileName,
140
148
  }
141
- : {
142
- type: 'new-composition',
143
- compositionFile,
144
- };
149
+ : newComposition === null
150
+ ? {
151
+ type: 'current-composition',
152
+ compositionFile,
153
+ compositionId,
154
+ }
155
+ : {
156
+ type: 'new-composition',
157
+ compositionFile,
158
+ };
145
159
  const plan = await (0, element_install_plan_1.getElementInstallPlan)({
146
160
  installationName,
147
161
  destination: installDestination,
@@ -187,6 +201,13 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
187
201
  throw new Error('Element source file conflicts with the new composition file');
188
202
  }
189
203
  const shouldWriteElementFile = !plan.elementFileExists || elementSourcesDiffer;
204
+ const initialProps = { ...element.initialProps };
205
+ if (componentOwnsSequence && element.dimensions !== null) {
206
+ initialProps.style = {
207
+ ...element.dimensions,
208
+ ...(typeof initialProps.style === 'object' ? initialProps.style : {}),
209
+ };
210
+ }
190
211
  const insertionInput = {
191
212
  remotionRoot,
192
213
  compositionFile,
@@ -197,7 +218,10 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
197
218
  importName: plan.componentName,
198
219
  importPath: plan.importPath,
199
220
  props: [
200
- ...Object.entries((_h = element.initialProps) !== null && _h !== void 0 ? _h : {}).map(([name, value]) => ({ name, value })),
221
+ ...Object.entries(initialProps).map(([name, value]) => ({
222
+ name,
223
+ value,
224
+ })),
201
225
  ...(componentOwnsSequence && element.durationInFrames !== null
202
226
  ? [
203
227
  {
@@ -225,10 +249,29 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
225
249
  position,
226
250
  },
227
251
  };
228
- const inserted = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
229
- ...insertionInput,
230
- sourceFileOverrides,
231
- });
252
+ let inserted;
253
+ if (captionTarget === null) {
254
+ inserted = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
255
+ ...insertionInput,
256
+ compositionFile,
257
+ compositionId,
258
+ sourceFileOverrides,
259
+ });
260
+ }
261
+ else {
262
+ const fileName = plan.safePaths.compositionFileName;
263
+ const oldContents = (0, node_fs_1.readFileSync)(fileName, 'utf-8');
264
+ inserted = {
265
+ ...codemods_1.CodemodsInternals.insertBasicCaptions({
266
+ ...captionTarget,
267
+ input: oldContents,
268
+ importPath: plan.importPath,
269
+ element: { componentName: plan.componentName, initialProps },
270
+ }),
271
+ fileName,
272
+ oldContents,
273
+ };
274
+ }
232
275
  if (compositionCreation !== null &&
233
276
  inserted.fileName !== compositionCreation.componentFilePath) {
234
277
  throw new Error('New composition component does not match installation target');
@@ -289,7 +332,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
289
332
  try {
290
333
  (0, node_fs_1.unlinkSync)(asset.absolutePath);
291
334
  }
292
- catch (_l) {
335
+ catch (_k) {
293
336
  // Keep the original write error.
294
337
  }
295
338
  throw error;
@@ -328,7 +371,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
328
371
  filePath: compositionCreation.registrationFilePath,
329
372
  oldContents: compositionCreation.registrationFileOldContents,
330
373
  newContents: compositionCreation.registrationFileNewContents,
331
- logLine: (_j = (_e = newComposition === null || newComposition === void 0 ? void 0 : newComposition.symbolicatedStack) === null || _e === void 0 ? void 0 : _e.originalLineNumber) !== null && _j !== void 0 ? _j : 1,
374
+ logLine: (_h = (_e = newComposition === null || newComposition === void 0 ? void 0 : newComposition.symbolicatedStack) === null || _e === void 0 ? void 0 : _e.originalLineNumber) !== null && _h !== void 0 ? _h : 1,
332
375
  nodePathRemappings: null,
333
376
  },
334
377
  ]),
@@ -397,7 +440,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
397
440
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright((0, format_log_file_location_1.formatLogFileLocation)({
398
441
  remotionRoot,
399
442
  absolutePath: compositionCreation.registrationFilePath,
400
- line: (_k = (_f = newComposition.symbolicatedStack) === null || _f === void 0 ? void 0 : _f.originalLineNumber) !== null && _k !== void 0 ? _k : 1,
443
+ line: (_j = (_f = newComposition.symbolicatedStack) === null || _f === void 0 ? void 0 : _f.originalLineNumber) !== null && _j !== void 0 ? _j : 1,
401
444
  }))} Created composition "${compositionId}"`);
402
445
  }
403
446
  const compositionLocationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
@@ -441,7 +484,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
441
484
  });
442
485
  }
443
486
  }
444
- catch (_m) {
487
+ catch (_l) {
445
488
  // Preserve subsequent user changes and the original installation error.
446
489
  }
447
490
  }
@@ -451,7 +494,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
451
494
  (0, node_fs_1.unlinkSync)(asset.absolutePath);
452
495
  }
453
496
  }
454
- catch (_o) {
497
+ catch (_m) {
455
498
  // Preserve subsequent user changes and the original installation error.
456
499
  }
457
500
  }
@@ -1,4 +1,5 @@
1
- import type { GetRemotionSkillsInfoResponse, InstallRemotionSkillRequest, RemoveRemotionSkillRequest } from '@remotion/studio-shared';
1
+ import type { GetRemotionSkillsInfoResponse, InstallRemotionSkillRequest, RemoveRemotionSkillRequest, UpgradeRemotionSkillRequest } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
3
  export declare const installRemotionSkillHandler: ApiHandler<InstallRemotionSkillRequest, GetRemotionSkillsInfoResponse>;
4
4
  export declare const removeRemotionSkillHandler: ApiHandler<RemoveRemotionSkillRequest, GetRemotionSkillsInfoResponse>;
5
+ export declare const upgradeRemotionSkillHandler: ApiHandler<UpgradeRemotionSkillRequest, GetRemotionSkillsInfoResponse>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.removeRemotionSkillHandler = exports.installRemotionSkillHandler = void 0;
3
+ exports.upgradeRemotionSkillHandler = exports.removeRemotionSkillHandler = exports.installRemotionSkillHandler = void 0;
4
4
  const node_child_process_1 = require("node:child_process");
5
5
  const renderer_1 = require("@remotion/renderer");
6
6
  const package_manager_spawn_options_1 = require("../../helpers/package-manager-spawn-options");
@@ -13,19 +13,28 @@ const changeRemotionSkill = async ({ action, remotionRoot, input: { skill }, log
13
13
  throw new Error(`Unknown Remotion skill: ${JSON.stringify(skill)}`);
14
14
  }
15
15
  if (changingSkillsInProjects.has(remotionRoot)) {
16
- throw new Error('A skill is already being installed or removed. Please try again once it finishes.');
16
+ throw new Error('A skill is already being installed, upgraded, or removed. Please try again once it finishes.');
17
17
  }
18
18
  changingSkillsInProjects.add(remotionRoot);
19
19
  try {
20
- const installedSkill = (0, remotion_skills_info_1.getRemotionSkillsInfo)({ remotionRoot }).skills.find(({ name }) => name === skill);
20
+ const currentInfo = (0, remotion_skills_info_1.getRemotionSkillsInfo)({ remotionRoot });
21
+ const installedSkill = currentInfo.skills.find(({ name }) => name === skill);
21
22
  const removingGlobally = action === 'remove' &&
22
23
  (installedSkill === null || installedSkill === void 0 ? void 0 : installedSkill.installedInProject) === false &&
23
24
  installedSkill.installedGlobally;
24
- if (action === 'remove' &&
25
- !removingGlobally &&
26
- !(installedSkill === null || installedSkill === void 0 ? void 0 : installedSkill.installedInProject)) {
25
+ if (action !== 'install' &&
26
+ !(installedSkill === null || installedSkill === void 0 ? void 0 : installedSkill.installedInProject) &&
27
+ !(installedSkill === null || installedSkill === void 0 ? void 0 : installedSkill.installedGlobally)) {
27
28
  throw new Error(`${skill} is not installed.`);
28
29
  }
30
+ const scopes = action === 'upgrade'
31
+ ? currentInfo.installations
32
+ .filter((installation) => installation.name === skill && installation.outdated)
33
+ .map(({ scope }) => scope)
34
+ : [removingGlobally ? 'global' : 'project'];
35
+ if (scopes.length === 0) {
36
+ throw new Error(`${skill} is already up to date.`);
37
+ }
29
38
  const packageManager = (0, get_package_manager_1.getPackageManager)({
30
39
  remotionRoot,
31
40
  packageManager: undefined,
@@ -38,61 +47,79 @@ const changeRemotionSkill = async ({ action, remotionRoot, input: { skill }, log
38
47
  : process.platform === 'win32'
39
48
  ? 'npx.cmd'
40
49
  : 'npx';
41
- const commandArgs = action === 'install'
42
- ? ['add', `remotion-dev/skills@${skill}`, '--yes']
43
- : ['remove', ...(removingGlobally ? ['--global'] : []), skill, '--yes'];
44
- const args = useBunx
45
- ? ['--silent', 'skills@1.7.0', ...commandArgs]
46
- : ['--yes', '--loglevel=error', 'skills@1.7.0', ...commandArgs];
47
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`╭─ ${executable} ${args.join(' ')}`));
48
- const time = Date.now();
49
- try {
50
- await new Promise((resolve, reject) => {
51
- const child = (0, node_child_process_1.spawn)(executable, args, {
52
- cwd: remotionRoot,
53
- env: { ...process.env, DISABLE_TELEMETRY: '1' },
54
- stdio: ['ignore', 'pipe', 'pipe'],
55
- ...(0, package_manager_spawn_options_1.getPackageManagerSpawnOptions)(),
50
+ for (const scope of scopes) {
51
+ const commandArgs = action === 'remove'
52
+ ? [
53
+ 'remove',
54
+ ...(scope === 'global' ? ['--global'] : []),
55
+ skill,
56
+ '--yes',
57
+ ]
58
+ : [
59
+ 'add',
60
+ `remotion-dev/skills@${skill}`,
61
+ ...(scope === 'global' ? ['--global'] : []),
62
+ '--yes',
63
+ ];
64
+ const args = useBunx
65
+ ? ['--silent', 'skills@1.7.0', ...commandArgs]
66
+ : ['--yes', '--loglevel=error', 'skills@1.7.0', ...commandArgs];
67
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`╭─ ${executable} ${args.join(' ')}`));
68
+ const time = Date.now();
69
+ try {
70
+ await new Promise((resolve, reject) => {
71
+ const child = (0, node_child_process_1.spawn)(executable, args, {
72
+ cwd: remotionRoot,
73
+ env: { ...process.env, DISABLE_TELEMETRY: '1' },
74
+ stdio: ['ignore', 'pipe', 'pipe'],
75
+ ...(0, package_manager_spawn_options_1.getPackageManagerSpawnOptions)(),
76
+ });
77
+ let output = '';
78
+ const onData = (data) => {
79
+ output = (output + data.toString()).slice(-8000);
80
+ data
81
+ .toString()
82
+ .trim()
83
+ .split('\n')
84
+ .forEach((line) => renderer_1.RenderInternals.Log.info({ indent: true, logLevel }, line));
85
+ };
86
+ child.stdout.on('data', onData);
87
+ child.stderr.on('data', onData);
88
+ child.on('error', reject);
89
+ child.on('close', (code, signal) => {
90
+ if (code === 0) {
91
+ resolve();
92
+ }
93
+ else {
94
+ reject(new Error(`Could not ${action} ${skill} (exit code ${code}, signal ${signal}). ${output.trim()}`));
95
+ }
96
+ });
56
97
  });
57
- let output = '';
58
- const onData = (data) => {
59
- output = (output + data.toString()).slice(-8000);
60
- data
61
- .toString()
62
- .trim()
63
- .split('\n')
64
- .forEach((line) => renderer_1.RenderInternals.Log.info({ indent: true, logLevel }, line));
65
- };
66
- child.stdout.on('data', onData);
67
- child.stderr.on('data', onData);
68
- child.on('error', reject);
69
- child.on('close', (code, signal) => {
70
- if (code === 0) {
71
- resolve();
72
- }
73
- else {
74
- reject(new Error(`Could not ${action} ${skill} (exit code ${code}, signal ${signal}). ${output.trim()}`));
98
+ const info = (0, remotion_skills_info_1.getRemotionSkillsInfo)({ remotionRoot });
99
+ const updatedSkill = info.skills.find(({ name }) => name === skill);
100
+ if (action === 'install' && !(updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedInProject)) {
101
+ throw new Error(`The installer finished, but ${skill} was not found in the project. Please try again.`);
102
+ }
103
+ if (action === 'upgrade') {
104
+ const upgradedInstallation = info.installations.find((installation) => installation.name === skill && installation.scope === scope);
105
+ if (!upgradedInstallation || upgradedInstallation.outdated) {
106
+ throw new Error(`The installer finished, but ${skill} ${scope === 'global' ? 'globally' : 'in the project'} is still out of date. Please try again.`);
75
107
  }
76
- });
77
- });
78
- const info = (0, remotion_skills_info_1.getRemotionSkillsInfo)({ remotionRoot });
79
- const updatedSkill = info.skills.find(({ name }) => name === skill);
80
- if (action === 'install' && !(updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedInProject)) {
81
- throw new Error(`The installer finished, but ${skill} was not found in the project. Please try again.`);
108
+ }
109
+ if (action === 'remove' &&
110
+ (removingGlobally
111
+ ? updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedGlobally
112
+ : updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedInProject)) {
113
+ throw new Error(`The remover finished, but ${skill} is still installed ${removingGlobally ? 'globally' : 'in the project'}. Please try again.`);
114
+ }
115
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), `Done in ${Date.now() - time}ms`);
82
116
  }
83
- if (action === 'remove' &&
84
- (removingGlobally
85
- ? updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedGlobally
86
- : updatedSkill === null || updatedSkill === void 0 ? void 0 : updatedSkill.installedInProject)) {
87
- throw new Error(`The remover finished, but ${skill} is still installed ${removingGlobally ? 'globally' : 'in the project'}. Please try again.`);
117
+ catch (error) {
118
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), renderer_1.RenderInternals.chalk.red(`Errored in ${Date.now() - time}ms`));
119
+ throw error;
88
120
  }
89
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), `Done in ${Date.now() - time}ms`);
90
- return info;
91
- }
92
- catch (error) {
93
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray('╰─ '), renderer_1.RenderInternals.chalk.red(`Errored in ${Date.now() - time}ms`));
94
- throw error;
95
121
  }
122
+ return (0, remotion_skills_info_1.getRemotionSkillsInfo)({ remotionRoot });
96
123
  }
97
124
  finally {
98
125
  changingSkillsInProjects.delete(remotionRoot);
@@ -106,3 +133,7 @@ const removeRemotionSkillHandler = (input) => {
106
133
  return changeRemotionSkill({ ...input, action: 'remove' });
107
134
  };
108
135
  exports.removeRemotionSkillHandler = removeRemotionSkillHandler;
136
+ const upgradeRemotionSkillHandler = (input) => {
137
+ return changeRemotionSkill({ ...input, action: 'upgrade' });
138
+ };
139
+ exports.upgradeRemotionSkillHandler = upgradeRemotionSkillHandler;
@@ -1,4 +1,4 @@
1
- import { type DefaultEditor } from '@remotion/renderer';
1
+ import type { DefaultEditor } from '@remotion/renderer';
2
2
  import type { OpenInEditorRequest, OpenInEditorResponse } from '@remotion/studio-shared';
3
3
  import type { ApiHandler } from '../api-types';
4
4
  export declare const getEditorName: ({ getDefaultEditor, logLevel, }: {