- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
182 lines
7.2 KiB
JavaScript
Executable File
182 lines
7.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
import { execFileSync } from "node:child_process";
|
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
import { gunzipSync } from "node:zlib";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
|
|
const root = process.cwd();
|
|
const npmCli = [
|
|
process.env.npm_execpath,
|
|
join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"),
|
|
join(dirname(dirname(process.execPath)), "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
].find((candidate) => candidate && existsSync(candidate));
|
|
const requiredFiles = [
|
|
"package/package.json",
|
|
"package/dist/index.js",
|
|
"package/dist/index.d.ts",
|
|
"package/cep-plugin/CSXS/manifest.xml",
|
|
"package/after-effects-cep-plugin/CSXS/manifest.xml",
|
|
"package/uxp-plugin/manifest.json",
|
|
"package/docs/supported-actions.md",
|
|
"package/docs/mogrt-authoring.md",
|
|
"package/docs/premiere-surface-registry.md",
|
|
"package/docs/adobe-beta-aaf-export-options-drift.md",
|
|
"package/docs/adobe-beta-project-options-drift.md",
|
|
"package/docs/adobe-beta-transition-options-drift.md",
|
|
"package/docs/adobe-beta-rectf-drift.md",
|
|
"package/docs/adobe-beta-color-drift.md",
|
|
"package/docs/adobe-beta-pointf-drift.md",
|
|
"package/docs/adobe-beta-guid-drift.md",
|
|
"package/docs/adobe-beta-frame-rate-drift.md",
|
|
"package/docs/adobe-beta-tick-time-drift.md",
|
|
"package/docs/adobe-beta-c2pa-drift.md",
|
|
"package/docs/adobe-beta-media-drift.md",
|
|
"package/docs/adobe-beta-media-manager-drift.md",
|
|
"package/docs/adobe-beta-transcript-drift.md",
|
|
"package/docs/adobe-beta-work-area-drift.md",
|
|
"package/docs/uxp-js-api-inventory.md",
|
|
"package/docs/premiere-doc-inventory.md",
|
|
"package/docs/native-sdk-header-inventory.md",
|
|
"package/docs/uxp-hybrid-addon-receipt.md",
|
|
"package/docs/uxp-hybrid-ccx-receipt.md",
|
|
"package/docs/uxp-hybrid-benchmark.md",
|
|
"package/docs/cep-reference-inventory.md",
|
|
"package/docs/extendscript-api-inventory.md",
|
|
"package/dist/resources/premiere-surface-registry.json",
|
|
"package/dist/resources/adobe-beta-aaf-export-options-drift.json",
|
|
"package/dist/resources/adobe-beta-project-options-drift.json",
|
|
"package/dist/resources/adobe-beta-transition-options-drift.json",
|
|
"package/dist/resources/adobe-beta-rectf-drift.json",
|
|
"package/dist/resources/adobe-beta-color-drift.json",
|
|
"package/dist/resources/adobe-beta-pointf-drift.json",
|
|
"package/dist/resources/adobe-beta-guid-drift.json",
|
|
"package/dist/resources/adobe-beta-frame-rate-drift.json",
|
|
"package/dist/resources/adobe-beta-tick-time-drift.json",
|
|
"package/dist/resources/adobe-beta-c2pa-drift.json",
|
|
"package/dist/resources/adobe-beta-media-drift.json",
|
|
"package/dist/resources/adobe-beta-media-manager-drift.json",
|
|
"package/dist/resources/adobe-beta-transcript-drift.json",
|
|
"package/dist/resources/adobe-beta-work-area-drift.json",
|
|
"package/dist/resources/uxp-js-api-inventory.json",
|
|
"package/dist/resources/premiere-doc-inventory.json",
|
|
"package/dist/resources/cep-reference-inventory.json",
|
|
"package/dist/resources/extendscript-api-inventory.json",
|
|
"package/scripts/install-cep.ps1",
|
|
"package/scripts/install-cep.sh",
|
|
"package/scripts/uninstall-cep.ps1",
|
|
"package/scripts/uninstall-cep.sh",
|
|
];
|
|
|
|
function tarEntries(tarball) {
|
|
const archive = gunzipSync(readFileSync(tarball));
|
|
const entries = new Set();
|
|
let offset = 0;
|
|
|
|
while (offset + 512 <= archive.length) {
|
|
const header = archive.subarray(offset, offset + 512);
|
|
if (header.every((byte) => byte === 0)) break;
|
|
|
|
const name = header.subarray(0, 100).toString("utf8").replace(/\0.*$/, "");
|
|
const prefix = header.subarray(345, 500).toString("utf8").replace(/\0.*$/, "");
|
|
const sizeText = header.subarray(124, 136).toString("utf8").replace(/\0.*$/, "").trim();
|
|
const size = Number.parseInt(sizeText || "0", 8);
|
|
if (!name || !Number.isSafeInteger(size) || size < 0) {
|
|
throw new Error(`Invalid tar entry at byte ${offset} in ${tarball}`);
|
|
}
|
|
|
|
entries.add(prefix ? `${prefix}/${name}` : name);
|
|
offset += 512 + Math.ceil(size / 512) * 512;
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
function run(command, args, options = {}) {
|
|
return execFileSync(command, args, {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
stdio: "pipe",
|
|
...options,
|
|
});
|
|
}
|
|
|
|
function runNpm(args, options = {}) {
|
|
if (!npmCli) {
|
|
throw new Error("The bundled npm CLI is unavailable for package verification");
|
|
}
|
|
return run(process.execPath, [npmCli, ...args], options);
|
|
}
|
|
|
|
let tarball;
|
|
let installDir;
|
|
let packDir;
|
|
|
|
try {
|
|
packDir = mkdtempSync(join(tmpdir(), "premiere-pro-mcp-pack-output-"));
|
|
const packed = JSON.parse(
|
|
runNpm(["pack", "--json", "--ignore-scripts", "--pack-destination", packDir]),
|
|
);
|
|
const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
const packEntries = Array.isArray(packed)
|
|
? packed
|
|
: packed && typeof packed === "object"
|
|
? Object.values(packed)
|
|
: [];
|
|
const matchingPackages = packEntries.filter(
|
|
(entry) =>
|
|
entry?.name === packageJson.name &&
|
|
entry?.version === packageJson.version &&
|
|
typeof entry?.filename === "string",
|
|
);
|
|
if (matchingPackages.length !== 1) {
|
|
throw new Error("npm pack did not return exactly one package matching package.json");
|
|
}
|
|
|
|
tarball = resolve(packDir, matchingPackages[0].filename);
|
|
const entries = tarEntries(tarball);
|
|
const missing = requiredFiles.filter((path) => !entries.has(path));
|
|
if (missing.length > 0) {
|
|
throw new Error(`npm package is missing required files: ${missing.join(", ")}`);
|
|
}
|
|
|
|
installDir = mkdtempSync(join(tmpdir(), "premiere-pro-mcp-pack-"));
|
|
runNpm(["install", "--ignore-scripts", "--no-audit", "--no-fund", tarball], {
|
|
cwd: installDir,
|
|
});
|
|
|
|
const installedCli = join(installDir, "node_modules", "premiere-pro-mcp", "dist", "index.js");
|
|
if (!existsSync(installedCli)) {
|
|
throw new Error("isolated package installation did not contain the CLI entrypoint");
|
|
}
|
|
const installedPackageRoot = join(installDir, "node_modules", "premiere-pro-mcp");
|
|
const installedRegistry = JSON.parse(readFileSync(join(
|
|
installedPackageRoot,
|
|
"dist",
|
|
"resources",
|
|
"premiere-surface-registry.json",
|
|
), "utf8"));
|
|
if (installedRegistry.schemaVersion !== 1 || !Array.isArray(installedRegistry.integrationSurfaces)) {
|
|
throw new Error("installed package did not contain a valid Premiere surface registry");
|
|
}
|
|
for (const surface of installedRegistry.integrationSurfaces) {
|
|
if (surface.inventoryArtifact !== null &&
|
|
(typeof surface.inventoryArtifact !== "string" || !existsSync(join(installedPackageRoot, surface.inventoryArtifact)))) {
|
|
throw new Error(`installed package registry references a missing inventory artifact: ${surface.id}`);
|
|
}
|
|
}
|
|
const help = run(process.execPath, [installedCli, "--help"], { cwd: installDir });
|
|
if (!help.includes("Usage:")) {
|
|
throw new Error("installed CLI --help did not return the expected usage text");
|
|
}
|
|
|
|
console.log(
|
|
`Verified npm package contents and isolated CLI install: ${matchingPackages[0].filename}`,
|
|
);
|
|
} finally {
|
|
if (installDir) rmSync(installDir, { recursive: true, force: true });
|
|
if (tarball) rmSync(tarball, { force: true });
|
|
if (packDir) rmSync(packDir, { recursive: true, force: true });
|
|
}
|