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:
+168
@@ -0,0 +1,168 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import ts from "typescript";
|
||||
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const packagePath = resolve(root, "node_modules/@adobe/cc-ext-uxp-types/package.json");
|
||||
const declarationsPath = process.env.UXP_JS_DECLARATIONS_PATH
|
||||
? resolve(process.env.UXP_JS_DECLARATIONS_PATH)
|
||||
: resolve(root, "node_modules/@adobe/cc-ext-uxp-types/uxp/index.d.ts");
|
||||
const coveragePath = resolve(root, "src/resources/uxp-js-coverage.json");
|
||||
const outputPath = resolve(root, "src/resources/uxp-js-api-inventory.json");
|
||||
const check = process.argv.includes("--check");
|
||||
const validateOnly = process.argv.includes("--validate-only");
|
||||
|
||||
const [packageText, declarationsText, coverageText] = await Promise.all([
|
||||
readFile(packagePath, "utf8"),
|
||||
readFile(declarationsPath, "utf8"),
|
||||
readFile(coveragePath, "utf8"),
|
||||
]);
|
||||
const packageMetadata = JSON.parse(packageText);
|
||||
const coverage = JSON.parse(coverageText);
|
||||
const mappedSymbols = new Set(coverage.entries.flatMap((entry) => entry.uxpApi));
|
||||
const source = ts.createSourceFile(declarationsPath, declarationsText, ts.ScriptTarget.Latest, true);
|
||||
if (source.parseDiagnostics.length > 0) {
|
||||
const details = source.parseDiagnostics
|
||||
.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, " "))
|
||||
.join("; ");
|
||||
throw new Error(`TypeScript declaration parse failed: ${details}`);
|
||||
}
|
||||
|
||||
const normalizedDeclarations = declarationsText.replaceAll("\r\n", "\n");
|
||||
const declarationsSha256 = createHash("sha256").update(normalizedDeclarations).digest("hex");
|
||||
const symbols = [];
|
||||
const compareText = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
||||
const cleanName = (node) => node.getText(source).replaceAll('"', "").replaceAll("'", "");
|
||||
const joinName = (owner, name) => owner ? `${owner}.${name}` : name;
|
||||
|
||||
function add(symbol, kind) {
|
||||
symbols.push({ symbol, kind });
|
||||
}
|
||||
|
||||
function memberName(member) {
|
||||
if (ts.isConstructorDeclaration(member) || ts.isConstructSignatureDeclaration(member)) return "[[construct]]";
|
||||
if (ts.isCallSignatureDeclaration(member)) return "[[call]]";
|
||||
if (ts.isIndexSignatureDeclaration(member)) return "[[index]]";
|
||||
if (!member.name) throw new Error(`Unsupported anonymous UXP member: ${ts.SyntaxKind[member.kind]}`);
|
||||
return cleanName(member.name);
|
||||
}
|
||||
|
||||
function memberKind(member) {
|
||||
if (ts.isConstructorDeclaration(member) || ts.isConstructSignatureDeclaration(member)) return "constructor";
|
||||
if (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) return "method";
|
||||
if (ts.isPropertyDeclaration(member) || ts.isPropertySignature(member)) return "property";
|
||||
if (ts.isGetAccessorDeclaration(member)) return "getter";
|
||||
if (ts.isSetAccessorDeclaration(member)) return "setter";
|
||||
if (ts.isCallSignatureDeclaration(member)) return "call";
|
||||
if (ts.isIndexSignatureDeclaration(member)) return "index";
|
||||
throw new Error(`Unsupported UXP type member: ${ts.SyntaxKind[member.kind]}`);
|
||||
}
|
||||
|
||||
function collectMembers(owner, members) {
|
||||
for (const member of members) add(joinName(owner, memberName(member)), memberKind(member));
|
||||
}
|
||||
|
||||
function collectTypeNode(owner, node) {
|
||||
if (ts.isTypeLiteralNode(node)) {
|
||||
collectMembers(owner, node.members);
|
||||
} else if (ts.isIntersectionTypeNode(node) || ts.isUnionTypeNode(node)) {
|
||||
for (const type of node.types) collectTypeNode(owner, type);
|
||||
} else if (ts.isParenthesizedTypeNode(node)) {
|
||||
collectTypeNode(owner, node.type);
|
||||
}
|
||||
}
|
||||
|
||||
function collectStatements(statements, owner = "globalThis") {
|
||||
for (const statement of statements) {
|
||||
if (ts.isModuleDeclaration(statement)) {
|
||||
const moduleOwner = joinName(owner === "globalThis" ? "" : owner, cleanName(statement.name));
|
||||
add(moduleOwner, "module");
|
||||
collectModuleBody(statement.body, moduleOwner);
|
||||
} else if (ts.isClassDeclaration(statement) || ts.isInterfaceDeclaration(statement)) {
|
||||
if (!statement.name) throw new Error(`Anonymous UXP declaration: ${ts.SyntaxKind[statement.kind]}`);
|
||||
const symbol = joinName(owner, statement.name.text);
|
||||
add(symbol, ts.isClassDeclaration(statement) ? "class" : "interface");
|
||||
collectMembers(symbol, statement.members);
|
||||
} else if (ts.isTypeAliasDeclaration(statement)) {
|
||||
const symbol = joinName(owner, statement.name.text);
|
||||
add(symbol, "type");
|
||||
collectTypeNode(symbol, statement.type);
|
||||
} else if (ts.isEnumDeclaration(statement)) {
|
||||
const symbol = joinName(owner, statement.name.text);
|
||||
add(symbol, "enum");
|
||||
for (const member of statement.members) add(joinName(symbol, cleanName(member.name)), "enumMember");
|
||||
} else if (ts.isFunctionDeclaration(statement)) {
|
||||
if (!statement.name) throw new Error("Anonymous UXP function declaration");
|
||||
add(joinName(owner, statement.name.text), "function");
|
||||
} else if (ts.isVariableStatement(statement)) {
|
||||
for (const declaration of statement.declarationList.declarations) {
|
||||
if (!ts.isIdentifier(declaration.name)) throw new Error("Unsupported destructured UXP variable declaration");
|
||||
add(joinName(owner, declaration.name.text), "variable");
|
||||
}
|
||||
} else if (ts.isExportAssignment(statement) || ts.isExportDeclaration(statement) || ts.isImportDeclaration(statement)) {
|
||||
// Module wiring does not add a callable or inspectable API symbol.
|
||||
} else {
|
||||
throw new Error(`Unsupported top-level UXP declaration: ${ts.SyntaxKind[statement.kind]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function collectModuleBody(body, owner) {
|
||||
if (!body) throw new Error(`UXP module ${owner} has no body`);
|
||||
if (ts.isModuleDeclaration(body)) {
|
||||
const nestedOwner = joinName(owner, cleanName(body.name));
|
||||
add(nestedOwner, "module");
|
||||
collectModuleBody(body.body, nestedOwner);
|
||||
} else if (ts.isModuleBlock(body)) {
|
||||
collectStatements(body.statements, owner);
|
||||
} else {
|
||||
throw new Error(`Unsupported UXP module body: ${ts.SyntaxKind[body.kind]}`);
|
||||
}
|
||||
}
|
||||
|
||||
collectStatements(source.statements);
|
||||
const uniqueSymbols = [...new Map(symbols.map((entry) => [entry.symbol, entry])).values()]
|
||||
.sort((left, right) => compareText(left.symbol, right.symbol));
|
||||
const declaredSymbols = new Set(uniqueSymbols.map((entry) => entry.symbol));
|
||||
const entries = uniqueSymbols.map((entry) => ({
|
||||
...entry,
|
||||
coverage: mappedSymbols.has(entry.symbol) ? "mapped" : "unmapped",
|
||||
}));
|
||||
const mapped = entries.filter((entry) => entry.coverage === "mapped").length;
|
||||
const manifestOnly = [...mappedSymbols].filter((symbol) => !declaredSymbols.has(symbol)).sort(compareText);
|
||||
const inventory = {
|
||||
schemaVersion: 1,
|
||||
source: {
|
||||
package: "@adobe/cc-ext-uxp-types",
|
||||
version: packageMetadata.version,
|
||||
declarations: "node_modules/@adobe/cc-ext-uxp-types/uxp/index.d.ts",
|
||||
declarationsSha256,
|
||||
coverageManifest: "src/resources/uxp-js-coverage.json",
|
||||
},
|
||||
semantics: {
|
||||
mapped: "The exact declaration symbol is referenced by panel coverage; this alone is not licensed-host verification.",
|
||||
unmapped: "No panel coverage entry references the exact declaration symbol; this is a review queue, not a requirement for a standalone MCP tool.",
|
||||
},
|
||||
stats: { total: entries.length, mapped, unmapped: entries.length - mapped, manifestOnly: manifestOnly.length },
|
||||
manifestOnly,
|
||||
entries,
|
||||
};
|
||||
const rendered = `${JSON.stringify(inventory, null, 2)}\n`;
|
||||
|
||||
if (validateOnly) {
|
||||
console.log(`Validated ${entries.length} UXP JavaScript API symbols from ${packageMetadata.version}.`);
|
||||
} else if (check) {
|
||||
let current = "";
|
||||
try { current = await readFile(outputPath, "utf8"); } catch {}
|
||||
if (current.replaceAll("\r\n", "\n") !== rendered) {
|
||||
console.error("UXP JavaScript API inventory is stale. Run npm run uxp:js-api-inventory.");
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
console.log(`UXP JavaScript API inventory is current: ${entries.length} symbols from ${packageMetadata.version}.`);
|
||||
}
|
||||
} else {
|
||||
await writeFile(outputPath, rendered);
|
||||
console.log(`Wrote ${entries.length} UXP JavaScript API symbols (${mapped} mapped, ${entries.length - mapped} unmapped).`);
|
||||
}
|
||||
Reference in New Issue
Block a user