vargai 0.3.1 → 0.4.0-alpha.1

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 (73) hide show
  1. package/README.md +1 -38
  2. package/biome.json +6 -1
  3. package/docs/index.html +1130 -0
  4. package/docs/prompting.md +326 -0
  5. package/docs/react.md +834 -0
  6. package/package.json +11 -6
  7. package/src/ai-sdk/index.ts +2 -21
  8. package/src/cli/commands/index.ts +1 -4
  9. package/src/cli/commands/render.tsx +71 -0
  10. package/src/cli/index.ts +2 -0
  11. package/src/react/cli.ts +52 -0
  12. package/src/react/elements.ts +146 -0
  13. package/src/react/examples/branching.tsx +66 -0
  14. package/src/react/examples/captions-demo.tsx +37 -0
  15. package/src/react/examples/character-video.tsx +84 -0
  16. package/src/react/examples/grid.tsx +53 -0
  17. package/src/react/examples/layouts-demo.tsx +57 -0
  18. package/src/react/examples/madi.tsx +60 -0
  19. package/src/react/examples/music-test.tsx +35 -0
  20. package/src/react/examples/onlyfans-1m/workflow.tsx +88 -0
  21. package/src/react/examples/orange-portrait.tsx +41 -0
  22. package/src/react/examples/split-element-demo.tsx +60 -0
  23. package/src/react/examples/split-layout-demo.tsx +60 -0
  24. package/src/react/examples/split.tsx +41 -0
  25. package/src/react/examples/video-grid.tsx +46 -0
  26. package/src/react/index.ts +43 -0
  27. package/src/react/layouts/grid.tsx +28 -0
  28. package/src/react/layouts/index.ts +2 -0
  29. package/src/react/layouts/split.tsx +20 -0
  30. package/src/react/react.test.ts +309 -0
  31. package/src/react/render.ts +21 -0
  32. package/src/react/renderers/animate.ts +59 -0
  33. package/src/react/renderers/captions.ts +297 -0
  34. package/src/react/renderers/clip.ts +248 -0
  35. package/src/react/renderers/context.ts +17 -0
  36. package/src/react/renderers/image.ts +109 -0
  37. package/src/react/renderers/index.ts +22 -0
  38. package/src/react/renderers/music.ts +60 -0
  39. package/src/react/renderers/packshot.ts +84 -0
  40. package/src/react/renderers/progress.ts +173 -0
  41. package/src/react/renderers/render.ts +243 -0
  42. package/src/react/renderers/slider.ts +69 -0
  43. package/src/react/renderers/speech.ts +53 -0
  44. package/src/react/renderers/split.ts +91 -0
  45. package/src/react/renderers/subtitle.ts +16 -0
  46. package/src/react/renderers/swipe.ts +75 -0
  47. package/src/react/renderers/title.ts +17 -0
  48. package/src/react/renderers/utils.ts +124 -0
  49. package/src/react/renderers/video.ts +127 -0
  50. package/src/react/runtime/jsx-dev-runtime.ts +43 -0
  51. package/src/react/runtime/jsx-runtime.ts +35 -0
  52. package/src/react/types.ts +232 -0
  53. package/src/studio/index.ts +26 -0
  54. package/src/studio/scanner.ts +102 -0
  55. package/src/studio/server.ts +554 -0
  56. package/src/studio/stages.ts +251 -0
  57. package/src/studio/step-renderer.ts +279 -0
  58. package/src/studio/types.ts +60 -0
  59. package/src/studio/ui/cache.html +303 -0
  60. package/src/studio/ui/index.html +1820 -0
  61. package/tsconfig.cli.json +8 -0
  62. package/tsconfig.json +3 -1
  63. package/bun.lock +0 -1255
  64. package/docs/plan.md +0 -66
  65. package/docs/todo.md +0 -14
  66. package/src/ai-sdk/middleware/index.ts +0 -25
  67. package/src/ai-sdk/middleware/placeholder.ts +0 -111
  68. package/src/ai-sdk/middleware/wrap-image-model.ts +0 -86
  69. package/src/ai-sdk/middleware/wrap-music-model.ts +0 -108
  70. package/src/ai-sdk/middleware/wrap-video-model.ts +0 -115
  71. /package/docs/{varg-sdk.md → sdk.md} +0 -0
  72. /package/src/ai-sdk/providers/{elevenlabs.ts → elevenlabs-provider.ts} +0 -0
  73. /package/src/ai-sdk/providers/{fal.ts → fal-provider.ts} +0 -0
package/docs/plan.md DELETED
@@ -1,66 +0,0 @@
1
- # varg ts-sdk migration plan
2
-
3
- ## core
4
-
5
- - [ ] File (load from path, url, buffer)
6
- - [ ] File.toTemp() - save to temp file for editly integration
7
- - [ ] scene`` tagged template for composing elements in prompts
8
- - [ ] types (AspectRatio, Element, etc)
9
-
10
- ## providers
11
-
12
- - [ ] @varg/fal (kling, nano-banana, lipsync)
13
- - [ ] @varg/elevenlabs (tts, music)
14
- - [ ] @varg/higgsfield (soul, characters)
15
- - [ ] @varg/heygen (talking heads)
16
- - [ ] @varg/openai (sora, gpt-image, dall-e)
17
- - [ ] @varg/replicate (birefnet, generic models)
18
-
19
- ## generation
20
-
21
- - [ ] generateImage (text to image)
22
- - [ ] generateImage (image to image / edit)
23
- - [ ] generateVideo (text to video)
24
- - [ ] generateVideo (image to video)
25
- - [ ] generateSpeech (voiceover via elevenlabs)
26
- - [ ] generateMusic (music generation via elevenlabs)
27
- - [ ] generateLipsync (sync video to audio via fal)
28
- - [ ] generateTalkingHead (photo to talking video via heygen)
29
- - [ ] generateElement (character/item/style reference for consistent generation)
30
-
31
- ## editing (use editly directly)
32
-
33
- users use editly npm package directly for video composition.
34
- we provide `File.toTemp()` to bridge ai outputs → editly paths.
35
-
36
- editly covers these py-sdk features:
37
- - [ ] crop_to_aspect_ratio → editly clips with resizeMode
38
- - [ ] mix_audio_with_ducking → editly audioNorm + audioTracks
39
- - [ ] apply_zoom_effect → editly zoomDirection on layers
40
- - [ ] create_ken_burns_effect → editly zoomDirection: "in" | "out"
41
- - [ ] create_slideshow → editly clips[] with transitions
42
- - [ ] concatenate_videos → editly clips[] with transitions
43
- - [ ] picture_in_picture → editly layers with position/size
44
- - [ ] blur_background_resize → editly resizeMode: "contain-blur"
45
- - [ ] 67 gl-transitions (fade, crossfade, wipe, cube, etc.)
46
-
47
- ## custom effects (not in editly)
48
-
49
- - [ ] addCaptions (tiktok-style word-by-word) - custom fabric.js layer for editly
50
- - [ ] createSlider (before/after reveal animation)
51
- - [ ] createPushTransition (card push effect)
52
- - [ ] createSwipeAnimation (tinder-style card swipes)
53
- - [ ] createSplitScreen (side-by-side comparison)
54
- - [ ] createPackshot (end card with cta button + blinking cta)
55
-
56
- ## image processing
57
-
58
- - [ ] removeBackground (via replicate birefnet)
59
-
60
- ## notes
61
-
62
- - editly used directly (not wrapped)
63
- - File.toTemp() bridges ai outputs to editly string paths
64
- - providers are separate packages (@varg/fal, @varg/elevenlabs, etc)
65
- - generateElement returns { images, text } for use in prompts
66
- - scene`` template composes elements in prompts
package/docs/todo.md DELETED
@@ -1,14 +0,0 @@
1
-
2
- # TODO
3
-
4
- • [ ] fal
5
- • [ ] higgsfield
6
- • [ ] captions (exactly as in TikTok)
7
- • [ ] editing (simple concat of video frames)
8
- • [ ] voiceover via elevenlabs
9
- • [ ] music generation via elevenlabs
10
- • [ ] adding music on top of video
11
- • [ ] lypsync (via sync models over fal)
12
- • [ ] resize with blur: i.e. 9:16 is resided to 4:5 by adding sides with a blur on all video
13
- • [ ] Picture-in-the-picture: one video on top of another
14
- • [ ] fade / slideshow transitions
@@ -1,25 +0,0 @@
1
- export {
2
- generatePlaceholder,
3
- type PlaceholderOptions,
4
- type PlaceholderResult,
5
- } from "./placeholder";
6
- export {
7
- type ImagePlaceholderFallbackOptions,
8
- imagePlaceholderFallbackMiddleware,
9
- withImagePlaceholderFallback,
10
- } from "./wrap-image-model";
11
- export {
12
- type MusicModelMiddleware,
13
- type MusicPlaceholderFallbackOptions,
14
- musicPlaceholderFallbackMiddleware,
15
- withMusicPlaceholderFallback,
16
- wrapMusicModel,
17
- } from "./wrap-music-model";
18
- export {
19
- type PlaceholderFallbackOptions,
20
- placeholderFallbackMiddleware,
21
- type RenderMode,
22
- type VideoModelMiddleware,
23
- withPlaceholderFallback,
24
- wrapVideoModel,
25
- } from "./wrap-video-model";
@@ -1,111 +0,0 @@
1
- import { unlink } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { $ } from "bun";
5
-
6
- export interface PlaceholderOptions {
7
- type: "image" | "video" | "audio";
8
- prompt: string;
9
- duration?: number;
10
- width?: number;
11
- height?: number;
12
- }
13
-
14
- export interface PlaceholderResult {
15
- data: Uint8Array;
16
- placeholder: true;
17
- }
18
-
19
- function promptToColor(prompt: string): string {
20
- let hash = 0;
21
- for (let i = 0; i < prompt.length; i++) {
22
- const char = prompt.charCodeAt(i);
23
- hash = (hash << 5) - hash + char;
24
- hash = hash & hash;
25
- }
26
-
27
- const h = Math.abs(hash) % 360;
28
- const s = 40 + (Math.abs(hash >> 8) % 30);
29
- const l = 35 + (Math.abs(hash >> 16) % 20);
30
-
31
- return `hsl(${h},${s}%,${l}%)`;
32
- }
33
-
34
- function hslToHex(hsl: string): string {
35
- const match = hsl.match(/hsl\((\d+),(\d+)%,(\d+)%\)/);
36
- if (!match) return "333333";
37
-
38
- const h = Number.parseInt(match[1]!) / 360;
39
- const s = Number.parseInt(match[2]!) / 100;
40
- const l = Number.parseInt(match[3]!) / 100;
41
-
42
- const hue2rgb = (p: number, q: number, t: number) => {
43
- if (t < 0) t += 1;
44
- if (t > 1) t -= 1;
45
- if (t < 1 / 6) return p + (q - p) * 6 * t;
46
- if (t < 1 / 2) return q;
47
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
48
- return p;
49
- };
50
-
51
- const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
52
- const p = 2 * l - q;
53
- const r = Math.round(hue2rgb(p, q, h + 1 / 3) * 255);
54
- const g = Math.round(hue2rgb(p, q, h) * 255);
55
- const b = Math.round(hue2rgb(p, q, h - 1 / 3) * 255);
56
-
57
- return `${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
58
- }
59
-
60
- function truncatePrompt(text: string, maxLen: number): string {
61
- const clean = text.replace(/[^a-zA-Z0-9 .,!?-]/g, "");
62
- if (clean.length <= maxLen) return clean;
63
- return `${clean.slice(0, maxLen - 3)}...`;
64
- }
65
-
66
- export async function generatePlaceholder(
67
- options: PlaceholderOptions,
68
- ): Promise<PlaceholderResult> {
69
- const { type, prompt, duration = 3, width = 1080, height = 1920 } = options;
70
-
71
- const color = promptToColor(prompt);
72
- const hexColor = hslToHex(color);
73
- const labelFontSize = Math.floor(Math.min(width, height) / 20);
74
- const promptFontSize = Math.floor(Math.min(width, height) / 35);
75
- const maxChars = Math.floor((width * 0.7) / (promptFontSize * 0.5));
76
- const typeLabel = type.toUpperCase();
77
- const promptText = truncatePrompt(prompt, maxChars);
78
-
79
- const ext = type === "audio" ? "mp3" : type === "image" ? "png" : "mp4";
80
- const outputPath = join(
81
- tmpdir(),
82
- `placeholder_${Date.now()}_${Math.random().toString(36).slice(2)}.${ext}`,
83
- );
84
-
85
- try {
86
- if (type === "audio") {
87
- await $`ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t ${duration} -c:a libmp3lame ${outputPath}`.quiet();
88
- } else if (type === "image") {
89
- const colorInput = `color=c=0x${hexColor}:s=${width}x${height}:d=1`;
90
- const labelY = `(h/2)-${labelFontSize}`;
91
- const promptY = `(h/2)+${Math.floor(labelFontSize * 0.5)}`;
92
- const drawLabel = `drawtext=text='${typeLabel}':fontcolor=white:fontsize=${labelFontSize}:x=(w-text_w)/2:y=${labelY}`;
93
- const drawPrompt = `drawtext=text='${promptText}':fontcolor=white@0.7:fontsize=${promptFontSize}:x=(w-text_w)/2:y=${promptY}`;
94
- await $`ffmpeg -y -f lavfi -i ${colorInput} -vf ${drawLabel},${drawPrompt} -frames:v 1 -update 1 ${outputPath}`.quiet();
95
- } else {
96
- const colorInput = `color=c=0x${hexColor}:s=${width}x${height}:d=${duration}:r=30`;
97
- const labelY = `(h/2)-${labelFontSize}`;
98
- const promptY = `(h/2)+${Math.floor(labelFontSize * 0.5)}`;
99
- const drawLabel = `drawtext=text='${typeLabel}':fontcolor=white:fontsize=${labelFontSize}:x=(w-text_w)/2:y=${labelY}`;
100
- const drawPrompt = `drawtext=text='${promptText}':fontcolor=white@0.7:fontsize=${promptFontSize}:x=(w-text_w)/2:y=${promptY}`;
101
- await $`ffmpeg -y -f lavfi -i ${colorInput} -vf ${drawLabel},${drawPrompt} -c:v libx264 -preset ultrafast -pix_fmt yuv420p ${outputPath}`.quiet();
102
- }
103
-
104
- const data = await Bun.file(outputPath).bytes();
105
- await unlink(outputPath).catch(() => {});
106
- return { data: new Uint8Array(data), placeholder: true };
107
- } catch (e) {
108
- await unlink(outputPath).catch(() => {});
109
- throw e;
110
- }
111
- }
@@ -1,86 +0,0 @@
1
- import type {
2
- ImageModelV3,
3
- ImageModelV3CallOptions,
4
- ImageModelV3Middleware,
5
- } from "@ai-sdk/provider";
6
- import { wrapImageModel } from "ai";
7
- import { generatePlaceholder } from "./placeholder";
8
- import type { RenderMode } from "./wrap-video-model";
9
-
10
- export interface ImagePlaceholderFallbackOptions {
11
- mode: RenderMode;
12
- onFallback?: (error: Error, prompt: string) => void;
13
- }
14
-
15
- export function imagePlaceholderFallbackMiddleware(
16
- options: ImagePlaceholderFallbackOptions,
17
- ): ImageModelV3Middleware {
18
- const { mode, onFallback } = options;
19
-
20
- return {
21
- specificationVersion: "v3",
22
- wrapGenerate: async ({ doGenerate, params, model }) => {
23
- const createPlaceholderResult = async () => {
24
- const [width, height] = (params.size?.split("x").map(Number) ?? [
25
- 1024, 1024,
26
- ]) as [number, number];
27
- const prompt =
28
- typeof params.prompt === "string"
29
- ? params.prompt
30
- : ((params.prompt as { text?: string } | undefined)?.text ??
31
- "placeholder");
32
-
33
- const placeholder = await generatePlaceholder({
34
- type: "image",
35
- prompt,
36
- width,
37
- height,
38
- });
39
-
40
- return {
41
- images: [placeholder.data],
42
- warnings: [
43
- {
44
- type: "other" as const,
45
- message: "placeholder: provider skipped or failed",
46
- },
47
- ],
48
- response: {
49
- timestamp: new Date(),
50
- modelId: model.modelId,
51
- headers: undefined,
52
- },
53
- };
54
- };
55
-
56
- if (mode === "preview") {
57
- return createPlaceholderResult();
58
- }
59
-
60
- try {
61
- return await doGenerate();
62
- } catch (e) {
63
- if (mode === "strict") throw e;
64
-
65
- const error = e instanceof Error ? e : new Error(String(e));
66
- const promptText =
67
- typeof params.prompt === "string"
68
- ? params.prompt
69
- : ((params.prompt as { text?: string } | undefined)?.text ??
70
- "placeholder");
71
- onFallback?.(error, promptText);
72
- return createPlaceholderResult();
73
- }
74
- },
75
- };
76
- }
77
-
78
- export function withImagePlaceholderFallback(
79
- model: ImageModelV3,
80
- options: ImagePlaceholderFallbackOptions,
81
- ): ImageModelV3 {
82
- return wrapImageModel({
83
- model,
84
- middleware: imagePlaceholderFallbackMiddleware(options),
85
- });
86
- }
@@ -1,108 +0,0 @@
1
- import type { MusicModelV3, MusicModelV3CallOptions } from "../music-model";
2
- import { generatePlaceholder } from "./placeholder";
3
- import type { RenderMode } from "./wrap-video-model";
4
-
5
- export interface MusicModelMiddleware {
6
- transformParams?: (options: {
7
- params: MusicModelV3CallOptions;
8
- model: MusicModelV3;
9
- }) => PromiseLike<MusicModelV3CallOptions> | MusicModelV3CallOptions;
10
-
11
- wrapGenerate?: (options: {
12
- doGenerate: () => PromiseLike<
13
- Awaited<ReturnType<MusicModelV3["doGenerate"]>>
14
- >;
15
- params: MusicModelV3CallOptions;
16
- model: MusicModelV3;
17
- }) => PromiseLike<Awaited<ReturnType<MusicModelV3["doGenerate"]>>>;
18
- }
19
-
20
- export function wrapMusicModel({
21
- model,
22
- middleware,
23
- }: {
24
- model: MusicModelV3;
25
- middleware: MusicModelMiddleware;
26
- }): MusicModelV3 {
27
- const { transformParams, wrapGenerate } = middleware;
28
-
29
- return {
30
- specificationVersion: "v3",
31
- provider: model.provider,
32
- modelId: model.modelId,
33
-
34
- async doGenerate(params: MusicModelV3CallOptions) {
35
- const transformedParams = transformParams
36
- ? await transformParams({ params, model })
37
- : params;
38
-
39
- const doGenerate = () => model.doGenerate(transformedParams);
40
-
41
- return wrapGenerate
42
- ? wrapGenerate({ doGenerate, params: transformedParams, model })
43
- : doGenerate();
44
- },
45
- };
46
- }
47
-
48
- export interface MusicPlaceholderFallbackOptions {
49
- mode: RenderMode;
50
- onFallback?: (error: Error, prompt: string) => void;
51
- }
52
-
53
- export function musicPlaceholderFallbackMiddleware(
54
- options: MusicPlaceholderFallbackOptions,
55
- ): MusicModelMiddleware {
56
- const { mode, onFallback } = options;
57
-
58
- return {
59
- wrapGenerate: async ({ doGenerate, params, model }) => {
60
- const createPlaceholderResult = async () => {
61
- const placeholder = await generatePlaceholder({
62
- type: "audio",
63
- prompt: params.prompt,
64
- duration: params.duration ?? 10,
65
- });
66
-
67
- return {
68
- audio: placeholder.data,
69
- warnings: [
70
- {
71
- type: "other" as const,
72
- message: "placeholder: provider skipped or failed",
73
- },
74
- ],
75
- response: {
76
- timestamp: new Date(),
77
- modelId: model.modelId,
78
- headers: undefined,
79
- },
80
- };
81
- };
82
-
83
- if (mode === "preview") {
84
- return createPlaceholderResult();
85
- }
86
-
87
- try {
88
- return await doGenerate();
89
- } catch (e) {
90
- if (mode === "strict") throw e;
91
-
92
- const error = e instanceof Error ? e : new Error(String(e));
93
- onFallback?.(error, params.prompt);
94
- return createPlaceholderResult();
95
- }
96
- },
97
- };
98
- }
99
-
100
- export function withMusicPlaceholderFallback(
101
- model: MusicModelV3,
102
- options: MusicPlaceholderFallbackOptions,
103
- ): MusicModelV3 {
104
- return wrapMusicModel({
105
- model,
106
- middleware: musicPlaceholderFallbackMiddleware(options),
107
- });
108
- }
@@ -1,115 +0,0 @@
1
- import type { VideoModelV3, VideoModelV3CallOptions } from "../video-model";
2
- import { generatePlaceholder } from "./placeholder";
3
-
4
- export type RenderMode = "strict" | "default" | "preview";
5
-
6
- export interface VideoModelMiddleware {
7
- transformParams?: (options: {
8
- params: VideoModelV3CallOptions;
9
- model: VideoModelV3;
10
- }) => PromiseLike<VideoModelV3CallOptions> | VideoModelV3CallOptions;
11
-
12
- wrapGenerate?: (options: {
13
- doGenerate: () => PromiseLike<
14
- Awaited<ReturnType<VideoModelV3["doGenerate"]>>
15
- >;
16
- params: VideoModelV3CallOptions;
17
- model: VideoModelV3;
18
- }) => PromiseLike<Awaited<ReturnType<VideoModelV3["doGenerate"]>>>;
19
- }
20
-
21
- export function wrapVideoModel({
22
- model,
23
- middleware,
24
- }: {
25
- model: VideoModelV3;
26
- middleware: VideoModelMiddleware;
27
- }): VideoModelV3 {
28
- const { transformParams, wrapGenerate } = middleware;
29
-
30
- return {
31
- specificationVersion: "v3",
32
- provider: model.provider,
33
- modelId: model.modelId,
34
- maxVideosPerCall: model.maxVideosPerCall,
35
-
36
- async doGenerate(params: VideoModelV3CallOptions) {
37
- const transformedParams = transformParams
38
- ? await transformParams({ params, model })
39
- : params;
40
-
41
- const doGenerate = () => model.doGenerate(transformedParams);
42
-
43
- return wrapGenerate
44
- ? wrapGenerate({ doGenerate, params: transformedParams, model })
45
- : doGenerate();
46
- },
47
- };
48
- }
49
-
50
- export interface PlaceholderFallbackOptions {
51
- mode: RenderMode;
52
- onFallback?: (error: Error, prompt: string) => void;
53
- }
54
-
55
- export function placeholderFallbackMiddleware(
56
- options: PlaceholderFallbackOptions,
57
- ): VideoModelMiddleware {
58
- const { mode, onFallback } = options;
59
-
60
- return {
61
- wrapGenerate: async ({ doGenerate, params, model }) => {
62
- const createPlaceholderResult = async () => {
63
- const [width, height] = (params.resolution?.split("x").map(Number) ?? [
64
- 1080, 1920,
65
- ]) as [number, number];
66
- const placeholder = await generatePlaceholder({
67
- type: "video",
68
- prompt: params.prompt,
69
- duration: params.duration ?? 3,
70
- width,
71
- height,
72
- });
73
-
74
- return {
75
- videos: [placeholder.data],
76
- warnings: [
77
- {
78
- type: "other" as const,
79
- message: "placeholder: provider skipped or failed",
80
- },
81
- ],
82
- response: {
83
- timestamp: new Date(),
84
- modelId: model.modelId,
85
- headers: undefined,
86
- },
87
- };
88
- };
89
-
90
- if (mode === "preview") {
91
- return createPlaceholderResult();
92
- }
93
-
94
- try {
95
- return await doGenerate();
96
- } catch (e) {
97
- if (mode === "strict") throw e;
98
-
99
- const error = e instanceof Error ? e : new Error(String(e));
100
- onFallback?.(error, params.prompt);
101
- return createPlaceholderResult();
102
- }
103
- },
104
- };
105
- }
106
-
107
- export function withPlaceholderFallback(
108
- model: VideoModelV3,
109
- options: PlaceholderFallbackOptions,
110
- ): VideoModelV3 {
111
- return wrapVideoModel({
112
- model,
113
- middleware: placeholderFallbackMiddleware(options),
114
- });
115
- }
File without changes