@hyperframes/studio-server 0.8.68 → 0.8.70

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.
package/dist/index.d.ts CHANGED
@@ -80,6 +80,13 @@ interface AppliedFileMutation {
80
80
  /** Applies prepared HTML mutations with the same journal and receipt semantics as Studio. */
81
81
  declare function applyFileMutations(projectDir: string, mutations: readonly FileMutationInput[], requestToken?: string, writeFile?: (path: string, content: string, encoding: "utf-8") => void): AppliedFileMutation[];
82
82
 
83
+ /** The bundler options every adapter's `bundle()` uses. This route serves project files under a
84
+ * `<base href>`, so assets keep their URLs: inlined base64 multiplies the document per reference. */
85
+ declare const PREVIEW_BUNDLE_OPTIONS: {
86
+ readonly runtime: "placeholder";
87
+ readonly inlineAssets: false;
88
+ };
89
+
83
90
  declare const MIME_TYPES: Record<string, string>;
84
91
  declare function getMimeType(path: string): string;
85
92
 
@@ -90,6 +97,15 @@ interface FileWriteReceipt {
90
97
  }
91
98
  /** Strong content version used as both the JSON version and HTTP ETag. */
92
99
  declare function fileContentVersion(content: string | Uint8Array): string;
100
+ /** A validator from a file's inode, change time and size, or null while the change is under three
101
+ * seconds old. Change time, not mtime: copy tools (`cp -p`, rsync, robocopy) set mtime back but not
102
+ * ctime, which Node reads from NTFS ChangeTime on Windows. A same-size rewrite within one tick keeps
103
+ * both, so only a settled file is tagged. */
104
+ declare function settledFileTag(stat: {
105
+ ino: number;
106
+ ctimeMs: number;
107
+ size: number;
108
+ }, now?: number): string | null;
93
109
  /**
94
110
  * Attach one API write's identity to the watcher echo for its exact bytes.
95
111
  *
@@ -167,4 +183,4 @@ type BackgroundRemovalRender = (options: {
167
183
  }>;
168
184
  declare function createBackgroundRemovalJob(opts: BackgroundRemovalJobOptions, render: BackgroundRemovalRender): MediaProcessingJobState;
169
185
 
170
- export { type AppliedFileMutation, type BackgroundRemovalRender, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MIME_TYPES, MediaProcessingJobState, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, thumbnailDeviceScaleFactor, walkDir };
186
+ export { type AppliedFileMutation, type BackgroundRemovalRender, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MIME_TYPES, MediaProcessingJobState, PREVIEW_BUNDLE_OPTIONS, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, settledFileTag, thumbnailDeviceScaleFactor, walkDir };
package/dist/index.js CHANGED
@@ -620,6 +620,10 @@ var receipts = /* @__PURE__ */ new Map();
620
620
  function fileContentVersion(content) {
621
621
  return `"sha256:${createHash2("sha256").update(content).digest("hex")}"`;
622
622
  }
623
+ function settledFileTag(stat, now = Date.now()) {
624
+ if (now - stat.ctimeMs < 3e3) return null;
625
+ return [stat.ino, stat.ctimeMs, stat.size].map((n) => n.toString(36)).join("-");
626
+ }
623
627
  function createWriteToken(requestToken) {
624
628
  const token = requestToken?.trim();
625
629
  return token && token.length <= 200 ? token : randomUUID2();
@@ -3182,7 +3186,10 @@ import { createReadStream, existsSync as existsSync5, readFileSync as readFileSy
3182
3186
  import { Readable } from "stream";
3183
3187
  import { join as join8, resolve as resolve4 } from "path";
3184
3188
  import { createHash as createHash3 } from "crypto";
3185
- import { injectScriptsIntoHtml, stripEmbeddedRuntimeScripts as stripEmbeddedRuntimeScripts2 } from "@hyperframes/core/compiler";
3189
+ import {
3190
+ injectScriptsIntoHtml,
3191
+ stripEmbeddedRuntimeScripts as stripEmbeddedRuntimeScripts2
3192
+ } from "@hyperframes/core/compiler";
3186
3193
  import { isWithinProjectRoot } from "@hyperframes/parsers/asset-resolution";
3187
3194
 
3188
3195
  // src/helpers/subComposition.ts
@@ -3627,6 +3634,10 @@ function resolveProjectMainHtml(projectDir, projectId) {
3627
3634
  }
3628
3635
  return null;
3629
3636
  }
3637
+ var PREVIEW_BUNDLE_OPTIONS = {
3638
+ runtime: "placeholder",
3639
+ inlineAssets: false
3640
+ };
3630
3641
  function registerPreviewRoutes(api, adapter) {
3631
3642
  const previewCacheHeaders = (etag) => ({
3632
3643
  "Cache-Control": "private, no-cache",
@@ -3789,12 +3800,10 @@ ${runtimeTag}`;
3789
3800
  return c.text("media proxy variant does not match asset", 422);
3790
3801
  }
3791
3802
  }
3792
- const etag = `"${stat.mtimeMs.toString(36)}-${stat.size.toString(36)}${proxyEtagSalt(proxyVariant)}"`;
3793
- const cacheHeaders = isText ? { "Cache-Control": "no-store" } : {
3794
- "Cache-Control": "private, no-cache",
3795
- ETag: etag
3796
- };
3797
- if (!isText) {
3803
+ const tag = settledFileTag(stat);
3804
+ const etag = tag && `"${tag}${proxyEtagSalt(proxyVariant)}"`;
3805
+ const cacheHeaders = isText ? { "Cache-Control": "no-store" } : { "Cache-Control": "private, no-cache", ...etag && { ETag: etag } };
3806
+ if (!isText && etag) {
3798
3807
  const ifNoneMatch = c.req.header("If-None-Match");
3799
3808
  if (ifNoneMatch === etag) {
3800
3809
  return new Response(null, { status: 304, headers: cacheHeaders });
@@ -5170,6 +5179,7 @@ function updateBackgroundRemovalProgress(state, event) {
5170
5179
  }
5171
5180
  export {
5172
5181
  MIME_TYPES,
5182
+ PREVIEW_BUNDLE_OPTIONS,
5173
5183
  STUDIO_MANUAL_EDITS_PATH,
5174
5184
  STUDIO_MOTION_PATH,
5175
5185
  affectsProjectSignature,
@@ -5194,6 +5204,7 @@ export {
5194
5204
  parseSourceDocument,
5195
5205
  patchElementInHtml,
5196
5206
  removeElementFromHtml,
5207
+ settledFileTag,
5197
5208
  splitElementInHtml,
5198
5209
  thumbnailDeviceScaleFactor,
5199
5210
  walkDir