diff --git a/scripts/check-capacitor-plugin-wiring.mjs b/scripts/check-capacitor-plugin-wiring.mjs index 538d9b5..f1243d2 100644 --- a/scripts/check-capacitor-plugin-wiring.mjs +++ b/scripts/check-capacitor-plugin-wiring.mjs @@ -15,26 +15,26 @@ * node scripts/check-capacitor-plugin-wiring.mjs --dir path # checks given plugin dir */ -import fs from "node:fs"; -import path from "node:path"; +import fs from 'node:fs'; +import path from 'node:path'; const SKIP_DIRS = new Set([ - "node_modules", - "dist", - "build", - ".build", - ".gradle", - "Pods", - "DerivedData", - ".swiftpm", - ".git", + 'node_modules', + 'dist', + 'build', + '.build', + '.gradle', + 'Pods', + 'DerivedData', + '.swiftpm', + '.git', ]); function readText(p) { try { - return fs.readFileSync(p, "utf8"); + return fs.readFileSync(p, 'utf8'); } catch { - return ""; + return ''; } } @@ -90,8 +90,8 @@ function parseArgs(argv) { const out = { dir: process.cwd() }; for (let i = 2; i < argv.length; i++) { const a = argv[i]; - if (a === "--dir" || a === "--pluginDir") { - out.dir = path.resolve(argv[++i] || "."); + if (a === '--dir' || a === '--pluginDir') { + out.dir = path.resolve(argv[++i] || '.'); continue; } } @@ -100,7 +100,7 @@ function parseArgs(argv) { const args = parseArgs(process.argv); const pluginDir = args.dir; -const pkgPath = path.join(pluginDir, "package.json"); +const pkgPath = path.join(pluginDir, 'package.json'); if (!exists(pkgPath)) { console.error(`[wiring] ERROR: missing package.json in ${pluginDir}`); @@ -115,9 +115,9 @@ try { process.exit(2); } -const cap = typeof pkg.capacitor === "object" && pkg.capacitor ? pkg.capacitor : {}; -const supportsAndroid = typeof cap.android === "object" && cap.android; -const supportsIos = typeof cap.ios === "object" && cap.ios; +const cap = typeof pkg.capacitor === 'object' && pkg.capacitor ? pkg.capacitor : {}; +const supportsAndroid = typeof cap.android === 'object' && cap.android; +const supportsIos = typeof cap.ios === 'object' && cap.ios; // Not a Capacitor plugin package (e.g. meta/workspace package). // We only enforce wiring rules for actual plugin packages declaring a `capacitor` config. @@ -126,10 +126,10 @@ if (!supportsAndroid && !supportsIos) { } // ---------------- JS (registerPlugin) ---------------- -const jsSrcDir = path.join(pluginDir, "src"); -let jsName = ""; +const jsSrcDir = path.join(pluginDir, 'src'); +let jsName = ''; if (exists(jsSrcDir)) { - const jsFiles = walkFiles(jsSrcDir, [".ts", ".js"]); + const jsFiles = walkFiles(jsSrcDir, ['.ts', '.js']); const reRegister = /registerPlugin(?:<[^>]*>)?\(\s*['"]([^'"]+)['"]/; for (const f of jsFiles) { const m = reRegister.exec(readText(f)); @@ -143,12 +143,12 @@ if (exists(jsSrcDir)) { // ---------------- Android (@CapacitorPlugin) ---------------- let androidNames = []; if (supportsAndroid) { - const androidMain = path.join(pluginDir, "android", "src", "main"); - const files = walkFiles(androidMain, [".java", ".kt"]); + const androidMain = path.join(pluginDir, 'android', 'src', 'main'); + const files = walkFiles(androidMain, ['.java', '.kt']); const foundAnnotations = []; for (const f of files) { const txt = readText(f); - if (!txt.includes("@CapacitorPlugin")) continue; + if (!txt.includes('@CapacitorPlugin')) continue; foundAnnotations.push(f); const m = /@CapacitorPlugin\(\s*name\s*=\s*"([^"]+)"/.exec(txt) || @@ -160,7 +160,7 @@ if (supportsAndroid) { // Enforce explicit name attribute to prevent silent class-name drift. if (foundAnnotations.length && !androidNames.length) { console.error( - `[wiring] ERROR: Android has @CapacitorPlugin but none specify name = \"...\". Add an explicit name to the plugin class.` + `[wiring] ERROR: Android has @CapacitorPlugin but none specify name = \"...\". Add an explicit name to the plugin class.`, ); process.exit(1); } @@ -169,13 +169,13 @@ if (supportsAndroid) { // ---------------- iOS (jsName) ---------------- let iosJsNames = []; if (supportsIos) { - const iosDir = path.join(pluginDir, "ios"); - const scanRoot = exists(path.join(iosDir, "Sources")) ? path.join(iosDir, "Sources") : iosDir; - const swiftFiles = walkFiles(scanRoot, [".swift"]); + const iosDir = path.join(pluginDir, 'ios'); + const scanRoot = exists(path.join(iosDir, 'Sources')) ? path.join(iosDir, 'Sources') : iosDir; + const swiftFiles = walkFiles(scanRoot, ['.swift']); const reJsName = /\bjsName\s*=\s*"([^"]+)"/g; for (const f of swiftFiles) { const txt = readText(f); - if (!txt.includes("jsName")) continue; + if (!txt.includes('jsName')) continue; let m; while ((m = reJsName.exec(txt))) iosJsNames.push(m[1]); } @@ -186,12 +186,12 @@ if (supportsIos) { function parsePodspecName(podspecPath) { const txt = readText(podspecPath); const m = /\bs\.name\s*=\s*'([^']+)'/.exec(txt); - return m ? m[1] : ""; + return m ? m[1] : ''; } function parseSpmNames(packageSwiftPath) { const txt = readText(packageSwiftPath); - const pkg = /Package\(\s*name\s*:\s*"([^"]+)"/.exec(txt)?.[1] || ""; + const pkg = /Package\(\s*name\s*:\s*"([^"]+)"/.exec(txt)?.[1] || ''; const libs = []; const reLib = /\.library\(\s*name\s*:\s*"([^"]+)"/g; let m; @@ -207,7 +207,7 @@ if (!jsName) { } if (supportsAndroid) { - if (!androidNames.length) errors.push("Android: missing @CapacitorPlugin(name = \"...\")"); + if (!androidNames.length) errors.push('Android: missing @CapacitorPlugin(name = "...")'); if (jsName && androidNames.length && androidNames.some((n) => n !== jsName)) { errors.push(`Android: @CapacitorPlugin(name)=${JSON.stringify(androidNames)} != JS registerPlugin=${jsName}`); } @@ -221,15 +221,16 @@ if (supportsIos) { const podspecs = fs .readdirSync(pluginDir, { withFileTypes: true }) - .filter((e) => e.isFile() && e.name.endsWith(".podspec")) + .filter((e) => e.isFile() && e.name.endsWith('.podspec')) .map((e) => path.join(pluginDir, e.name)) .sort(); - if (!podspecs.length) errors.push("iOS: missing *.podspec at plugin root"); - if (podspecs.length > 1) errors.push(`iOS: multiple podspecs at plugin root: ${podspecs.map((p) => path.basename(p))}`); + if (!podspecs.length) errors.push('iOS: missing *.podspec at plugin root'); + if (podspecs.length > 1) + errors.push(`iOS: multiple podspecs at plugin root: ${podspecs.map((p) => path.basename(p))}`); - const pkgSwift = path.join(pluginDir, "Package.swift"); + const pkgSwift = path.join(pluginDir, 'Package.swift'); if (!exists(pkgSwift)) { - errors.push("iOS: missing Package.swift at plugin root"); + errors.push('iOS: missing Package.swift at plugin root'); } else if (podspecs.length) { const podName = parsePodspecName(podspecs[0]); const { pkgName, libNames } = parseSpmNames(pkgSwift); @@ -245,7 +246,7 @@ if (supportsIos) { } if (errors.length) { - const relDir = path.relative(process.cwd(), pluginDir) || "."; + const relDir = path.relative(process.cwd(), pluginDir) || '.'; console.error(`[wiring] FAIL in ${relDir}`); for (const e of errors) console.error(`- ${e}`); process.exit(1);