UNPKG

@iobroker/create-adapter

Version:

Command line utility to create customized ioBroker adapters

353 lines 14.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); const JSON5 = __importStar(require("json5")); const licenses_1 = require("../src/lib/core/licenses"); const questions_1 = require("../src/lib/core/questions"); const packageVersions_1 = require("../src/lib/packageVersions"); const constants_1 = require("../src/lib/constants"); const templateFunction = async (answers) => { // Limit package version downloads to 10 simultaneous connections const pLimit = await import("p-limit"); const downloadLimiter = pLimit.default(10); const isAdapter = answers.features.indexOf("adapter") > -1; const isWidget = answers.features.indexOf("vis") > -1; const useTypeScript = answers.language === "TypeScript"; const useTSWithoutBuild = answers.language === "TypeScript (without build)"; const useTypeChecking = useTypeScript || useTSWithoutBuild || (answers.tools && answers.tools.indexOf("type checking") > -1); const useAdminReact = answers.adminUi === "react"; const useTabReact = answers.tabReact === "yes"; const useReact = useAdminReact || useTabReact; const useESLint = answers.tools && answers.tools.indexOf("ESLint") > -1; const useOfficialESLintConfig = useESLint && answers.eslintConfig === "official"; const usePrettier = answers.tools && answers.tools.indexOf("Prettier") > -1; const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1; const useReleaseScript = answers.releaseScript === "yes"; const useDevServerLocal = answers.devServer === "local"; const minNodeVersion = answers.nodeVersion ?? constants_1.RECOMMENDED_NODE_VERSION_FALLBACK; const dependencyPromises = [...(isAdapter ? ["@iobroker/adapter-core"] : [])] .sort() .map(dep => async () => `"${dep}": "${await (0, packageVersions_1.fetchPackageReferenceVersion)(dep)}"`) .map(task => downloadLimiter(task)); const dependencies = await Promise.all(dependencyPromises); const devDependencyPromises = [ ...[ // testing and translations are always required "@iobroker/testing", "@iobroker/adapter-dev", ], ...(isAdapter ? [ // Testing dependencies are now included in @iobroker/testing 5.2.x ] : []), ...(isAdapter && useTypeChecking ? [ // Type definitions for testing dependencies are now included in @iobroker/testing 5.2.x // Recommended tsconfig for the minimum supported Node.js version `@tsconfig/node${minNodeVersion}`, // and NodeJS typings `@types/node@${minNodeVersion}`, ] : []), ...(useTypeChecking ? ["typescript@~5.9"] : []), ...(useTypeScript ? [ // enhance testing through TS tools "source-map-support", "ts-node", // to clean the build dir "rimraf", ] : []), ...(useTSWithoutBuild ? [ // enhance testing through TS tools "source-map-support", "ts-node", ] : []), ...(useReact ? [ // React "react@17", "react-dom@17", // ioBroker react framework "@iobroker/adapter-react@2.0.22", // UI library "@material-ui/core", ] : []), ...(useTypeChecking && useReact ? [ // React's type definitions "@types/react@17", "@types/react-dom@17", ] : []), ...(useOfficialESLintConfig ? [ // Use the official ioBroker ESLint config "@iobroker/eslint-config", ] : []), ...(useESLint && !useOfficialESLintConfig ? [ // Upgrade to ESLint 9 for custom configuration "eslint@^9", "@eslint/js@^9", ] : []), ...(useESLint && !useOfficialESLintConfig && useTypeScript ? ["@typescript-eslint/eslint-plugin@^8", "@typescript-eslint/parser@^8"] : []), ...(useESLint && !useOfficialESLintConfig && useReact ? ["eslint-plugin-react"] : []), ...(useESLint && !useOfficialESLintConfig && usePrettier ? ["eslint-config-prettier", "eslint-plugin-prettier", "prettier"] : []), ...(useNyc ? ["nyc"] : []), ...(useReleaseScript ? [ "@alcalzone/release-script", "@alcalzone/release-script-plugin-iobroker", "@alcalzone/release-script-plugin-license", "@alcalzone/release-script-plugin-manual-review", ] : []), ...(useDevServerLocal ? ["@iobroker/dev-server"] : []), ] .sort() .map(dep => async () => `"${(0, packageVersions_1.getPackageName)(dep)}": "${await (0, packageVersions_1.fetchPackageReferenceVersion)(dep)}"`) .map(task => downloadLimiter(task)); const devDependencies = await Promise.all(devDependencyPromises); // Add ioBroker types using npm alias to make IDE treat it like @types package if (isAdapter && useTypeChecking) { const iobrokerTypesVersion = await (0, packageVersions_1.fetchPackageReferenceVersion)("@iobroker/types"); devDependencies.push(`"@types/iobroker": "npm:@iobroker/types@${iobrokerTypesVersion}"`); } // Sort dependencies alphabetically, with @-scoped packages first devDependencies.sort((a, b) => { const aName = a.match(/"([^"]+)":/)?.[1] || ""; const bName = b.match(/"([^"]+)":/)?.[1] || ""; const aIsScoped = aName.startsWith("@"); const bIsScoped = bName.startsWith("@"); if (aIsScoped && !bIsScoped) return -1; if (!aIsScoped && bIsScoped) return 1; return aName.localeCompare(bName); }); const gitUrl = answers.gitRemoteProtocol === "HTTPS" ? `https://github.com/${answers.authorGithub}/ioBroker.${answers.adapterName}.git` : `git@github.com:${answers.authorGithub}/ioBroker.${answers.adapterName}.git`; // Generate whitelist for package files const packageFiles = [ "LICENSE", "io-package.json", // We currently don't have web templates, but users might want to add them "www/", ...(isAdapter ? (useTypeScript ? ["build/"] : useTSWithoutBuild ? ["src/"] : ["main.js", "lib/"]) : []), ...(isAdapter ? [ // Web files in the admin root and all subdirectories except src/ "admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}", // JSON files, but not tsconfig.*.json or .eslintrc.json "admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}", ] : []), ...(isAdapter && useReact ? ["admin/build/"] : []), ...(isWidget ? [ // Web files in the widgets folder "widgets/**/*.{html,css,png,svg,jpg,js}", // JSON files, but not tsconfig.*.json or .eslintrc.json "widgets/**/!(tsconfig|tsconfig.*|.eslintrc).json", ] : []), ].sort((a, b) => { // Put directories on top const isDirA = a.includes("/"); const isDirB = b.includes("/"); if (isDirA && !isDirB) { return -1; } if (isDirB && !isDirA) { return 1; } return a.localeCompare(b); }); const npmScripts = {}; if (isAdapter) { if (useTSWithoutBuild && !useReact) { // TS-only mode: no build, just type checking npmScripts.check = "tsc --noEmit"; } else if (useTypeScript && !useReact) { npmScripts.prebuild = `rimraf build`; npmScripts.build = "build-adapter ts"; npmScripts.watch = "build-adapter ts --watch"; npmScripts["prebuild:ts"] = `rimraf build`; npmScripts["build:ts"] = "build-adapter ts"; npmScripts["watch:ts"] = "build-adapter ts --watch"; } else if (useReact && !useTypeScript && !useTSWithoutBuild) { npmScripts.prebuild = `rimraf admin/build`; npmScripts.build = "build-adapter react"; npmScripts.watch = "build-adapter react --watch"; npmScripts["prebuild:react"] = `rimraf admin/build`; npmScripts["build:react"] = "build-adapter react"; npmScripts["watch:react"] = "build-adapter react --watch"; } else if (useReact && useTypeScript) { npmScripts.prebuild = `rimraf build admin/build`; npmScripts.build = "build-adapter all"; npmScripts.watch = "build-adapter all --watch"; npmScripts["prebuild:ts"] = `rimraf build`; npmScripts["build:ts"] = "build-adapter ts"; npmScripts["watch:ts"] = "build-adapter ts --watch"; npmScripts["prebuild:react"] = `rimraf admin/build`; npmScripts["build:react"] = "build-adapter react"; npmScripts["watch:react"] = "build-adapter react --watch"; } if (useTypeScript || useTSWithoutBuild) { npmScripts["test:ts"] = "mocha --config test/mocharc.custom.json src/**/*.test.ts"; } else { npmScripts["test:js"] = `mocha --config test/mocharc.custom.json "{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}"`; } npmScripts["test:package"] = "mocha test/package --exit"; npmScripts["test:integration"] = "mocha test/integration --exit"; npmScripts.test = `${useTypeScript || useTSWithoutBuild ? "npm run test:ts" : "npm run test:js"} && npm run test:package`; if (useTypeChecking && !useTSWithoutBuild) { if (useReact) { npmScripts.check = `tsc --noEmit${useTypeScript ? " && tsc --noEmit -p admin/tsconfig.json" : " -p tsconfig.check.json"}`; } else { npmScripts.check = `tsc --noEmit${useTypeScript ? "" : " -p tsconfig.check.json"}`; } } if (useNyc && (useTypeScript || useTSWithoutBuild)) { npmScripts.coverage = "nyc npm run test:ts"; } if (useESLint) { // Both official and custom configs now use ESLint 9 flat config format npmScripts.lint = "eslint -c eslint.config.mjs ."; } } else if (isWidget) { npmScripts["test:package"] = "mocha test/package --exit"; npmScripts.test = "npm run test:package"; } npmScripts.translate = "translate-adapter"; if (useReleaseScript) { npmScripts.release = "release-script"; } if (useDevServerLocal) { npmScripts["dev-server"] = "dev-server"; } // Always include contributors section as an array const allContributors = []; // Add contributors if specified if (answers.contributors && answers.contributors.length) { for (const contributorName of answers.contributors) { allContributors.push({ name: contributorName }); } } const template = ` { "name": "iobroker.${answers.adapterName.toLowerCase()}", "version": "0.0.1", "description": "${answers.description || answers.adapterName}", "author": { "name": "${answers.authorName}", "email": "${answers.authorEmail}", }, "contributors": ${JSON.stringify(allContributors)}, "homepage": "https://github.com/${answers.authorGithub}/ioBroker.${answers.adapterName}", "license": "${licenses_1.licenses[answers.license].id}", "keywords": ${JSON.stringify(answers.keywords || (0, questions_1.getDefaultAnswer)("keywords"))}, "repository": { "type": "git", "url": "${gitUrl}", }, "engines": { "node": ">= ${minNodeVersion}" }, "dependencies": {${dependencies.join(",")}}, "devDependencies": {${devDependencies.join(",")}}, ${isAdapter ? ` "main": "${useTSWithoutBuild ? "src/main.ts" : useTypeScript ? "build/main.js" : "main.js"}", ` : isWidget ? ` "main": "widgets/${answers.adapterName}.html", ` : ""} "files": ${JSON.stringify(packageFiles)}, "scripts": ${JSON.stringify(npmScripts)}, ${useNyc ? `"nyc": { "include": [ "src/**/*.ts", ], "exclude": [ "src/**/*.test.ts", ], "extension": [ ".ts", ], "require": [ "ts-node/register", ], "reporter": [ "text-summary", "html", ], "sourceMap": true, "instrument": true, },` : ""} "bugs": { "url": "https://github.com/${answers.authorGithub}/ioBroker.${answers.adapterName}/issues", }, "readmeFilename": "README.md", }`; return JSON.stringify(JSON5.parse(template), null, 2); }; // package.json is always formatted with 2 spaces templateFunction.noReformat = true; module.exports = templateFunction; //# sourceMappingURL=package.json.js.map