@hyperframes/studio-server 0.9.2 → 0.9.4

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.
@@ -0,0 +1,11 @@
1
+ // src/helpers/mediaRange.ts
2
+ var MAX_OPEN_MEDIA_RANGE_BYTES = 4 * 1024 * 1024;
3
+ var isMedia = (contentType) => /^(audio|video)\//i.test(contentType);
4
+ function openRangeEnd(start, last, contentType) {
5
+ return isMedia(contentType) ? Math.min(last, start + MAX_OPEN_MEDIA_RANGE_BYTES - 1) : last;
6
+ }
7
+
8
+ export {
9
+ MAX_OPEN_MEDIA_RANGE_BYTES,
10
+ openRangeEnd
11
+ };
@@ -14,36 +14,51 @@ var isCompositionSource = (html) => /data-composition-id\s*=/.test(html);
14
14
  var STAMP_RECORD = join(".hyperframes", "hf-ids-stamped.json");
15
15
  var contentHash = (text) => createHash("sha1").update(text).digest("base64url");
16
16
  function stampProjectHfIds(projectDir) {
17
+ const pass = stampPass(projectDir);
18
+ while (!pass.next().done) ;
19
+ }
20
+ async function stampProjectHfIdsAsync(projectDir) {
21
+ const pass = stampPass(projectDir);
22
+ while (!pass.next().done) await new Promise((resolve) => setImmediate(resolve));
23
+ }
24
+ function* stampPass(projectDir) {
17
25
  const recordPath = join(projectDir, STAMP_RECORD);
18
- let last = {};
19
- try {
20
- last = JSON.parse(readFileSync(recordPath, "utf-8"));
21
- } catch {
22
- }
26
+ const last = readStampRecord(recordPath);
23
27
  const next = {};
24
28
  for (const file of walkDir(projectDir)) {
25
29
  if (!file.endsWith(".html") || isInHiddenOrVendorDir(file)) continue;
26
- const absPath = join(projectDir, file);
27
- let html;
28
- try {
29
- html = readFileSync(absPath, "utf-8");
30
- } catch {
31
- continue;
32
- }
33
- let hash = contentHash(html);
34
- if (last[file] !== hash && isCompositionSource(html)) {
35
- const stamped = stampFileHfIds(absPath);
36
- if (stamped === null) continue;
37
- hash = contentHash(stamped);
38
- }
39
- next[file] = hash;
30
+ const hash = hashAfterStamp(join(projectDir, file), last[file]);
31
+ if (hash !== null) next[file] = hash;
32
+ yield;
40
33
  }
34
+ writeStampRecord(projectDir, recordPath, next);
35
+ }
36
+ function readStampRecord(recordPath) {
37
+ try {
38
+ return JSON.parse(readFileSync(recordPath, "utf-8"));
39
+ } catch {
40
+ return {};
41
+ }
42
+ }
43
+ function writeStampRecord(projectDir, recordPath, next) {
41
44
  try {
42
45
  mkdirWithinProject(projectDir, dirname(recordPath));
43
46
  writeFileSync(recordPath, JSON.stringify(next));
44
47
  } catch {
45
48
  }
46
49
  }
50
+ function hashAfterStamp(absPath, recorded) {
51
+ let html;
52
+ try {
53
+ html = readFileSync(absPath, "utf-8");
54
+ } catch {
55
+ return null;
56
+ }
57
+ const hash = contentHash(html);
58
+ if (recorded === hash || !isCompositionSource(html)) return hash;
59
+ const stamped = stampFileHfIds(absPath);
60
+ return stamped === null ? null : contentHash(stamped);
61
+ }
47
62
  function openNoFollow(filePath, flags) {
48
63
  const noFollow = constants.O_NOFOLLOW ?? 0;
49
64
  try {
@@ -93,5 +108,6 @@ function stampFileHfIds(filePath) {
93
108
  export {
94
109
  isCompositionSource,
95
110
  stampProjectHfIds,
111
+ stampProjectHfIdsAsync,
96
112
  stampFileHfIds
97
113
  };
@@ -3,6 +3,8 @@ declare const isCompositionSource: (html: string) => boolean;
3
3
  * watches the project: an id write during a session reaches Studio as an outside edit and reloads it.
4
4
  * A file whose content hash matches the last run's (kept in `.hyperframes`) is not parsed again. */
5
5
  declare function stampProjectHfIds(projectDir: string): void;
6
+ /** stampProjectHfIds for a host whose event loop must keep answering: it yields to the loop after each file. */
7
+ declare function stampProjectHfIdsAsync(projectDir: string): Promise<void>;
6
8
  /**
7
9
  * Read `filePath`, mint any missing `data-hf-id`s, write the stamped content
8
10
  * back if new ids were added, and return the stamped content. Every open of the path is
@@ -20,4 +22,4 @@ declare function stampProjectHfIds(projectDir: string): void;
20
22
  */
21
23
  declare function stampFileHfIds(filePath: string): string | null;
22
24
 
23
- export { isCompositionSource, stampFileHfIds, stampProjectHfIds };
25
+ export { isCompositionSource, stampFileHfIds, stampProjectHfIds, stampProjectHfIdsAsync };
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  isCompositionSource,
3
3
  stampFileHfIds,
4
- stampProjectHfIds
5
- } from "../chunk-FJBJJURY.js";
4
+ stampProjectHfIds,
5
+ stampProjectHfIdsAsync
6
+ } from "../chunk-7ROCGO5U.js";
6
7
  import "../chunk-QF7MFJJU.js";
7
8
  import "../chunk-SVQFE44C.js";
8
9
  import "../chunk-L3HJVTQE.js";
9
10
  export {
10
11
  isCompositionSource,
11
12
  stampFileHfIds,
12
- stampProjectHfIds
13
+ stampProjectHfIds,
14
+ stampProjectHfIdsAsync
13
15
  };
@@ -0,0 +1,4 @@
1
+ declare const MAX_OPEN_MEDIA_RANGE_BYTES: number;
2
+ declare function openRangeEnd(start: number, last: number, contentType: string): number;
3
+
4
+ export { MAX_OPEN_MEDIA_RANGE_BYTES, openRangeEnd };
@@ -0,0 +1,8 @@
1
+ import {
2
+ MAX_OPEN_MEDIA_RANGE_BYTES,
3
+ openRangeEnd
4
+ } from "../chunk-6HAB346W.js";
5
+ export {
6
+ MAX_OPEN_MEDIA_RANGE_BYTES,
7
+ openRangeEnd
8
+ };
package/dist/index.d.ts CHANGED
@@ -5,9 +5,10 @@ export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as
5
5
  export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, InPlaceOutcome, ProjectHistoryRecord, PrunedHistory, ReclaimedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, isUncopiedMedia, listProjectHistories, onRestoredInPlace, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput } 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
- export { stampProjectHfIds } from './helpers/hfIdPersist.js';
8
+ export { stampProjectHfIds, stampProjectHfIdsAsync } from './helpers/hfIdPersist.js';
9
9
  import { SourceMutationTarget } from './helpers/sourceMutation.js';
10
10
  export { PatchOperation, dedupeClonedCompositionId, findTargetElement, parseSourceDocument, patchElementInHtml, removeElementFromHtml, splitElementInHtml } from './helpers/sourceMutation.js';
11
+ export { MAX_OPEN_MEDIA_RANGE_BYTES, openRangeEnd } from './helpers/mediaRange.js';
11
12
  export { ScreenshotClip, clearElementScreenshotIsolation, getElementScreenshotClip } from './helpers/screenshotClip.js';
12
13
  export { STUDIO_MANUAL_EDITS_PATH, StudioManualEditsRenderScriptOptions, createStudioManualEditsRenderBodyScript, createStudioPositionSeekReapplyScript } from './helpers/manualEditsRenderScript.js';
13
14
  export { STUDIO_MOTION_PATH, StudioMotionRenderScriptOptions, createStudioMotionRenderBodyScript } from './helpers/studioMotionRenderScript.js';
package/dist/index.js CHANGED
@@ -20,11 +20,16 @@ import {
20
20
  } from "./chunk-LRTNNDXS.js";
21
21
  import {
22
22
  isCompositionSource,
23
- stampProjectHfIds
24
- } from "./chunk-FJBJJURY.js";
23
+ stampProjectHfIds,
24
+ stampProjectHfIdsAsync
25
+ } from "./chunk-7ROCGO5U.js";
25
26
  import {
26
27
  parseEncoderOptions
27
28
  } from "./chunk-H5AB5322.js";
29
+ import {
30
+ MAX_OPEN_MEDIA_RANGE_BYTES,
31
+ openRangeEnd
32
+ } from "./chunk-6HAB346W.js";
28
33
  import {
29
34
  DEFAULT_HISTORY_ROOT,
30
35
  DELETED_VERSION,
@@ -4674,7 +4679,7 @@ ${etag}`;
4674
4679
  const match = rangeHeader ? /bytes=(\d+)-(\d*)/.exec(rangeHeader) : null;
4675
4680
  if (match) {
4676
4681
  const start = parseInt(match[1], 10);
4677
- const end = match[2] ? parseInt(match[2], 10) : totalSize - 1;
4682
+ const end = match[2] ? parseInt(match[2], 10) : openRangeEnd(start, totalSize - 1, servedContentType);
4678
4683
  const safeEnd = Math.min(end, totalSize - 1);
4679
4684
  if (start > safeEnd) {
4680
4685
  return new Response(null, {
@@ -6971,6 +6976,7 @@ export {
6971
6976
  HistoryClosedError,
6972
6977
  HistoryIdError,
6973
6978
  HistoryRefusedError,
6979
+ MAX_OPEN_MEDIA_RANGE_BYTES,
6974
6980
  MAX_UPLOAD_BYTES,
6975
6981
  MAX_WINDOW_IDLE_MS,
6976
6982
  MIME_TYPES,
@@ -7014,6 +7020,7 @@ export {
7014
7020
  listProjectHistories,
7015
7021
  onRestoredInPlace,
7016
7022
  openProjectHistory,
7023
+ openRangeEnd,
7017
7024
  parseSourceDocument,
7018
7025
  patchElementInHtml,
7019
7026
  pruneGoneProjectHistories,
@@ -7029,6 +7036,7 @@ export {
7029
7036
  settledFileTag,
7030
7037
  splitElementInHtml,
7031
7038
  stampProjectHfIds,
7039
+ stampProjectHfIdsAsync,
7032
7040
  thumbnailDeviceScaleFactor,
7033
7041
  walkDir
7034
7042
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/studio-server",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -74,6 +74,10 @@
74
74
  "./encoder-options": {
75
75
  "import": "./dist/helpers/encoderOptions.js",
76
76
  "types": "./dist/helpers/encoderOptions.d.ts"
77
+ },
78
+ "./media-range": {
79
+ "import": "./dist/helpers/mediaRange.js",
80
+ "types": "./dist/helpers/mediaRange.d.ts"
77
81
  }
78
82
  },
79
83
  "publishConfig": {
@@ -84,8 +88,8 @@
84
88
  "linkedom": "^0.18.12",
85
89
  "postcss": "^8.5.8",
86
90
  "postcss-selector-parser": "^7.1.2",
87
- "@hyperframes/core": "0.9.2",
88
- "@hyperframes/parsers": "0.9.2"
91
+ "@hyperframes/core": "0.9.4",
92
+ "@hyperframes/parsers": "0.9.4"
89
93
  },
90
94
  "devDependencies": {
91
95
  "@types/node": "^25.0.10",