@hyperframes/studio-server 0.8.150 → 0.8.152

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  realpath
3
- } from "./chunk-M62HDRLX.js";
3
+ } from "./chunk-K56J3CL7.js";
4
4
 
5
5
  // src/helpers/mediaCodecMap.ts
6
6
  import { scanHtmlOpeningTags, decodeAuthoredAttribute } from "@hyperframes/parsers";
@@ -307,11 +307,20 @@ function setElementDuration(el, start, duration, trackIndex) {
307
307
  ...trackIndex != null ? { trackIndex } : {}
308
308
  });
309
309
  }
310
+ function isWindowOf(media, row) {
311
+ if (media.duration <= 0) return false;
312
+ const near = (a, b) => Math.abs(a - b) < 1e-3;
313
+ return !row || near(media.start, row.start) && near(media.duration, row.duration);
314
+ }
310
315
  function splitElementInHtml(source, target, splitTime, newId, fallbackTiming) {
311
316
  const { document, wrappedFragment } = parseSourceDocument(source);
312
317
  const el = findTargetElement(document, target);
313
318
  if (!el || !isHTMLElement(el)) return { html: source, matched: false, newId: null };
314
- const timing = resolveElementTiming(el);
319
+ const timedMediaSelector = "video[data-start], audio[data-start]";
320
+ const innerMedia = el.hasAttribute("data-start") || resolveElementTiming(el).duration > 0 || el.matches("[data-composition-src], [data-composition-id]") ? null : el.querySelector(timedMediaSelector);
321
+ const timedMedia = innerMedia && isWindowOf(resolveElementTiming(innerMedia), fallbackTiming) ? innerMedia : null;
322
+ const timed = timedMedia ?? el;
323
+ const timing = resolveElementTiming(timed);
315
324
  let { start, duration } = timing;
316
325
  if (duration <= 0 && fallbackTiming && fallbackTiming.duration > 0) {
317
326
  start = fallbackTiming.start;
@@ -329,16 +338,22 @@ function splitElementInHtml(source, target, splitTime, newId, fallbackTiming) {
329
338
  dedupeClonedCompositionId(document, clone);
330
339
  clone.removeAttribute("data-hf-id");
331
340
  for (const node of clone.querySelectorAll("[data-hf-id]")) node.removeAttribute("data-hf-id");
332
- setElementDuration(clone, splitTime, secondDuration, fallbackTiming?.track);
333
- const playbackStartAttr = el.hasAttribute("data-playback-start") ? "data-playback-start" : el.hasAttribute("data-media-start") ? "data-media-start" : el.matches("[data-composition-src], [data-composition-id]") ? "data-playback-start" : el.matches("audio, video") ? "data-media-start" : null;
341
+ const clonedTimed = timedMedia ? clone.querySelector(timedMediaSelector) : clone;
342
+ if (timedMedia?.id) {
343
+ const mediaId = nextUniqueId(document, `${timedMedia.id}-split`, /* @__PURE__ */ new Set([newId]));
344
+ duplicateCssRulesForId(document, timedMedia.id, mediaId);
345
+ clonedTimed.setAttribute("id", mediaId);
346
+ }
347
+ setElementDuration(clonedTimed, splitTime, secondDuration, fallbackTiming?.track);
348
+ const playbackStartAttr = timed.hasAttribute("data-playback-start") ? "data-playback-start" : timed.hasAttribute("data-media-start") ? "data-media-start" : timed.matches("[data-composition-src], [data-composition-id]") ? "data-playback-start" : timed.matches("audio, video") ? "data-media-start" : null;
334
349
  if (playbackStartAttr) {
335
- const readAttr = (name) => el.getAttribute(name);
336
- const authoredTrim = el.getAttribute(playbackStartAttr);
350
+ const readAttr = (name) => timed.getAttribute(name);
351
+ const authoredTrim = timed.getAttribute(playbackStartAttr);
337
352
  const currentTrim = authoredTrim !== null ? readMediaOffsetSeconds(readAttr) : fallbackTiming?.playbackStart ?? 0;
338
353
  const rate = readPlaybackRate(readAttr, fallbackTiming?.playbackRate);
339
354
  if (authoredTrim === null || Number(authoredTrim) !== currentTrim)
340
- el.setAttribute(playbackStartAttr, String(Math.round(currentTrim * 1e3) / 1e3));
341
- clone.setAttribute(
355
+ timed.setAttribute(playbackStartAttr, String(Math.round(currentTrim * 1e3) / 1e3));
356
+ clonedTimed.setAttribute(
342
357
  playbackStartAttr,
343
358
  String(Math.round((currentTrim + firstDuration * rate) * 1e3) / 1e3)
344
359
  );
@@ -347,7 +362,7 @@ function splitElementInHtml(source, target, splitTime, newId, fallbackTiming) {
347
362
  if (originalId) {
348
363
  duplicateCssRulesForId(document, originalId, newId);
349
364
  }
350
- setElementDuration(el, start, firstDuration, fallbackTiming?.track);
365
+ setElementDuration(timed, start, firstDuration, fallbackTiming?.track);
351
366
  if (el.nextSibling) {
352
367
  el.parentElement.insertBefore(clone, el.nextSibling);
353
368
  } else {
@@ -2,12 +2,12 @@ import {
2
2
  PROXY_VARIANT_CONFIG,
3
3
  probeFirstFrameColour,
4
4
  probeMediaMetadata
5
- } from "./chunk-EJC7TX3O.js";
5
+ } from "./chunk-FKJBNFWA.js";
6
6
  import {
7
7
  mkdirWithinProject,
8
8
  realProjectRoot,
9
9
  realpath
10
- } from "./chunk-M62HDRLX.js";
10
+ } from "./chunk-K56J3CL7.js";
11
11
 
12
12
  // src/helpers/proxyTranscoder.ts
13
13
  import { spawn } from "child_process";
@@ -42,7 +42,12 @@ function isPrivateProjectFile(projectDir, filePath) {
42
42
  );
43
43
  }
44
44
  function pinWithinProject(base, relativePath) {
45
- const checked = resolveWithinProject(base, relativePath);
45
+ return pinResolved(base, resolveWithinProject(base, relativePath));
46
+ }
47
+ function pinProjectRecord(base, relativePath) {
48
+ return pinResolved(base, resolveInProject(base, relativePath));
49
+ }
50
+ function pinResolved(base, checked) {
46
51
  if (!checked) return null;
47
52
  const inside = relative(realFilePath(base), realFilePath(checked));
48
53
  const escapes = inside === ".." || inside.startsWith(`..${sep}`) || isAbsolute(inside);
@@ -91,6 +96,7 @@ export {
91
96
  isPrivateProjectPath,
92
97
  isPrivateProjectFile,
93
98
  pinWithinProject,
99
+ pinProjectRecord,
94
100
  isInHiddenOrVendorDir,
95
101
  walkDir,
96
102
  folderGone,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveWithinProject
3
- } from "./chunk-M62HDRLX.js";
3
+ } from "./chunk-K56J3CL7.js";
4
4
 
5
5
  // src/helpers/loudness.ts
6
6
  import { execFile } from "child_process";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  PROXY_PARAMS_VERSION,
3
3
  resolveProxy
4
- } from "./chunk-XKBQOQFZ.js";
4
+ } from "./chunk-JTPV2T3F.js";
5
5
  import {
6
6
  createMediaCodecProbeCache,
7
7
  proxyVariantFor,
8
8
  recordProxyPrewarm,
9
9
  scanProjectMediaCodecMap,
10
10
  shouldPrewarmProxy
11
- } from "./chunk-EJC7TX3O.js";
11
+ } from "./chunk-FKJBNFWA.js";
12
12
 
13
13
  // src/helpers/mediaProxyPreview.ts
14
14
  import { resolve } from "path";
@@ -2,8 +2,8 @@ import {
2
2
  isCompositionSource,
3
3
  stampFileHfIds,
4
4
  stampProjectHfIds
5
- } from "../chunk-3RUFN2CK.js";
6
- import "../chunk-M62HDRLX.js";
5
+ } from "../chunk-6RICWA3B.js";
6
+ import "../chunk-K56J3CL7.js";
7
7
  import "../chunk-SVQFE44C.js";
8
8
  import "../chunk-L3HJVTQE.js";
9
9
  export {
@@ -11,8 +11,8 @@ import {
11
11
  requiredFfmpeg,
12
12
  resolveLocalAudioPath,
13
13
  updateAudioVolume
14
- } from "../chunk-VMT4OC5B.js";
15
- import "../chunk-M62HDRLX.js";
14
+ } from "../chunk-KR3B6IJC.js";
15
+ import "../chunk-K56J3CL7.js";
16
16
  import "../chunk-SVQFE44C.js";
17
17
  import "../chunk-L3HJVTQE.js";
18
18
  export {
@@ -13,8 +13,8 @@ import {
13
13
  resolveProxyVariantRequest,
14
14
  scanProjectMediaCodecMap,
15
15
  shouldPrewarmProxy
16
- } from "../chunk-EJC7TX3O.js";
17
- import "../chunk-M62HDRLX.js";
16
+ } from "../chunk-FKJBNFWA.js";
17
+ import "../chunk-K56J3CL7.js";
18
18
  import "../chunk-SVQFE44C.js";
19
19
  import "../chunk-L3HJVTQE.js";
20
20
  export {
@@ -1,6 +1,6 @@
1
1
  import '@hyperframes/core';
2
- export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-BR7yXz2M.js';
2
+ export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-DB1EEdxc.js';
3
3
  import './mediaCodecMap.js';
4
4
  import '@hyperframes/parsers';
5
5
  import '@hyperframes/core/compiler';
6
- import '../projectHistory-CyTVYz2y.js';
6
+ import '../projectHistory-C5dpCjPU.js';
@@ -4,10 +4,10 @@ import {
4
4
  isAutoProxyEnabled,
5
5
  proxyEtagSalt,
6
6
  resolvePreviewMediaCodecProbeCache
7
- } from "../chunk-ZNRTEXK2.js";
8
- import "../chunk-XKBQOQFZ.js";
9
- import "../chunk-EJC7TX3O.js";
10
- import "../chunk-M62HDRLX.js";
7
+ } from "../chunk-RHYH6YOX.js";
8
+ import "../chunk-JTPV2T3F.js";
9
+ import "../chunk-FKJBNFWA.js";
10
+ import "../chunk-K56J3CL7.js";
11
11
  import "../chunk-SVQFE44C.js";
12
12
  import "../chunk-L3HJVTQE.js";
13
13
  export {
@@ -16,9 +16,9 @@ import {
16
16
  resolveProxies,
17
17
  resolveProxy,
18
18
  waitForProxy
19
- } from "../chunk-XKBQOQFZ.js";
20
- import "../chunk-EJC7TX3O.js";
21
- import "../chunk-M62HDRLX.js";
19
+ } from "../chunk-JTPV2T3F.js";
20
+ import "../chunk-FKJBNFWA.js";
21
+ import "../chunk-K56J3CL7.js";
22
22
  import "../chunk-SVQFE44C.js";
23
23
  import "../chunk-L3HJVTQE.js";
24
24
  export {
@@ -12,6 +12,8 @@ declare function isPrivateProjectFile(projectDir: string, filePath: string): boo
12
12
  * file checked here even if a link on the way is retargeted before the write.
13
13
  */
14
14
  declare function pinWithinProject(base: string, relativePath: string): string | null;
15
+ /** `pinWithinProject` for the app's and the CLI's own records under `.hyperframes/`, which no route serves. */
16
+ declare function pinProjectRecord(base: string, relativePath: string): string | null;
15
17
  /**
16
18
  * True when any directory segment of a relative path is a dot-directory or
17
19
  * node_modules. Projects that vendor tooling assets under dot-directories
@@ -24,4 +26,4 @@ declare function isInHiddenOrVendorDir(relPath: string): boolean;
24
26
  * or removed mid-walk is skipped; any other failure, or an unreadable `dir` itself, throws. */
25
27
  declare function walkDir(dir: string, prefix?: string): string[];
26
28
 
27
- export { isInHiddenOrVendorDir, isPrivateProjectFile, isPrivateProjectPath, pinWithinProject, realFilePath, resolveWithinProject, walkDir };
29
+ export { isInHiddenOrVendorDir, isPrivateProjectFile, isPrivateProjectPath, pinProjectRecord, pinWithinProject, realFilePath, resolveWithinProject, walkDir };
@@ -6,13 +6,14 @@ import {
6
6
  isProjectRootMissing,
7
7
  isSafePath,
8
8
  mkdirWithinProject,
9
+ pinProjectRecord,
9
10
  pinWithinProject,
10
11
  realFilePath,
11
12
  realProjectRoot,
12
13
  realpath,
13
14
  resolveWithinProject,
14
15
  walkDir
15
- } from "../chunk-M62HDRLX.js";
16
+ } from "../chunk-K56J3CL7.js";
16
17
  import "../chunk-SVQFE44C.js";
17
18
  import "../chunk-L3HJVTQE.js";
18
19
  export {
@@ -23,6 +24,7 @@ export {
23
24
  isProjectRootMissing,
24
25
  isSafePath,
25
26
  mkdirWithinProject,
27
+ pinProjectRecord,
26
28
  pinWithinProject,
27
29
  realFilePath,
28
30
  realProjectRoot,
@@ -13,7 +13,7 @@ import {
13
13
  splitElementInHtml,
14
14
  unwrapElementsFromHtml,
15
15
  wrapElementsInHtml
16
- } from "../chunk-Z5UJMFO4.js";
16
+ } from "../chunk-JBFOY5SI.js";
17
17
  export {
18
18
  dedupeClonedCompositionId,
19
19
  findTargetElement,
@@ -1,5 +1,5 @@
1
- import { P as ProjectHistory } from '../projectHistory-CyTVYz2y.js';
2
- export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryResult, f as HistoryWho, g as HistoryWindow, M as MAX_WINDOW_IDLE_MS, h as ProjectHistoryOptions, i as ProjectHistoryView, U as UNDO_MODES, j as UndoMode, o as openProjectHistory, r as readProjectHistory } from '../projectHistory-CyTVYz2y.js';
1
+ import { P as ProjectHistory, f as HistoryTarget, g as HistoryWho } from '../projectHistory-C5dpCjPU.js';
2
+ export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryResult, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from '../projectHistory-C5dpCjPU.js';
3
3
 
4
4
  declare class HistoryBusyError extends Error {
5
5
  readonly pid: number;
@@ -46,4 +46,91 @@ interface PrunedHistory {
46
46
  /** Removes the histories whose project is gone and that no live process holds. */
47
47
  declare function pruneGoneProjectHistories(historyRoot: string, options?: PruneOptions): Promise<PrunedHistory[]>;
48
48
 
49
- export { HistoryBusyError, HistoryIdError, ProjectHistory, type ProjectHistoryRecord, type PrunedHistory, historyCache, listProjectHistories, pruneGoneProjectHistories };
49
+ interface PendingArtifactCleanup {
50
+ path: string;
51
+ hash: string;
52
+ revision: string;
53
+ id: string;
54
+ kind: "checks" | "snapshots";
55
+ }
56
+
57
+ interface FileVersion {
58
+ hash: string;
59
+ content: string;
60
+ }
61
+ interface RevisionState {
62
+ targets?: HistoryTarget[];
63
+ actor: HistoryWho;
64
+ label: string;
65
+ startedAt: number;
66
+ endedAt: number;
67
+ undoes?: string;
68
+ restoredTo?: string;
69
+ files: Record<string, {
70
+ before: string | null;
71
+ after: string | null;
72
+ }>;
73
+ }
74
+ interface ArtifactInput {
75
+ kind: "check" | "snapshot";
76
+ id: string;
77
+ scope: string;
78
+ report?: string;
79
+ image?: string;
80
+ time?: number;
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+ interface ArtifactRecord extends Omit<ArtifactInput, "kind"> {
84
+ status?: "cleaned";
85
+ cleanedAfterRender?: string;
86
+ createdAt: number;
87
+ contentHash: string;
88
+ revision: string | null;
89
+ inputFingerprint: string;
90
+ inputScope: "local-project-files";
91
+ attribution: "recorded-revision" | "unversioned" | "inputs-changed";
92
+ }
93
+ interface ArtifactCollection {
94
+ latest: {
95
+ revision: string | null;
96
+ id: string;
97
+ } | null;
98
+ revisions: Record<string, ArtifactRecord[]>;
99
+ unversioned: ArtifactRecord[];
100
+ }
101
+ interface RenderRecord {
102
+ revision?: string | null;
103
+ id: string;
104
+ completedAt: number;
105
+ output: string;
106
+ status: "completed" | "completed_with_warnings";
107
+ }
108
+ interface VideoState {
109
+ version: 1;
110
+ historyId: string | null;
111
+ currentRevision: string | null;
112
+ pendingChanges: boolean;
113
+ files: Record<string, FileVersion>;
114
+ revisions: Record<string, RevisionState>;
115
+ checks: ArtifactCollection;
116
+ snapshots: ArtifactCollection;
117
+ renders?: {
118
+ latest: RenderRecord | null;
119
+ retainedRevisions?: string[];
120
+ };
121
+ pendingArtifactCleanup?: PendingArtifactCleanup[];
122
+ }
123
+ interface ArtifactCapture {
124
+ revision: string | null;
125
+ fingerprint: string;
126
+ }
127
+ declare function beginArtifactCapture(projectDir: string): Promise<ArtifactCapture>;
128
+ declare function recordArtifact(projectDir: string, capture: ArtifactCapture, artifact: ArtifactInput): Promise<ArtifactRecord[]>;
129
+ declare function recordArtifacts(projectDir: string, capture: ArtifactCapture, artifactsToRecord: readonly ArtifactInput[]): Promise<ArtifactRecord[]>;
130
+ declare function forgetRecordedArtifacts(projectDir: string, paths: readonly string[]): Promise<void>;
131
+ declare function artifactDirectory(projectDir: string, kind: "checks" | "snapshots"): string;
132
+ declare function recordRenderSuccess(projectDir: string, output: string, status?: RenderRecord["status"], capture?: ArtifactCapture): Promise<RenderRecord>;
133
+
134
+ declare function registerRenderOutput(projectDir: string, output: string): Promise<void>;
135
+
136
+ export { type ArtifactCapture, type ArtifactInput, type ArtifactRecord, HistoryBusyError, HistoryIdError, HistoryTarget, HistoryWho, ProjectHistory, type ProjectHistoryRecord, type PrunedHistory, type RenderRecord, type VideoState, artifactDirectory, beginArtifactCapture, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput };
@@ -6,13 +6,20 @@ import {
6
6
  MAX_WINDOW_IDLE_MS,
7
7
  START,
8
8
  UNDO_MODES,
9
+ artifactDirectory,
10
+ beginArtifactCapture,
11
+ forgetRecordedArtifacts,
9
12
  historyCache,
10
13
  listProjectHistories,
11
14
  openProjectHistory,
12
15
  pruneGoneProjectHistories,
13
- readProjectHistory
14
- } from "../chunk-Y7V6FJHS.js";
15
- import "../chunk-M62HDRLX.js";
16
+ readProjectHistory,
17
+ recordArtifact,
18
+ recordArtifacts,
19
+ recordRenderSuccess,
20
+ registerRenderOutput
21
+ } from "../chunk-CW5G6XXR.js";
22
+ import "../chunk-K56J3CL7.js";
16
23
  import "../chunk-SVQFE44C.js";
17
24
  import "../chunk-L3HJVTQE.js";
18
25
  export {
@@ -23,9 +30,16 @@ export {
23
30
  HistoryIdError,
24
31
  MAX_WINDOW_IDLE_MS,
25
32
  UNDO_MODES,
33
+ artifactDirectory,
34
+ beginArtifactCapture,
35
+ forgetRecordedArtifacts,
26
36
  historyCache,
27
37
  listProjectHistories,
28
38
  openProjectHistory,
29
39
  pruneGoneProjectHistories,
30
- readProjectHistory
40
+ readProjectHistory,
41
+ recordArtifact,
42
+ recordArtifacts,
43
+ recordRenderSuccess,
44
+ registerRenderOutput
31
45
  };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Hono } from 'hono';
2
- import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-BR7yXz2M.js';
3
- export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-BR7yXz2M.js';
4
- export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryResult, f as HistoryWho, g as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, h as ProjectHistoryOptions, i as ProjectHistoryView, U as UNDO_MODES, j as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-CyTVYz2y.js';
5
- export { HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, historyCache, listProjectHistories, pruneGoneProjectHistories } from './history/index.js';
2
+ import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-DB1EEdxc.js';
3
+ export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-DB1EEdxc.js';
4
+ export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryResult, f as HistoryTarget, g as HistoryWho, h as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, i as ProjectHistoryOptions, j as ProjectHistoryView, U as UNDO_MODES, k as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-C5dpCjPU.js';
5
+ export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput } from './history/index.js';
6
6
  export { CACHE_DIR_NAME as PROXY_CACHE_DIR_NAME } from './helpers/proxyTranscoder.js';
7
7
  export { walkDir } from './helpers/safePath.js';
8
8
  export { stampProjectHfIds } from './helpers/hfIdPersist.js';
package/dist/index.js CHANGED
@@ -17,11 +17,11 @@ import {
17
17
  splitElementInHtml,
18
18
  unwrapElementsFromHtml,
19
19
  wrapElementsInHtml
20
- } from "./chunk-Z5UJMFO4.js";
20
+ } from "./chunk-JBFOY5SI.js";
21
21
  import {
22
22
  isCompositionSource,
23
23
  stampProjectHfIds
24
- } from "./chunk-3RUFN2CK.js";
24
+ } from "./chunk-6RICWA3B.js";
25
25
  import {
26
26
  DEFAULT_HISTORY_ROOT,
27
27
  DELETED_VERSION,
@@ -33,22 +33,29 @@ import {
33
33
  STUDIO_SIGNATURE_MANIFEST_PATHS,
34
34
  UNDO_MODES,
35
35
  affectsProjectSignature,
36
+ artifactDirectory,
37
+ beginArtifactCapture,
36
38
  clearFileWriteReceipt,
37
39
  consumeFileWriteReceipt,
38
40
  createProjectSignature,
39
41
  createWriteToken,
40
42
  fileContentVersion,
43
+ forgetRecordedArtifacts,
41
44
  historyCache,
42
45
  identifyFileWrite,
43
46
  listProjectHistories,
44
47
  openProjectHistory,
45
48
  pruneGoneProjectHistories,
46
49
  readProjectHistory,
50
+ recordArtifact,
51
+ recordArtifacts,
47
52
  recordFileWriteReceipt,
53
+ recordRenderSuccess,
54
+ registerRenderOutput,
48
55
  resolveProjectAndSignature,
49
56
  resolveProjectSignature,
50
57
  settledFileTag
51
- } from "./chunk-Y7V6FJHS.js";
58
+ } from "./chunk-CW5G6XXR.js";
52
59
  import {
53
60
  clearElementScreenshotIsolation,
54
61
  getElementScreenshotClip
@@ -62,13 +69,13 @@ import {
62
69
  requestedProjectPath,
63
70
  requiredFfmpeg,
64
71
  resolveLocalAudioPath
65
- } from "./chunk-VMT4OC5B.js";
72
+ } from "./chunk-KR3B6IJC.js";
66
73
  import {
67
74
  injectMediaCodecMap,
68
75
  isAutoProxyEnabled,
69
76
  proxyEtagSalt,
70
77
  resolvePreviewMediaCodecProbeCache
71
- } from "./chunk-ZNRTEXK2.js";
78
+ } from "./chunk-RHYH6YOX.js";
72
79
  import {
73
80
  CACHE_DIR_NAME,
74
81
  PROXY_PENDING_RETRY_AFTER_SECONDS,
@@ -79,7 +86,7 @@ import {
79
86
  proxyActivityMark,
80
87
  resolveProxy,
81
88
  waitForProxy
82
- } from "./chunk-XKBQOQFZ.js";
89
+ } from "./chunk-JTPV2T3F.js";
83
90
  import {
84
91
  PROXY_VARIANT_CONFIG,
85
92
  decideMediaProxyEligibility,
@@ -88,7 +95,7 @@ import {
88
95
  probeMediaMetadata,
89
96
  recordProxyRequest,
90
97
  resolveProxyVariantRequest
91
- } from "./chunk-EJC7TX3O.js";
98
+ } from "./chunk-FKJBNFWA.js";
92
99
  import {
93
100
  folderGone,
94
101
  isInHiddenOrVendorDir,
@@ -102,7 +109,7 @@ import {
102
109
  realpath,
103
110
  resolveWithinProject,
104
111
  walkDir
105
- } from "./chunk-M62HDRLX.js";
112
+ } from "./chunk-K56J3CL7.js";
106
113
  import {
107
114
  STUDIO_MANUAL_EDITS_PATH,
108
115
  createStudioManualEditsRenderBodyScript,
@@ -6368,6 +6375,29 @@ function versionsOf(value) {
6368
6375
  );
6369
6376
  return pairs.length ? Object.fromEntries(pairs) : void 0;
6370
6377
  }
6378
+ function targetsOf(value) {
6379
+ if (!Array.isArray(value)) return void 0;
6380
+ const targets = value.flatMap((item) => targetOf2(item) ?? []);
6381
+ return targets.length ? targets : void 0;
6382
+ }
6383
+ function targetOf2(item) {
6384
+ if (!item || typeof item !== "object") return null;
6385
+ const fields = item;
6386
+ if (typeof fields.file !== "string") return null;
6387
+ const target = { file: fields.file, ...identityOf(fields) };
6388
+ if (!target.id && !target.hfId && !target.selector) return null;
6389
+ if (isSelectorIndex(fields.selectorIndex)) target.selectorIndex = fields.selectorIndex;
6390
+ return target;
6391
+ }
6392
+ function identityOf(fields) {
6393
+ const identity = {};
6394
+ for (const key of ["id", "hfId", "selector"]) {
6395
+ const field = fields[key];
6396
+ if (typeof field === "string" && field) identity[key] = field;
6397
+ }
6398
+ return identity;
6399
+ }
6400
+ var isSelectorIndex = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
6371
6401
  function nextStep(history, direction) {
6372
6402
  const target = history.next(direction, YOU);
6373
6403
  if (!target) return null;
@@ -6393,6 +6423,13 @@ function registerHistoryRoutes(api, adapter) {
6393
6423
  return { entries, back: nextStep(history, "back"), forward: nextStep(history, "forward") };
6394
6424
  })
6395
6425
  );
6426
+ api.post(
6427
+ `${base}/checkpoint`,
6428
+ (c) => withHistory(adapter, c, async (history) => {
6429
+ await history.checkpoint();
6430
+ return { ok: true };
6431
+ })
6432
+ );
6396
6433
  api.post(
6397
6434
  `${base}/step`,
6398
6435
  (c) => withHistory(
@@ -6441,9 +6478,11 @@ function registerHistoryRoutes(api, adapter) {
6441
6478
  const paths = Array.isArray(body.paths) ? body.paths.filter((path) => text(path)) : [];
6442
6479
  const coalesceKey = text(body.coalesceKey) ?? void 0;
6443
6480
  const overwrote = versionsOf(body.overwrote);
6481
+ const targets = targetsOf(body.targets);
6444
6482
  const claimed = await history.claim(YOU, text(body.label) ?? "Edited in Studio", paths, {
6445
6483
  ...coalesceKey && { coalesceKey, idleMs: idleOf(body) ?? Infinity },
6446
- ...overwrote && { overwrote }
6484
+ ...overwrote && { overwrote },
6485
+ ...targets && { targets }
6447
6486
  });
6448
6487
  return { claimed };
6449
6488
  })
@@ -6455,7 +6494,10 @@ function registerHistoryRoutes(api, adapter) {
6455
6494
  const window = await history.beginWindow(
6456
6495
  whoOf(body),
6457
6496
  text(body.label) ?? "Edited in Studio",
6458
- idleMs ? { idleMs } : void 0
6497
+ {
6498
+ ...idleMs ? { idleMs } : {},
6499
+ ...body.exclusive === true && { exclusive: true }
6500
+ }
6459
6501
  );
6460
6502
  windows.set(window.id, { history, window });
6461
6503
  return { windowId: window.id, startedAt: window.startedAt };
@@ -6687,6 +6729,8 @@ export {
6687
6729
  affectsPreview,
6688
6730
  affectsProjectSignature,
6689
6731
  applyFileMutations,
6732
+ artifactDirectory,
6733
+ beginArtifactCapture,
6690
6734
  buildSubCompositionHtml,
6691
6735
  cleanupProxyCache,
6692
6736
  clearElementScreenshotIsolation,
@@ -6704,6 +6748,7 @@ export {
6704
6748
  duplicateElementInHtml,
6705
6749
  fileContentVersion,
6706
6750
  findTargetElement,
6751
+ forgetRecordedArtifacts,
6707
6752
  getElementScreenshotClip,
6708
6753
  getMimeType,
6709
6754
  historyCache,
@@ -6715,6 +6760,10 @@ export {
6715
6760
  patchElementInHtml,
6716
6761
  pruneGoneProjectHistories,
6717
6762
  readProjectHistory,
6763
+ recordArtifact,
6764
+ recordArtifacts,
6765
+ recordRenderSuccess,
6766
+ registerRenderOutput,
6718
6767
  removeElementFromHtml,
6719
6768
  requestSubPath,
6720
6769
  settledFileTag,
@@ -2,7 +2,7 @@ import * as _hyperframes_core from '@hyperframes/core';
2
2
  import { RegistryItem, PreviewProxyBox } from '@hyperframes/core';
3
3
  import { CanvasResolution } from '@hyperframes/parsers';
4
4
  import { BundleOptions } from '@hyperframes/core/compiler';
5
- import { P as ProjectHistory } from './projectHistory-CyTVYz2y.js';
5
+ import { P as ProjectHistory } from './projectHistory-C5dpCjPU.js';
6
6
  import { MediaCodecProbeCache, HtmlSourceLike } from './helpers/mediaCodecMap.js';
7
7
 
8
8
  /** Resolved info about a single project. */
@@ -10,7 +10,15 @@ interface HistoryFileChange {
10
10
  after: string | null;
11
11
  }
12
12
  type HistoryEntrySide = "before" | "after";
13
+ interface HistoryTarget {
14
+ file: string;
15
+ id?: string;
16
+ hfId?: string;
17
+ selector?: string;
18
+ selectorIndex?: number;
19
+ }
13
20
  interface HistoryEntry {
21
+ targets?: HistoryTarget[];
14
22
  id: string;
15
23
  who: HistoryWho;
16
24
  label: string;
@@ -44,10 +52,12 @@ interface ProjectHistoryOptions {
44
52
  ownerWaitMs?: number;
45
53
  /** A CLI turn's window from an earlier open: writes since, within its idle limit, become the entry with its id. */
46
54
  closedWindow?: ClosedWindow;
55
+ closedWindowAfterOwnership?: () => ClosedWindow | undefined;
47
56
  undoScope?: "own" | "everyone";
48
57
  pruneGoneProjectsBudgetMs?: number;
49
58
  }
50
59
  interface ClaimOptions {
60
+ targets?: readonly HistoryTarget[];
51
61
  coalesceKey?: string;
52
62
  idleMs?: number;
53
63
  /** Per path, the version (fileContentVersion) the claimer overwrote: earlier changes stay their writer's. */
@@ -94,6 +104,7 @@ interface ProjectHistory {
94
104
  * part so far first (fresh id), returned by close() if nothing else remained. Overlaps go to the newest. */
95
105
  beginWindow(who: HistoryWho, label: string, options?: {
96
106
  idleMs?: number;
107
+ exclusive?: boolean;
97
108
  }): Promise<HistoryWindow>;
98
109
  /**
99
110
  * For a writer that records after writing (Studio): moves the uncommitted changes to `paths` into one entry of
@@ -124,6 +135,7 @@ interface ProjectHistory {
124
135
  pin(id: string, pinned: boolean): void;
125
136
  onEntry(listener: (entry: HistoryEntry) => void): () => void;
126
137
  /** Takes in every pending write and commits every open window and the outside group. */
138
+ checkpoint(): Promise<void>;
127
139
  flush(): Promise<void>;
128
140
  /** True once another project stands at the folder's path: open that one's history instead. */
129
141
  replacedAtPath(): boolean;
@@ -144,4 +156,4 @@ interface ProjectHistoryView {
144
156
  /** Reads only: takes no lock and files, prunes or writes nothing; an owner's half-appended last line is skipped. */
145
157
  declare function readProjectHistory(options: Pick<ProjectHistoryOptions, "projectDir" | "historyRoot">): ProjectHistoryView;
146
158
 
147
- export { type ClosedWindow as C, DEFAULT_HISTORY_ROOT as D, HistoryClosedError as H, MAX_WINDOW_IDLE_MS as M, type ProjectHistory as P, START as S, UNDO_MODES as U, type HistoryEntry as a, type HistoryEntrySide as b, type HistoryFileChange as c, type HistoryListItem as d, type HistoryResult as e, type HistoryWho as f, type HistoryWindow as g, type ProjectHistoryOptions as h, type ProjectHistoryView as i, type UndoMode as j, openProjectHistory as o, readProjectHistory as r };
159
+ export { type ClosedWindow as C, DEFAULT_HISTORY_ROOT as D, HistoryClosedError as H, MAX_WINDOW_IDLE_MS as M, type ProjectHistory as P, START as S, UNDO_MODES as U, type HistoryEntry as a, type HistoryEntrySide as b, type HistoryFileChange as c, type HistoryListItem as d, type HistoryResult as e, type HistoryTarget as f, type HistoryWho as g, type HistoryWindow as h, type ProjectHistoryOptions as i, type ProjectHistoryView as j, type UndoMode as k, openProjectHistory as o, readProjectHistory as r };