@remotion/studio-server 4.0.438 → 4.0.440

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 (36) hide show
  1. package/dist/client-render-queue.js +3 -3
  2. package/dist/codemods/apply-visual-control.js +8 -1
  3. package/dist/codemods/format-inline-content.d.ts +21 -0
  4. package/dist/codemods/format-inline-content.js +108 -0
  5. package/dist/codemods/read-visual-control-values.d.ts +7 -0
  6. package/dist/codemods/read-visual-control-values.js +166 -0
  7. package/dist/codemods/update-default-props.d.ts +4 -1
  8. package/dist/codemods/update-default-props.js +51 -22
  9. package/dist/file-watcher.d.ts +24 -7
  10. package/dist/file-watcher.js +148 -29
  11. package/dist/index.d.ts +5 -2
  12. package/dist/index.js +3 -0
  13. package/dist/preview-server/api-routes.js +8 -2
  14. package/dist/preview-server/default-props-watchers.js +12 -17
  15. package/dist/preview-server/file-existence-watchers.js +3 -3
  16. package/dist/preview-server/hot-middleware/index.d.ts +2 -2
  17. package/dist/preview-server/hot-middleware/index.js +14 -92
  18. package/dist/preview-server/live-events.d.ts +7 -1
  19. package/dist/preview-server/live-events.js +21 -2
  20. package/dist/preview-server/routes/apply-codemod.js +2 -1
  21. package/dist/preview-server/routes/apply-visual-control-change.js +103 -5
  22. package/dist/preview-server/routes/can-update-default-props.d.ts +10 -3
  23. package/dist/preview-server/routes/can-update-default-props.js +138 -13
  24. package/dist/preview-server/routes/can-update-sequence-props.js +4 -0
  25. package/dist/preview-server/routes/log-update.d.ts +8 -0
  26. package/dist/preview-server/routes/log-update.js +60 -27
  27. package/dist/preview-server/routes/save-sequence-props.js +47 -5
  28. package/dist/preview-server/routes/update-default-props.js +41 -4
  29. package/dist/preview-server/sequence-props-watchers.js +4 -9
  30. package/dist/preview-server/start-server.js +16 -9
  31. package/dist/preview-server/undo-stack.d.ts +24 -4
  32. package/dist/preview-server/undo-stack.js +75 -11
  33. package/dist/preview-server/watch-ignore-next-change.d.ts +3 -0
  34. package/dist/preview-server/watch-ignore-next-change.js +12 -0
  35. package/dist/start-studio.js +3 -0
  36. package/package.json +6 -6
package/dist/index.d.ts CHANGED
@@ -56,13 +56,16 @@ export declare const StudioServerInternals: {
56
56
  getMaxTimelineTracks: () => number;
57
57
  setMaxTimelineTracks: (maxTracks: number) => void;
58
58
  getLatestRemotionVersion: () => Promise<any>;
59
- installFileWatcher: ({ file, onChange, }: {
59
+ installFileWatcher: (options: {
60
60
  file: string;
61
- onChange: (type: "changed" | "created" | "deleted") => void;
61
+ onChange: (event: import("./file-watcher").FileChangeEvent) => void;
62
62
  }) => {
63
63
  exists: boolean;
64
64
  unwatch: () => void;
65
65
  };
66
+ writeFileAndNotifyFileWatchers: (file: string, content: string) => void;
67
+ createFileWatcherRegistry: () => import("./file-watcher").FileWatcherRegistry;
68
+ setFileWatcherRegistry: (registry: import("./file-watcher").FileWatcherRegistry) => () => void;
66
69
  AnsiDiff: typeof AnsiDiff;
67
70
  formatBytes: (number: number, options?: (Intl.NumberFormatOptions & {
68
71
  locale: string;
package/dist/index.js CHANGED
@@ -26,6 +26,9 @@ exports.StudioServerInternals = {
26
26
  setMaxTimelineTracks: max_timeline_tracks_1.setMaxTimelineTracks,
27
27
  getLatestRemotionVersion: get_latest_remotion_version_1.getLatestRemotionVersion,
28
28
  installFileWatcher: file_watcher_1.installFileWatcher,
29
+ writeFileAndNotifyFileWatchers: file_watcher_1.writeFileAndNotifyFileWatchers,
30
+ createFileWatcherRegistry: file_watcher_1.createFileWatcherRegistry,
31
+ setFileWatcherRegistry: file_watcher_1.setFileWatcherRegistry,
29
32
  AnsiDiff: ansi_diff_1.AnsiDiff,
30
33
  formatBytes: studio_shared_1.formatBytes,
31
34
  parseAndApplyCodemod: duplicate_composition_1.parseAndApplyCodemod,
@@ -4,17 +4,20 @@ exports.allApiRoutes = void 0;
4
4
  const add_render_1 = require("./routes/add-render");
5
5
  const apply_codemod_1 = require("./routes/apply-codemod");
6
6
  const apply_visual_control_change_1 = require("./routes/apply-visual-control-change");
7
- const can_update_default_props_1 = require("./routes/can-update-default-props");
8
7
  const cancel_render_1 = require("./routes/cancel-render");
9
8
  const delete_static_file_1 = require("./routes/delete-static-file");
10
9
  const install_dependency_1 = require("./routes/install-dependency");
11
10
  const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
12
11
  const project_info_1 = require("./routes/project-info");
12
+ const redo_1 = require("./routes/redo");
13
13
  const remove_render_1 = require("./routes/remove-render");
14
14
  const restart_studio_1 = require("./routes/restart-studio");
15
15
  const save_sequence_props_1 = require("./routes/save-sequence-props");
16
+ const subscribe_to_default_props_1 = require("./routes/subscribe-to-default-props");
16
17
  const subscribe_to_file_existence_1 = require("./routes/subscribe-to-file-existence");
17
18
  const subscribe_to_sequence_props_1 = require("./routes/subscribe-to-sequence-props");
19
+ const undo_1 = require("./routes/undo");
20
+ const unsubscribe_from_default_props_1 = require("./routes/unsubscribe-from-default-props");
18
21
  const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-file-existence");
19
22
  const unsubscribe_from_sequence_props_1 = require("./routes/unsubscribe-from-sequence-props");
20
23
  const update_available_1 = require("./routes/update-available");
@@ -29,7 +32,8 @@ exports.allApiRoutes = {
29
32
  '/api/update-default-props': update_default_props_1.updateDefaultPropsHandler,
30
33
  '/api/apply-visual-control-change': apply_visual_control_change_1.applyVisualControlHandler,
31
34
  '/api/apply-codemod': apply_codemod_1.applyCodemodHandler,
32
- '/api/can-update-default-props': can_update_default_props_1.canUpdateDefaultPropsHandler,
35
+ '/api/subscribe-to-default-props': subscribe_to_default_props_1.subscribeToDefaultProps,
36
+ '/api/unsubscribe-from-default-props': unsubscribe_from_default_props_1.unsubscribeFromDefaultProps,
33
37
  '/api/subscribe-to-sequence-props': subscribe_to_sequence_props_1.subscribeToSequenceProps,
34
38
  '/api/unsubscribe-from-sequence-props': unsubscribe_from_sequence_props_1.unsubscribeFromSequenceProps,
35
39
  '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
@@ -38,4 +42,6 @@ exports.allApiRoutes = {
38
42
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
39
43
  '/api/restart-studio': restart_studio_1.handleRestartStudio,
40
44
  '/api/install-package': install_dependency_1.handleInstallPackage,
45
+ '/api/undo': undo_1.undoHandler,
46
+ '/api/redo': redo_1.redoHandler,
41
47
  };
@@ -17,8 +17,8 @@ const ensureGlobalWatcher = (rootFile) => {
17
17
  }
18
18
  const { unwatch } = (0, file_watcher_1.installFileWatcher)({
19
19
  file: rootFile,
20
- onChange: (type) => {
21
- if (type === 'deleted') {
20
+ onChange: (event) => {
21
+ if (event.type === 'deleted') {
22
22
  return;
23
23
  }
24
24
  if (!watcherConfig) {
@@ -30,21 +30,16 @@ const ensureGlobalWatcher = (rootFile) => {
30
30
  continue;
31
31
  }
32
32
  const clientIds = [...subscriptions[compositionId]];
33
- (0, can_update_default_props_1.computeCanUpdateDefaultProps)({
34
- compositionId,
35
- remotionRoot: watcherConfig.remotionRoot,
36
- entryPoint: watcherConfig.entryPoint,
37
- }).then(({ result: newResult }) => {
38
- (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
39
- const event = {
40
- type: 'default-props-updatable-changed',
41
- compositionId,
42
- result: newResult,
43
- };
44
- for (const cId of clientIds) {
45
- listener.sendEventToClientId(cId, event);
46
- }
47
- });
33
+ const newResult = (0, can_update_default_props_1.computeCanUpdateDefaultPropsFromContent)(event.content, compositionId);
34
+ (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
35
+ const updateEvent = {
36
+ type: 'default-props-updatable-changed',
37
+ compositionId,
38
+ result: newResult,
39
+ };
40
+ for (const cId of clientIds) {
41
+ listener.sendEventToClientId(cId, updateEvent);
42
+ }
48
43
  });
49
44
  }
50
45
  },
@@ -12,8 +12,8 @@ const subscribeToFileExistenceWatchers = ({ file: relativeFile, remotionRoot, cl
12
12
  const file = node_path_1.default.resolve(remotionRoot, relativeFile);
13
13
  const { unwatch, exists } = (0, file_watcher_1.installFileWatcher)({
14
14
  file,
15
- onChange: (type) => {
16
- if (type === 'created') {
15
+ onChange: (event) => {
16
+ if (event.type === 'created') {
17
17
  (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
18
18
  listener.sendEventToClient({
19
19
  type: 'watched-file-undeleted',
@@ -22,7 +22,7 @@ const subscribeToFileExistenceWatchers = ({ file: relativeFile, remotionRoot, cl
22
22
  });
23
23
  });
24
24
  }
25
- if (type === 'deleted') {
25
+ if (event.type === 'deleted') {
26
26
  (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
27
27
  listener.sendEventToClient({
28
28
  type: 'watched-file-deleted',
@@ -3,8 +3,8 @@
3
3
  * https://github.com/webpack-contrib/webpack-hot-middleware#readme
4
4
  * and rewritten in TypeScript. This file is MIT licensed
5
5
  */
6
- import type { IncomingMessage, ServerResponse } from 'node:http';
7
6
  import type { webpack } from '@remotion/bundler';
7
+ import type { LiveEventsServer } from '../live-events';
8
8
  declare global {
9
9
  const __webpack_hash__: unknown;
10
10
  interface HotNotifierInfo {
@@ -99,4 +99,4 @@ declare global {
99
99
  };
100
100
  type ModuleId = string | number;
101
101
  }
102
- export declare const webpackHotMiddleware: (compiler: webpack.Compiler, logLevel: "error" | "info" | "trace" | "verbose" | "warn") => (req: IncomingMessage, res: ServerResponse<IncomingMessage>, next: () => void) => void;
102
+ export declare const setupWebpackHmr: (compiler: webpack.Compiler, logLevel: "error" | "info" | "trace" | "verbose" | "warn", liveEventsServer: LiveEventsServer) => void;
@@ -5,113 +5,35 @@
5
5
  * and rewritten in TypeScript. This file is MIT licensed
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.webpackHotMiddleware = void 0;
9
- const node_url_1 = require("node:url");
8
+ exports.setupWebpackHmr = void 0;
10
9
  const renderer_1 = require("@remotion/renderer");
11
- const studio_shared_1 = require("@remotion/studio-shared");
12
- const hmr_suppression_1 = require("../hmr-suppression");
13
- const pathMatch = function (url, path) {
14
- try {
15
- return (0, node_url_1.parse)(url).pathname === path;
16
- }
17
- catch (_a) {
18
- return false;
19
- }
20
- };
21
- const webpackHotMiddleware = (compiler, logLevel) => {
22
- const eventStream = createEventStream(studio_shared_1.hotMiddlewareOptions.heartbeat);
10
+ const setupWebpackHmr = (compiler, logLevel, liveEventsServer) => {
23
11
  let latestStats = null;
24
- let currentBuildSuppressed = false;
12
+ const publishHmr = (hmrEvent) => {
13
+ liveEventsServer.sendEventToClient({ type: 'hmr', hmrEvent });
14
+ };
25
15
  compiler.hooks.invalid.tap('remotion', onInvalid);
26
16
  compiler.hooks.done.tap('remotion', onDone);
27
- function onInvalid(filename) {
28
- if ((0, hmr_suppression_1.shouldSuppressHmr)(filename)) {
29
- currentBuildSuppressed = true;
30
- latestStats = null;
31
- return;
32
- }
33
- currentBuildSuppressed = false;
17
+ function onInvalid() {
34
18
  latestStats = null;
35
19
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, 'Building...');
36
- eventStream === null || eventStream === void 0 ? void 0 : eventStream.publish({
20
+ publishHmr({
37
21
  action: 'building',
38
22
  });
39
23
  }
40
24
  function onDone(statsResult) {
41
25
  // Keep hold of latest stats so they can be propagated to new clients
42
26
  latestStats = statsResult;
43
- if (currentBuildSuppressed) {
44
- // Still send the "built" event so the client hash stays in sync,
45
- // but skip the "building" spinner. This avoids accumulating
46
- // a large HMR delta for the next real build.
47
- currentBuildSuppressed = false;
48
- }
49
- publishStats('built', latestStats, eventStream);
27
+ publishStats('built', latestStats, publishHmr);
50
28
  }
51
- const middleware = function (req, res, next) {
52
- if (!pathMatch(req.url, studio_shared_1.hotMiddlewareOptions.path))
53
- return next();
54
- eventStream === null || eventStream === void 0 ? void 0 : eventStream.handler(req, res);
29
+ liveEventsServer.addNewClientListener(() => {
55
30
  if (latestStats) {
56
- publishStats('sync', latestStats, eventStream);
31
+ publishStats('sync', latestStats, publishHmr);
57
32
  }
58
- };
59
- return middleware;
33
+ });
60
34
  };
61
- exports.webpackHotMiddleware = webpackHotMiddleware;
62
- function createEventStream(heartbeat) {
63
- let clientId = 0;
64
- let clients = {};
65
- function everyClient(fn) {
66
- Object.keys(clients).forEach((id) => {
67
- fn(clients[id]);
68
- });
69
- }
70
- const interval = setInterval(() => {
71
- everyClient((client) => {
72
- client.write('data: \uD83D\uDC93\n\n');
73
- });
74
- }, heartbeat).unref();
75
- return {
76
- close() {
77
- clearInterval(interval);
78
- everyClient((client) => {
79
- if (!client.finished)
80
- client.end();
81
- });
82
- clients = {};
83
- },
84
- handler(req, res) {
85
- const headers = {
86
- 'Access-Control-Allow-Origin': '*',
87
- 'Content-Type': 'text/event-stream;charset=utf-8',
88
- 'Cache-Control': 'no-cache, no-transform',
89
- };
90
- const isHttp1 = !(parseInt(req.httpVersion, 10) >= 2);
91
- if (isHttp1) {
92
- req.socket.setKeepAlive(true);
93
- Object.assign(headers, {
94
- Connection: 'keep-alive',
95
- });
96
- }
97
- res.writeHead(200, headers);
98
- res.write('\n');
99
- const id = clientId++;
100
- clients[id] = res;
101
- req.on('close', () => {
102
- if (!res.finished)
103
- res.end();
104
- delete clients[id];
105
- });
106
- },
107
- publish(payload) {
108
- everyClient((client) => {
109
- client.write('data: ' + JSON.stringify(payload) + '\n\n');
110
- });
111
- },
112
- };
113
- }
114
- function publishStats(action, statsResult, eventStream) {
35
+ exports.setupWebpackHmr = setupWebpackHmr;
36
+ function publishStats(action, statsResult, publishHmr) {
115
37
  const stats = statsResult.toJson({
116
38
  all: false,
117
39
  cached: true,
@@ -128,7 +50,7 @@ function publishStats(action, statsResult, eventStream) {
128
50
  if (bundles.length === 1 && !name && statsResult.compilation) {
129
51
  name = statsResult.compilation.name || '';
130
52
  }
131
- eventStream === null || eventStream === void 0 ? void 0 : eventStream.publish({
53
+ publishHmr({
132
54
  name,
133
55
  action,
134
56
  time: _stats.time,
@@ -2,9 +2,15 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import type { EventSourceEvent } from '@remotion/studio-shared';
3
3
  export type LiveEventsServer = {
4
4
  sendEventToClient: (event: EventSourceEvent) => void;
5
+ sendEventToClientId: (clientId: string, event: EventSourceEvent) => void;
5
6
  router: (request: IncomingMessage, response: ServerResponse) => Promise<void>;
6
7
  closeConnections: () => Promise<void>;
8
+ addNewClientListener: (cb: () => void) => () => void;
7
9
  };
8
- export declare const makeLiveEventsRouter: (logLevel: "error" | "info" | "trace" | "verbose" | "warn") => LiveEventsServer;
10
+ export type InitialUndoRedoState = {
11
+ undoFile: string | null;
12
+ redoFile: string | null;
13
+ };
14
+ export declare const makeLiveEventsRouter: (logLevel: "error" | "info" | "trace" | "verbose" | "warn", getInitialUndoRedoState: () => InitialUndoRedoState) => LiveEventsServer;
9
15
  export declare const waitForLiveEventsListener: () => Promise<LiveEventsServer>;
10
16
  export declare const setLiveEventsListener: (listener: LiveEventsServer) => () => void;
@@ -2,14 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setLiveEventsListener = exports.waitForLiveEventsListener = exports.makeLiveEventsRouter = void 0;
4
4
  const server_ready_1 = require("../server-ready");
5
+ const default_props_watchers_1 = require("./default-props-watchers");
5
6
  const file_existence_watchers_1 = require("./file-existence-watchers");
6
7
  const sequence_props_watchers_1 = require("./sequence-props-watchers");
7
8
  const serializeMessage = (message) => {
8
9
  return `data: ${JSON.stringify(message)}\n\n`;
9
10
  };
10
11
  let printPortMessageTimeout = null;
11
- const makeLiveEventsRouter = (logLevel) => {
12
+ const makeLiveEventsRouter = (logLevel, getInitialUndoRedoState) => {
12
13
  let clients = [];
14
+ let newClientListeners = [];
13
15
  const router = (request, response) => {
14
16
  const headers = {
15
17
  'content-type': 'text/event-stream;charset=utf-8',
@@ -23,16 +25,19 @@ const makeLiveEventsRouter = (logLevel) => {
23
25
  return Promise.resolve();
24
26
  }
25
27
  const clientId = String(Math.random());
26
- response.write(serializeMessage({ type: 'init', clientId }));
28
+ const { undoFile, redoFile } = getInitialUndoRedoState();
29
+ response.write(serializeMessage({ type: 'init', clientId, undoFile, redoFile }));
27
30
  const newClient = {
28
31
  id: clientId,
29
32
  response,
30
33
  };
31
34
  clients.push(newClient);
35
+ newClientListeners.forEach((cb) => cb());
32
36
  if (printPortMessageTimeout) {
33
37
  clearTimeout(printPortMessageTimeout);
34
38
  }
35
39
  request.on('close', () => {
40
+ (0, default_props_watchers_1.unsubscribeClientDefaultPropsWatchers)(clientId);
36
41
  (0, file_existence_watchers_1.unsubscribeClientFileExistenceWatchers)(clientId);
37
42
  (0, sequence_props_watchers_1.unsubscribeClientSequencePropsWatchers)(clientId);
38
43
  clients = clients.filter((client) => client.id !== clientId);
@@ -53,9 +58,23 @@ const makeLiveEventsRouter = (logLevel) => {
53
58
  client.response.write(serializeMessage(event));
54
59
  });
55
60
  };
61
+ const sendEventToClientId = (clientId, event) => {
62
+ const client = clients.find((c) => c.id === clientId);
63
+ if (client) {
64
+ client.response.write(serializeMessage(event));
65
+ }
66
+ };
67
+ const addNewClientListener = (cb) => {
68
+ newClientListeners.push(cb);
69
+ return () => {
70
+ newClientListeners = newClientListeners.filter((l) => l !== cb);
71
+ };
72
+ };
56
73
  return {
57
74
  sendEventToClient,
75
+ sendEventToClientId,
58
76
  router,
77
+ addNewClientListener,
59
78
  closeConnections: () => {
60
79
  return Promise.all(clients.map((client) => {
61
80
  return new Promise((resolve) => {
@@ -5,6 +5,7 @@ const node_fs_1 = require("node:fs");
5
5
  const renderer_1 = require("@remotion/renderer");
6
6
  const duplicate_composition_1 = require("../../codemods/duplicate-composition");
7
7
  const simple_diff_1 = require("../../codemods/simple-diff");
8
+ const file_watcher_1 = require("../../file-watcher");
8
9
  const project_info_1 = require("../project-info");
9
10
  const can_update_default_props_1 = require("./can-update-default-props");
10
11
  const applyCodemodHandler = async ({ input: { codemod, dryRun }, logLevel, remotionRoot, entryPoint }) => {
@@ -26,7 +27,7 @@ const applyCodemodHandler = async ({ input: { codemod, dryRun }, logLevel, remot
26
27
  newLines: formatted.split('\n'),
27
28
  });
28
29
  if (!dryRun) {
29
- (0, node_fs_1.writeFileSync)(projectInfo.rootFile, formatted);
30
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, formatted);
30
31
  const end = Date.now() - time;
31
32
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blue(`Edited root file in ${end}ms`));
32
33
  }
@@ -1,4 +1,37 @@
1
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
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -6,9 +39,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.applyVisualControlHandler = void 0;
7
40
  const node_fs_1 = require("node:fs");
8
41
  const node_path_1 = __importDefault(require("node:path"));
42
+ const renderer_1 = require("@remotion/renderer");
9
43
  const parse_ast_1 = require("../../codemods/parse-ast");
10
44
  const recast_mods_1 = require("../../codemods/recast-mods");
11
- const applyVisualControlHandler = ({ input: { fileName, changes }, remotionRoot }) => {
45
+ const file_watcher_1 = require("../../file-watcher");
46
+ const make_link_1 = require("../../hyperlinks/make-link");
47
+ const live_events_1 = require("../live-events");
48
+ const undo_stack_1 = require("../undo-stack");
49
+ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
50
+ const log_update_1 = require("./log-update");
51
+ const applyVisualControlHandler = async ({ input: { fileName, changes }, remotionRoot, logLevel }) => {
52
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[apply-visual-control] Received request for ${fileName} with ${changes.length} changes`);
12
53
  const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
13
54
  const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
14
55
  if (fileRelativeToRoot.startsWith('..')) {
@@ -26,10 +67,67 @@ const applyVisualControlHandler = ({ input: { fileName, changes }, remotionRoot
26
67
  if (changesMade.length === 0) {
27
68
  throw new Error('No changes were made to the file');
28
69
  }
29
- const output = (0, parse_ast_1.serializeAst)(newAst);
30
- (0, node_fs_1.writeFileSync)(absolutePath, output);
31
- return Promise.resolve({
32
- success: true,
70
+ let output = (0, parse_ast_1.serializeAst)(newAst);
71
+ let formatted = false;
72
+ try {
73
+ const prettier = await Promise.resolve().then(() => __importStar(require('prettier')));
74
+ const { format, resolveConfig, resolveConfigFile } = prettier;
75
+ const configFilePath = await resolveConfigFile();
76
+ if (configFilePath) {
77
+ const prettierConfig = await resolveConfig(configFilePath);
78
+ if (prettierConfig) {
79
+ output = await format(output, {
80
+ ...prettierConfig,
81
+ filepath: 'test.tsx',
82
+ plugins: [],
83
+ endOfLine: 'auto',
84
+ });
85
+ formatted = true;
86
+ }
87
+ }
88
+ }
89
+ catch (_a) {
90
+ // Prettier not available, use unformatted output
91
+ }
92
+ (0, undo_stack_1.pushToUndoStack)({
93
+ filePath: absolutePath,
94
+ oldContents: fileContents,
95
+ logLevel,
96
+ remotionRoot,
97
+ description: {
98
+ undoMessage: 'Undid visual control change',
99
+ redoMessage: 'Redid visual control change',
100
+ },
101
+ entryType: 'visual-control',
33
102
  });
103
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
104
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
105
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output);
106
+ (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
107
+ listener.sendEventToClient({
108
+ type: 'visual-control-values-changed',
109
+ values: changes.map((change) => ({
110
+ id: change.id,
111
+ value: change.newValueIsUndefined
112
+ ? null
113
+ : JSON.parse(change.newValueSerialized),
114
+ isUndefined: change.newValueIsUndefined,
115
+ })),
116
+ });
117
+ });
118
+ const locationLabel = `${fileRelativeToRoot}`;
119
+ const fileLink = (0, make_link_1.makeHyperlink)({
120
+ url: `file://${absolutePath}`,
121
+ text: locationLabel,
122
+ fallback: locationLabel,
123
+ });
124
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} Applied visual control changes`);
125
+ if (!formatted) {
126
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
127
+ }
128
+ (0, undo_stack_1.printUndoHint)(logLevel);
129
+ return {
130
+ success: true,
131
+ };
34
132
  };
35
133
  exports.applyVisualControlHandler = applyVisualControlHandler;
@@ -1,4 +1,11 @@
1
- import type { CanUpdateDefaultPropsRequest, CanUpdateDefaultPropsResponse } from '@remotion/studio-shared';
2
- import type { ApiHandler } from '../api-types';
1
+ import type { CanUpdateDefaultPropsResponse } from '@remotion/studio-shared';
3
2
  export declare const checkIfTypeScriptFile: (file: string) => void;
4
- export declare const canUpdateDefaultPropsHandler: ApiHandler<CanUpdateDefaultPropsRequest, CanUpdateDefaultPropsResponse>;
3
+ export declare const computeCanUpdateDefaultPropsFromContent: (content: string, compositionId: string) => CanUpdateDefaultPropsResponse;
4
+ export declare const computeCanUpdateDefaultProps: ({ compositionId, remotionRoot, entryPoint, }: {
5
+ compositionId: string;
6
+ remotionRoot: string;
7
+ entryPoint: string;
8
+ }) => Promise<{
9
+ result: CanUpdateDefaultPropsResponse;
10
+ rootFile: string | null;
11
+ }>;