feat: initial commit - Jhonny Editor
- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
This commit is contained in:
Executable
+181
@@ -0,0 +1,181 @@
|
||||
#!/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 });
|
||||
}
|
||||
Reference in New Issue
Block a user