@anvpx/motion-build 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +67 -2
- package/dist/.out/demo/boot.js +90 -0
- package/dist/.out/demo/runtime/easing.js +45 -0
- package/dist/.out/demo/runtime/mount.js +153 -0
- package/dist/.out/demo/runtime/timeline.js +199 -0
- package/dist/.out/demo/scenes/count/scene.js +6 -0
- package/dist/.out/demo/scenes/intro/scene.js +6 -0
- package/dist/.out/demo/scenes/outro/scene.js +6 -0
- package/dist/.out/demo/scenes/path/scene.js +6 -0
- package/dist/.out/demo/scenes/signals/scene.js +6 -0
- package/dist/.out/demo/shared/format.js +59 -0
- package/dist/.out/demo/shared/motion.js +117 -0
- package/dist/.out/demo-overlays/boot.js +95 -0
- package/dist/.out/demo-overlays/runtime/easing.js +45 -0
- package/dist/.out/demo-overlays/runtime/mount.js +153 -0
- package/dist/.out/demo-overlays/runtime/timeline.js +199 -0
- package/dist/.out/demo-overlays/scenes/chapter-signals/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/count/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/flow-progress/scene.js +17 -0
- package/dist/.out/demo-overlays/scenes/intro/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/mark/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/outro/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/path/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/presenter/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/signals/scene.js +6 -0
- package/dist/.out/demo-overlays/scenes/tick/scene.js +21 -0
- package/dist/.out/demo-overlays/shared/format.js +59 -0
- package/dist/.out/demo-overlays/shared/motion.js +117 -0
- package/dist/assets.d.ts +36 -0
- package/dist/assets.js +95 -0
- package/dist/audio/approval.d.ts +45 -0
- package/dist/audio/approval.js +82 -0
- package/dist/audio/mix.d.ts +231 -0
- package/dist/audio/mix.js +491 -0
- package/dist/audio/music.d.ts +82 -0
- package/dist/audio/music.js +134 -0
- package/dist/audio/preview.d.ts +31 -0
- package/dist/audio/preview.js +31 -0
- package/dist/build.d.ts +65 -0
- package/dist/build.js +260 -0
- package/dist/cache.d.ts +59 -0
- package/dist/cache.js +249 -0
- package/dist/emit/boot.d.ts +16 -0
- package/dist/emit/boot.js +32 -0
- package/dist/emit/boot.template.js +85 -0
- package/dist/emit/fragment-guard.d.ts +5 -0
- package/dist/emit/fragment-guard.js +15 -0
- package/dist/emit/index-html.d.ts +26 -0
- package/dist/emit/index-html.js +63 -0
- package/dist/emit/safe-json.d.ts +2 -0
- package/dist/emit/safe-json.js +7 -0
- package/dist/emit/vendor.d.ts +7 -0
- package/dist/emit/vendor.js +57 -0
- package/dist/fonts.d.ts +39 -0
- package/dist/fonts.js +112 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +19 -0
- package/dist/integration/render.integration.d.ts +1 -0
- package/dist/integration/render.integration.js +162 -0
- package/dist/lint/custom-source.d.ts +12 -0
- package/dist/lint/custom-source.js +130 -0
- package/dist/lint/fixtures.d.ts +24 -0
- package/dist/lint/fixtures.js +42 -0
- package/dist/lint/flow.d.ts +12 -0
- package/dist/lint/flow.js +38 -0
- package/dist/lint/frame.d.ts +3 -0
- package/dist/lint/frame.js +2 -0
- package/dist/lint/hook-first.d.ts +6 -0
- package/dist/lint/hook-first.js +27 -0
- package/dist/lint/index.d.ts +25 -0
- package/dist/lint/index.js +55 -0
- package/dist/lint/layout-estimate.d.ts +18 -0
- package/dist/lint/layout-estimate.js +165 -0
- package/dist/lint/linear-ease.d.ts +2 -0
- package/dist/lint/linear-ease.js +14 -0
- package/dist/lint/long-hold.d.ts +9 -0
- package/dist/lint/long-hold.js +52 -0
- package/dist/lint/min-hold.d.ts +4 -0
- package/dist/lint/min-hold.js +10 -0
- package/dist/lint/motion-craft.d.ts +18 -0
- package/dist/lint/motion-craft.js +112 -0
- package/dist/lint/narration-pace.d.ts +6 -0
- package/dist/lint/narration-pace.js +35 -0
- package/dist/lint/overlays.d.ts +9 -0
- package/dist/lint/overlays.js +64 -0
- package/dist/lint/reading-time.d.ts +5 -0
- package/dist/lint/reading-time.js +17 -0
- package/dist/lint/safe-zone-9x16.d.ts +11 -0
- package/dist/lint/safe-zone-9x16.js +101 -0
- package/dist/lint/text-floor.d.ts +8 -0
- package/dist/lint/text-floor.js +34 -0
- package/dist/lint/transition-implemented.d.ts +3 -0
- package/dist/lint/transition-implemented.js +15 -0
- package/dist/lint/transition-length.d.ts +4 -0
- package/dist/lint/transition-length.js +10 -0
- package/dist/lint/type-grid.d.ts +30 -0
- package/dist/lint/type-grid.js +147 -0
- package/dist/lint/types.d.ts +41 -0
- package/dist/lint/types.js +1 -0
- package/dist/lint/words-on-screen.d.ts +5 -0
- package/dist/lint/words-on-screen.js +24 -0
- package/dist/manifest.d.ts +53 -0
- package/dist/manifest.js +55 -0
- package/dist/render-manifest.d.ts +21 -0
- package/dist/render-manifest.js +7 -0
- package/dist/review/review.d.ts +15 -0
- package/dist/review/review.js +56 -0
- package/dist/templates/discover-check.d.ts +11 -0
- package/dist/templates/discover-check.js +36 -0
- package/dist/templates/discover.d.ts +37 -0
- package/dist/templates/discover.js +63 -0
- package/dist/templates/expand.d.ts +17 -0
- package/dist/templates/expand.js +184 -0
- package/dist/templates/fixtures.d.ts +4 -0
- package/dist/templates/fixtures.js +63 -0
- package/dist/templates/index.d.ts +8 -0
- package/dist/templates/index.js +6 -0
- package/dist/templates/instantiate.d.ts +43 -0
- package/dist/templates/instantiate.js +160 -0
- package/dist/templates/load.d.ts +16 -0
- package/dist/templates/load.js +122 -0
- package/dist/templates/pacing.d.ts +21 -0
- package/dist/templates/pacing.js +61 -0
- package/dist/templates/search.d.ts +64 -0
- package/dist/templates/search.js +129 -0
- package/dist/templates/semver.d.ts +2 -0
- package/dist/templates/semver.js +12 -0
- package/dist/templates/slots.d.ts +8 -0
- package/dist/templates/slots.js +116 -0
- package/dist/templates/style.d.ts +25 -0
- package/dist/templates/style.js +56 -0
- package/dist/templates/types.d.ts +29 -0
- package/dist/templates/types.js +1 -0
- package/dist/templates/validate.d.ts +17 -0
- package/dist/templates/validate.js +203 -0
- package/dist/timing.d.ts +38 -0
- package/dist/timing.js +88 -0
- package/dist/validate-full.d.ts +3 -0
- package/dist/validate-full.js +132 -0
- package/dist/verify.d.ts +32 -0
- package/dist/verify.js +180 -0
- package/dist/versions.d.ts +26 -0
- package/dist/versions.js +74 -0
- package/package.json +40 -3
package/dist/verify.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const EXPECTED_VIDEO_CODEC = "h264";
|
|
2
|
+
const EXPECTED_PIX_FMT = "yuv420p";
|
|
3
|
+
const EXPECTED_AUDIO_CODEC = "aac";
|
|
4
|
+
const FPS_TOLERANCE = 0.01;
|
|
5
|
+
const DURATION_TOLERANCE_SECONDS = 0.1;
|
|
6
|
+
const FRAME_TOLERANCE = 1;
|
|
7
|
+
const ASPECT_TOLERANCE = 0.01;
|
|
8
|
+
const asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value)
|
|
9
|
+
? value
|
|
10
|
+
: undefined;
|
|
11
|
+
const text = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
12
|
+
const count = (value) => {
|
|
13
|
+
const n = typeof value === "string" ? Number(value) : value;
|
|
14
|
+
return typeof n === "number" && Number.isFinite(n) && n >= 0 ? n : undefined;
|
|
15
|
+
};
|
|
16
|
+
const parseRate = (value) => {
|
|
17
|
+
const match = /^(\d+)\/(\d+)$/.exec(String(value ?? ""));
|
|
18
|
+
const denominator = Number(match?.[2]);
|
|
19
|
+
return match && denominator > 0 ? Number(match[1]) / denominator : undefined;
|
|
20
|
+
};
|
|
21
|
+
const videoOf = (stream) => ({
|
|
22
|
+
...(text(stream.codec_name) ? { codec: text(stream.codec_name) } : {}),
|
|
23
|
+
...(text(stream.pix_fmt) ? { pixFmt: text(stream.pix_fmt) } : {}),
|
|
24
|
+
...(count(stream.width) !== undefined ? { width: count(stream.width) } : {}),
|
|
25
|
+
...(count(stream.height) !== undefined ? { height: count(stream.height) } : {}),
|
|
26
|
+
...(parseRate(stream.r_frame_rate) !== undefined
|
|
27
|
+
? { fps: parseRate(stream.r_frame_rate) }
|
|
28
|
+
: {}),
|
|
29
|
+
...(count(stream.nb_frames) !== undefined ? { frames: count(stream.nb_frames) } : {}),
|
|
30
|
+
});
|
|
31
|
+
const readProbe = (probe) => {
|
|
32
|
+
const root = asRecord(probe);
|
|
33
|
+
const streams = Array.isArray(root?.streams) ? root.streams.map(asRecord) : [];
|
|
34
|
+
const videoStream = streams.find((s) => s?.codec_type === "video");
|
|
35
|
+
const audioStream = streams.find((s) => s?.codec_type === "audio");
|
|
36
|
+
const duration = count(asRecord(root?.format)?.duration);
|
|
37
|
+
return {
|
|
38
|
+
...(videoStream ? { video: videoOf(videoStream) } : {}),
|
|
39
|
+
...(text(audioStream?.codec_name)
|
|
40
|
+
? { audioCodec: text(audioStream?.codec_name) }
|
|
41
|
+
: {}),
|
|
42
|
+
hasAudio: audioStream !== undefined,
|
|
43
|
+
...(duration !== undefined ? { duration } : {}),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const sizeOf = (width, height) => `${width ?? "?"}x${height ?? "?"}`;
|
|
47
|
+
function checkCodecs(video, add) {
|
|
48
|
+
if (video.codec !== undefined && video.codec !== EXPECTED_VIDEO_CODEC) {
|
|
49
|
+
add("video-codec-unexpected", "fatal", `Video codec is ${video.codec}, expected ${EXPECTED_VIDEO_CODEC}. Re-encode with libx264.`);
|
|
50
|
+
}
|
|
51
|
+
if (video.pixFmt !== undefined && video.pixFmt !== EXPECTED_PIX_FMT) {
|
|
52
|
+
add("pix-fmt-unexpected", "fatal", `Pixel format is ${video.pixFmt}, expected ${EXPECTED_PIX_FMT}. Re-encode with -pix_fmt yuv420p.`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function checkFrame(video, expected, add) {
|
|
56
|
+
const { width, height, fps } = video;
|
|
57
|
+
const differs = (actual, wanted) => actual !== undefined && wanted !== undefined && actual !== wanted;
|
|
58
|
+
if (differs(width, expected.width) || differs(height, expected.height)) {
|
|
59
|
+
add("resolution-mismatch", "fatal", `Resolution is ${sizeOf(width, height)}, expected ${sizeOf(expected.width, expected.height)}.`);
|
|
60
|
+
}
|
|
61
|
+
if (expected.fps !== undefined &&
|
|
62
|
+
fps !== undefined &&
|
|
63
|
+
Math.abs(fps - expected.fps) > FPS_TOLERANCE) {
|
|
64
|
+
add("fps-mismatch", "fatal", `Frame rate is ${fps.toFixed(3)}, expected ${expected.fps}.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function checkTiming(probed, expected, add) {
|
|
68
|
+
const { video, duration } = probed;
|
|
69
|
+
const fps = video?.fps;
|
|
70
|
+
if (expected.duration !== undefined && duration !== undefined) {
|
|
71
|
+
const tolerance = Math.max(DURATION_TOLERANCE_SECONDS, fps ? 1 / fps : 0);
|
|
72
|
+
if (Math.abs(duration - expected.duration) > tolerance) {
|
|
73
|
+
add("duration-mismatch", "fatal", `Duration is ${duration.toFixed(2)}s, expected ${expected.duration.toFixed(2)}s.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const reference = expected.duration ?? duration;
|
|
77
|
+
if (video?.frames === undefined || fps === undefined || reference === undefined)
|
|
78
|
+
return;
|
|
79
|
+
const wanted = Math.round(reference * fps);
|
|
80
|
+
if (Math.abs(video.frames - wanted) > FRAME_TOLERANCE) {
|
|
81
|
+
add("frame-count-mismatch", "fatal", `Frame count is ${video.frames}, expected ${wanted} (duration x fps, 1 frame tolerance).`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function checkAudio(probed, expected, add) {
|
|
85
|
+
if (expected.audio === true && !probed.hasAudio) {
|
|
86
|
+
add("audio-stream-missing", "fatal", "No audio stream, but the storyboard expects audio.");
|
|
87
|
+
}
|
|
88
|
+
if (expected.audio === false && probed.hasAudio) {
|
|
89
|
+
add("audio-unexpected", "info", "Audio stream present although none was expected.");
|
|
90
|
+
}
|
|
91
|
+
if (probed.audioCodec !== undefined && probed.audioCodec !== EXPECTED_AUDIO_CODEC) {
|
|
92
|
+
add("audio-codec-unexpected", "warn", `Audio codec is ${probed.audioCodec}, expected ${EXPECTED_AUDIO_CODEC}.`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const isDecidable = (probed, expected) => {
|
|
96
|
+
const { video, duration } = probed;
|
|
97
|
+
if (!video)
|
|
98
|
+
return true;
|
|
99
|
+
const needsSize = expected.width !== undefined || expected.height !== undefined;
|
|
100
|
+
const missing = video.codec === undefined ||
|
|
101
|
+
video.pixFmt === undefined ||
|
|
102
|
+
video.fps === undefined ||
|
|
103
|
+
video.frames === undefined ||
|
|
104
|
+
duration === undefined ||
|
|
105
|
+
(needsSize && (video.width === undefined || video.height === undefined));
|
|
106
|
+
return !missing;
|
|
107
|
+
};
|
|
108
|
+
function aspectOf(template) {
|
|
109
|
+
const [w = 1, h = 1] = template.aspect.split(":").map(Number);
|
|
110
|
+
return w / h;
|
|
111
|
+
}
|
|
112
|
+
function checkPlatformSize(video, template, add) {
|
|
113
|
+
const { width, height } = video;
|
|
114
|
+
if (!width || !height)
|
|
115
|
+
return;
|
|
116
|
+
if (Math.abs(width / height - aspectOf(template)) > ASPECT_TOLERANCE) {
|
|
117
|
+
add("platform-aspect", "fatal", `${sizeOf(width, height)} is not ${template.aspect} as ${template.id} requires.`);
|
|
118
|
+
}
|
|
119
|
+
else if (width !== template.width || height !== template.height) {
|
|
120
|
+
add("platform-resolution", "warn", `${template.id} targets ${template.width}x${template.height}; file is ${sizeOf(width, height)}.`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function checkPlatformFrame(video, template, add) {
|
|
124
|
+
const id = template.id;
|
|
125
|
+
checkPlatformSize(video, template, add);
|
|
126
|
+
if (video.fps !== undefined && video.fps > template.maxFps + FPS_TOLERANCE) {
|
|
127
|
+
add("platform-fps", "fatal", `Frame rate ${video.fps} exceeds the ${id} maximum ${template.maxFps}.`);
|
|
128
|
+
}
|
|
129
|
+
if (video.codec !== undefined && video.codec !== template.codec.video) {
|
|
130
|
+
add("platform-codec", "fatal", `Video codec ${video.codec} differs from ${id} ${template.codec.video}.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function checkPlatform(probed, template, add) {
|
|
134
|
+
const { video, duration } = probed;
|
|
135
|
+
const id = template.id;
|
|
136
|
+
if (video)
|
|
137
|
+
checkPlatformFrame(video, template, add);
|
|
138
|
+
const cap = template.maxDurationSec;
|
|
139
|
+
if (cap !== undefined && duration !== undefined && duration > cap) {
|
|
140
|
+
add("platform-duration", "fatal", `Duration ${duration.toFixed(1)}s exceeds the ${id} cap ${cap}s.`);
|
|
141
|
+
}
|
|
142
|
+
if (!template.verified) {
|
|
143
|
+
add("platform-unverified", "info", `Template ${id} has verified: false; its limits are approximations. Check the platform's current specs.`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const statusOf = (findings, decidable) => {
|
|
147
|
+
if (findings.some((f) => f.level === "fatal"))
|
|
148
|
+
return "FAIL";
|
|
149
|
+
if (!decidable)
|
|
150
|
+
return "UNKNOWN";
|
|
151
|
+
return findings.some((f) => f.level === "warn") ? "WARN" : "PASS";
|
|
152
|
+
};
|
|
153
|
+
/** Pure QC over probe JSON: measures and reports; the caller decides what to do with the status. */
|
|
154
|
+
export function verifyMedia(input) {
|
|
155
|
+
if (!Array.isArray(asRecord(input.probe)?.streams)) {
|
|
156
|
+
const message = "Probe output has no streams list; result is UNKNOWN.";
|
|
157
|
+
return { status: "UNKNOWN", findings: [{ code: "probe-incomplete", level: "warn", message }] };
|
|
158
|
+
}
|
|
159
|
+
const expected = input.expect ?? {};
|
|
160
|
+
const probed = readProbe(input.probe);
|
|
161
|
+
const findings = [];
|
|
162
|
+
const add = (code, level, message, path) => findings.push({ code, level, message, ...(path === undefined ? {} : { path }) });
|
|
163
|
+
const { video } = probed;
|
|
164
|
+
if (video) {
|
|
165
|
+
checkCodecs(video, add);
|
|
166
|
+
checkFrame(video, expected, add);
|
|
167
|
+
checkTiming(probed, expected, add);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
add("video-stream-missing", "fatal", "No video stream found. Is the file a rendered mp4?");
|
|
171
|
+
}
|
|
172
|
+
checkAudio(probed, expected, add);
|
|
173
|
+
if (input.platform)
|
|
174
|
+
checkPlatform(probed, input.platform, add);
|
|
175
|
+
const decidable = isDecidable(probed, expected);
|
|
176
|
+
if (!decidable) {
|
|
177
|
+
add("probe-incomplete", "warn", "Probe lacked fields needed to decide; result is UNKNOWN.");
|
|
178
|
+
}
|
|
179
|
+
return { status: statusOf(findings, decidable), findings };
|
|
180
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Turns a package id into a path; injectable so tests need no real package tree. */
|
|
2
|
+
export type PackageResolver = (id: string) => string;
|
|
3
|
+
/**
|
|
4
|
+
* Where the root manifest may live, in order: the project being run in (a consumer
|
|
5
|
+
* install has only its own), the workspace root beside these sources, and finally this
|
|
6
|
+
* package's own manifest, which exists in every installed layout.
|
|
7
|
+
*/
|
|
8
|
+
export declare function rootPackageCandidates(cwd?: string): string[];
|
|
9
|
+
export interface VersionInfo {
|
|
10
|
+
readonly packages: Readonly<Record<string, string>>;
|
|
11
|
+
readonly hyperframes: string;
|
|
12
|
+
readonly node: string;
|
|
13
|
+
}
|
|
14
|
+
/** Overrides for the two resolution paths, so fixtures need no real package tree. */
|
|
15
|
+
export interface VersionSources {
|
|
16
|
+
/** Resolves `@anvpx/motion-<name>/package.json`; throws when the package is not installed. */
|
|
17
|
+
readonly resolve?: PackageResolver;
|
|
18
|
+
/** Base URL of this module, for the workspace-relative fallback. */
|
|
19
|
+
readonly manifestBase?: string | URL;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Versions recorded in manifest.json: workspace packages and the pinned renderer.
|
|
23
|
+
* The root manifest is best-effort provenance, never a render gate: a consumer install
|
|
24
|
+
* without a repo root yields the unpinned/empty shape instead of throwing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const readVersions: (candidates?: readonly string[], sources?: VersionSources) => VersionInfo;
|
package/dist/versions.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const PACKAGES = ["build", "scenes", "schema", "themes"];
|
|
6
|
+
const defaultResolve = (id) => createRequire(import.meta.url).resolve(id);
|
|
7
|
+
/** Reads and parses a manifest; undefined when it is absent or not JSON. */
|
|
8
|
+
const tryReadJson = (path) => {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Where the root manifest may live, in order: the project being run in (a consumer
|
|
18
|
+
* install has only its own), the workspace root beside these sources, and finally this
|
|
19
|
+
* package's own manifest, which exists in every installed layout.
|
|
20
|
+
*/
|
|
21
|
+
export function rootPackageCandidates(cwd = process.cwd()) {
|
|
22
|
+
return [
|
|
23
|
+
join(cwd, "package.json"),
|
|
24
|
+
fileURLToPath(new URL("../../../package.json", import.meta.url)),
|
|
25
|
+
fileURLToPath(new URL("../package.json", import.meta.url)),
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
/** First candidate that reads and parses; an empty manifest when none does. */
|
|
29
|
+
function readRootPackage(candidates) {
|
|
30
|
+
for (const path of candidates) {
|
|
31
|
+
const value = tryReadJson(path);
|
|
32
|
+
if (value !== undefined)
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One sibling package's version. Installed layouts name siblings `@anvpx/motion-<name>`,
|
|
39
|
+
* so the manifest is resolved by package name; the workspace checkout keeps `../../<name>`
|
|
40
|
+
* as a fallback, and a total miss is `"unknown"` rather than a throw.
|
|
41
|
+
*/
|
|
42
|
+
function packageVersion(name, resolve, base) {
|
|
43
|
+
try {
|
|
44
|
+
const installed = tryReadJson(resolve(`@anvpx/motion-${name}/package.json`));
|
|
45
|
+
if (installed?.version !== undefined)
|
|
46
|
+
return String(installed.version);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Not an installed layout: the workspace sibling below still names the version.
|
|
50
|
+
}
|
|
51
|
+
const sibling = tryReadJson(fileURLToPath(new URL(`../../${name}/package.json`, base)));
|
|
52
|
+
return sibling?.version === undefined ? "unknown" : String(sibling.version);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Versions recorded in manifest.json: workspace packages and the pinned renderer.
|
|
56
|
+
* The root manifest is best-effort provenance, never a render gate: a consumer install
|
|
57
|
+
* without a repo root yields the unpinned/empty shape instead of throwing.
|
|
58
|
+
*/
|
|
59
|
+
export const readVersions = (candidates = rootPackageCandidates(), sources = {}) => {
|
|
60
|
+
const resolve = sources.resolve ?? defaultResolve;
|
|
61
|
+
const base = sources.manifestBase ?? import.meta.url;
|
|
62
|
+
const entries = [...PACKAGES]
|
|
63
|
+
.sort()
|
|
64
|
+
.map((name) => [
|
|
65
|
+
`@anvpx/motion-${name}`,
|
|
66
|
+
packageVersion(name, resolve, base),
|
|
67
|
+
]);
|
|
68
|
+
const root = readRootPackage(candidates);
|
|
69
|
+
return {
|
|
70
|
+
packages: Object.fromEntries(entries),
|
|
71
|
+
hyperframes: root.motionKit?.pins?.hyperframes ?? "unpinned",
|
|
72
|
+
node: process.versions.node,
|
|
73
|
+
};
|
|
74
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anvpx/motion-build",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Storyboard compiler for @anvpx/motion: validation, scene emission and HyperFrames project output.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "anvpx",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=22"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"motion-kit",
|
|
13
|
+
"build",
|
|
14
|
+
"storyboard",
|
|
15
|
+
"hyperframes",
|
|
16
|
+
"video"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./dist/index.js",
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/**/*.js",
|
|
27
|
+
"dist/**/*.d.ts"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@fontsource/inter": "5.3.0",
|
|
31
|
+
"@fontsource/jetbrains-mono": "5.3.0",
|
|
32
|
+
"@fontsource/source-serif-4": "5.3.1",
|
|
33
|
+
"@fontsource/space-grotesk": "5.3.0",
|
|
34
|
+
"@anvpx/motion-scenes": "0.1.0",
|
|
35
|
+
"@anvpx/motion-schema": "0.1.0",
|
|
36
|
+
"@anvpx/motion-themes": "0.1.0",
|
|
37
|
+
"postprocessing": "6.39.5",
|
|
38
|
+
"three": "0.186.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"test:integration": "vitest run --config vitest.integration.config.ts"
|
|
42
|
+
}
|
|
6
43
|
}
|