chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
||||
import { extname, join, posix } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const ROOT = join(import.meta.dirname, "..");
|
||||
const PACKAGES_DIR = join(ROOT, "packages");
|
||||
const DEP_FIELDS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
|
||||
const RUNTIME_IMPORT_EXTENSIONS = new Set([".js", ".mjs", ".cjs", ".json", ".wasm", ".node"]);
|
||||
const PACKED_JAVASCRIPT_FILE_PATTERN = /\.(?:js|mjs|cjs)$/;
|
||||
|
||||
function listWorkspacePackageDirs() {
|
||||
return readdirSync(PACKAGES_DIR)
|
||||
.map((dir) => join("packages", dir))
|
||||
.filter((dir) => existsSync(join(ROOT, dir, "package.json")));
|
||||
}
|
||||
|
||||
function listWorkspaceRefs(pkg) {
|
||||
return DEP_FIELDS.flatMap((field) =>
|
||||
Object.entries(pkg[field] || {})
|
||||
.filter(([, spec]) => String(spec).startsWith("workspace:"))
|
||||
.map(([depName, spec]) => `${field}:${depName}=${spec}`),
|
||||
);
|
||||
}
|
||||
|
||||
function listMissingPublishedExports(pkg) {
|
||||
if (!pkg.exports || !pkg.publishConfig?.exports) return [];
|
||||
|
||||
return Object.keys(pkg.exports).filter((exportKey) => !(exportKey in pkg.publishConfig.exports));
|
||||
}
|
||||
|
||||
function normalizePackagePath(path) {
|
||||
return path.replace(/^\.\//, "");
|
||||
}
|
||||
|
||||
function isPackageLocalPath(path) {
|
||||
return path.startsWith("./") || path.startsWith("dist/") || path.startsWith("src/");
|
||||
}
|
||||
|
||||
function isPublishedSourceEntrypoint(path) {
|
||||
return /^src\/.*\.(?:ts|tsx|mts|cts)$/.test(normalizePackagePath(path));
|
||||
}
|
||||
|
||||
function appendManifestEntry(entries, trail, path) {
|
||||
entries.push({ field: trail.join(".") || "<root>", path });
|
||||
}
|
||||
|
||||
function collectStringEntrypoint(value, trail, entries) {
|
||||
appendManifestEntry(entries, trail, value);
|
||||
return entries;
|
||||
}
|
||||
|
||||
function collectArrayEntrypoints(value, trail, entries) {
|
||||
value.forEach((item, index) =>
|
||||
collectManifestEntrypoints(item, [...trail, String(index)], entries),
|
||||
);
|
||||
return entries;
|
||||
}
|
||||
|
||||
function collectObjectEntrypoints(value, trail, entries) {
|
||||
Object.entries(value).forEach(([key, nested]) =>
|
||||
collectManifestEntrypoints(nested, [...trail, key], entries),
|
||||
);
|
||||
return entries;
|
||||
}
|
||||
|
||||
function isStringEntrypoint(value) {
|
||||
return typeof value === "string";
|
||||
}
|
||||
|
||||
function isArrayEntrypoint(value) {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
|
||||
function isObjectEntrypoint(value) {
|
||||
return Boolean(value) && typeof value === "object";
|
||||
}
|
||||
|
||||
const MANIFEST_ENTRY_COLLECTORS = [
|
||||
[isStringEntrypoint, collectStringEntrypoint],
|
||||
[isArrayEntrypoint, collectArrayEntrypoints],
|
||||
[isObjectEntrypoint, collectObjectEntrypoints],
|
||||
];
|
||||
|
||||
function collectManifestEntrypoints(value, trail = [], entries = []) {
|
||||
const collector = MANIFEST_ENTRY_COLLECTORS.find(([matches]) => matches(value));
|
||||
return collector ? collector[1](value, trail, entries) : entries;
|
||||
}
|
||||
|
||||
function listPackedEntrypoints(pkg) {
|
||||
const entries = [];
|
||||
|
||||
for (const field of ["main", "module", "types", "typings"]) {
|
||||
if (typeof pkg[field] === "string") {
|
||||
entries.push({ field, path: pkg[field] });
|
||||
}
|
||||
}
|
||||
|
||||
if (pkg.exports != null) {
|
||||
entries.push(...collectManifestEntrypoints(pkg.exports, ["exports"]));
|
||||
}
|
||||
|
||||
return entries.filter((entry) => isPackageLocalPath(entry.path));
|
||||
}
|
||||
|
||||
function listPackedFiles(filename) {
|
||||
const output = execFileSync("tar", ["-tf", filename], {
|
||||
cwd: ROOT,
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
return new Set(
|
||||
output
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((path) => path.replace(/^package\//, "")),
|
||||
);
|
||||
}
|
||||
|
||||
function stripSpecifierQuery(specifier) {
|
||||
return specifier.replace(/[?#].*$/, "");
|
||||
}
|
||||
|
||||
function hasExplicitRuntimeExtension(specifier) {
|
||||
return RUNTIME_IMPORT_EXTENSIONS.has(extname(stripSpecifierQuery(specifier)));
|
||||
}
|
||||
|
||||
function listRelativeImportSpecifiers(source) {
|
||||
const patterns = [
|
||||
/^\s*import\s+["'](\.\.?\/[^"']+)["']/gm,
|
||||
/^\s*(?:import|export)\b(?:(?!;)[\s\S])*?\s+from\s+["'](\.\.?\/[^"']+)["']/gm,
|
||||
/\bimport\s*\(\s*["'](\.\.?\/[^"']+)["']\s*\)/gm,
|
||||
/\brequire\s*\(\s*["'](\.\.?\/[^"']+)["']\s*\)/gm,
|
||||
];
|
||||
const specifiers = [];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
for (const match of source.matchAll(pattern)) {
|
||||
specifiers.push({ index: match.index, specifier: match[1] });
|
||||
}
|
||||
}
|
||||
|
||||
return specifiers;
|
||||
}
|
||||
|
||||
function lineNumberAt(source, index) {
|
||||
return source.slice(0, index).split("\n").length;
|
||||
}
|
||||
|
||||
function readPackedFile(filename, file) {
|
||||
return execFileSync("tar", ["-xOf", filename, `package/${file}`], {
|
||||
cwd: ROOT,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 64 * 1024 * 1024,
|
||||
});
|
||||
}
|
||||
|
||||
function verifyPackedEntrypoints(workspace, packedPackage, packedFiles) {
|
||||
const entries = listPackedEntrypoints(packedPackage);
|
||||
const sourceEntries = entries.filter((entry) => isPublishedSourceEntrypoint(entry.path));
|
||||
if (sourceEntries.length > 0) {
|
||||
throw new Error(
|
||||
`Packed manifest for ${workspace} exposes source TypeScript entrypoints: ` +
|
||||
sourceEntries.map((entry) => `${entry.field}:${entry.path}`).join(", "),
|
||||
);
|
||||
}
|
||||
|
||||
const missingEntries = entries.filter((entry) => {
|
||||
const normalized = normalizePackagePath(entry.path);
|
||||
return !normalized.includes("*") && !packedFiles.has(normalized);
|
||||
});
|
||||
|
||||
if (missingEntries.length > 0) {
|
||||
throw new Error(
|
||||
`Packed manifest for ${workspace} points at missing files: ` +
|
||||
missingEntries.map((entry) => `${entry.field}:${entry.path}`).join(", "),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePackedRelativeImport(fromFile, specifier) {
|
||||
return posix.normalize(posix.join(posix.dirname(fromFile), stripSpecifierQuery(specifier)));
|
||||
}
|
||||
|
||||
export function listPackedJavaScriptImportIssues(filename, packedFiles) {
|
||||
return [...packedFiles]
|
||||
.filter((file) => PACKED_JAVASCRIPT_FILE_PATTERN.test(file))
|
||||
.flatMap((file) => {
|
||||
const source = readPackedFile(filename, file);
|
||||
return listRelativeImportSpecifiers(source).flatMap(({ index, specifier }) => {
|
||||
if (!hasExplicitRuntimeExtension(specifier)) {
|
||||
return [`${file}:${lineNumberAt(source, index)} imports ${specifier}`];
|
||||
}
|
||||
|
||||
const target = resolvePackedRelativeImport(file, specifier);
|
||||
if (!packedFiles.has(target)) {
|
||||
return [`${file}:${lineNumberAt(source, index)} imports missing ${specifier}`];
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function verifyPackedJavaScriptImports(workspace, filename, packedFiles) {
|
||||
const importIssues = listPackedJavaScriptImportIssues(filename, packedFiles);
|
||||
if (importIssues.length > 0) {
|
||||
throw new Error(
|
||||
`Packed JavaScript for ${workspace} contains Node-incompatible relative imports: ` +
|
||||
importIssues.slice(0, 10).join(", "),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function parsePackJson(output, workspace) {
|
||||
try {
|
||||
const parsed = JSON.parse(output);
|
||||
return Array.isArray(parsed) ? parsed : [parsed];
|
||||
} catch {
|
||||
throw new Error(`Could not parse pnpm pack JSON output for ${workspace}`);
|
||||
}
|
||||
}
|
||||
|
||||
function readWorkspacePackage(workspace) {
|
||||
return JSON.parse(readFileSync(join(ROOT, workspace, "package.json"), "utf8"));
|
||||
}
|
||||
|
||||
function assertPublishedExportsMatchSource(workspace, sourcePackageJson) {
|
||||
const missingPublishedExports = listMissingPublishedExports(sourcePackageJson);
|
||||
if (missingPublishedExports.length === 0) return;
|
||||
|
||||
throw new Error(
|
||||
`${workspace} publishConfig.exports is missing source exports: ${missingPublishedExports.join(", ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
function packWorkspace(workspace, packDir) {
|
||||
const packOutput = execFileSync("pnpm", ["pack", "--json", "--pack-destination", packDir], {
|
||||
cwd: join(ROOT, workspace),
|
||||
encoding: "utf8",
|
||||
});
|
||||
const [{ filename }] = parsePackJson(packOutput, workspace);
|
||||
return filename;
|
||||
}
|
||||
|
||||
function readPackedPackage(filename) {
|
||||
const packedPackageJson = execFileSync("tar", ["-xOf", filename, "package/package.json"], {
|
||||
cwd: ROOT,
|
||||
encoding: "utf8",
|
||||
});
|
||||
return JSON.parse(packedPackageJson);
|
||||
}
|
||||
|
||||
function assertNoWorkspaceRefs(workspace, packedPackage) {
|
||||
const packedRefs = listWorkspaceRefs(packedPackage);
|
||||
if (packedRefs.length === 0) return;
|
||||
|
||||
throw new Error(
|
||||
`Packed manifest for ${workspace} still contains workspace refs: ${packedRefs.join(", ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
function verifyPackedWorkspace(workspace, filename) {
|
||||
const packedPackage = readPackedPackage(filename);
|
||||
const packedFiles = listPackedFiles(filename);
|
||||
|
||||
assertNoWorkspaceRefs(workspace, packedPackage);
|
||||
verifyPackedEntrypoints(workspace, packedPackage, packedFiles);
|
||||
verifyPackedJavaScriptImports(workspace, filename, packedFiles);
|
||||
}
|
||||
|
||||
function verifyWorkspace(workspace) {
|
||||
const sourcePackageJson = readWorkspacePackage(workspace);
|
||||
if (sourcePackageJson.private) return;
|
||||
|
||||
assertPublishedExportsMatchSource(workspace, sourcePackageJson);
|
||||
|
||||
const packDir = mkdtempSync(join(tmpdir(), "hyperframes-pack-"));
|
||||
try {
|
||||
verifyPackedWorkspace(workspace, packWorkspace(workspace, packDir));
|
||||
console.log(`Verified ${workspace}: packed manifest is publish-safe.`);
|
||||
} finally {
|
||||
rmSync(packDir, { force: true, recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
listWorkspacePackageDirs().forEach(verifyWorkspace);
|
||||
}
|
||||
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
main();
|
||||
}
|
||||
Reference in New Issue
Block a user