From 85aa8cf78a23f7383e2b48cd0eae0127b7d1b202 Mon Sep 17 00:00:00 2001 From: Ernest Teluk Date: Tue, 29 Oct 2024 14:36:03 +0100 Subject: [PATCH 1/4] Add create theme command --- .eslintrc.json | 4 +- package-lock.json | 283 +++++++++++++------------ package.json | 5 +- src/commands/createTheme/index.ts | 125 +++++++++++ src/index.ts | 3 +- src/lib/copyFiles.ts | 23 ++ src/lib/createFolder.ts | 24 +++ src/lib/createTsConfigFileInFolder.ts | 20 ++ src/lib/deleteSpecificFilesInFolder.ts | 19 ++ src/lib/fetchFilesFromGithub.ts | 37 ++++ 10 files changed, 405 insertions(+), 138 deletions(-) create mode 100644 src/commands/createTheme/index.ts create mode 100644 src/lib/copyFiles.ts create mode 100644 src/lib/createFolder.ts create mode 100644 src/lib/createTsConfigFileInFolder.ts create mode 100644 src/lib/deleteSpecificFilesInFolder.ts create mode 100644 src/lib/fetchFilesFromGithub.ts diff --git a/.eslintrc.json b/.eslintrc.json index 1845f8c..8c4be10 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,6 +15,8 @@ "import/no-extraneous-dependencies": 0, "import/prefer-default-export": 0, "@typescript-eslint/no-shadow": 0, - "no-restricted-syntax": 0 + "no-restricted-syntax": 0, + "no-await-in-loop": 0, + "no-promise-executor-return": 0 } } diff --git a/package-lock.json b/package-lock.json index 5aba20e..baa9ff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "uniforms-cli": "index.js" }, "devDependencies": { + "@types/jsdom": "^21.1.7", "@types/prompts": "2.4.2", "commander": "12.1.0", "eslint": "8.57.1", @@ -19,10 +20,11 @@ "eslint-config-airbnb-typescript": "18.0.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-react": "7.37.1", + "https-proxy-agent": "^7.0.5", "kolorist": "1.7.0", - "open": "10.1.0", + "node-fetch": "3.3.2", "prettier": "3.3.3", - "prompts": "^2.4.2", + "prompts": "2.4.2", "typescript": "5.6.3", "typescript-eslint": "8.8.1", "unbuild": "2.0.0" @@ -1096,6 +1098,17 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/@types/jsdom": { + "version": "21.1.7", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", + "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1128,6 +1141,12 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -1395,6 +1414,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1753,21 +1784,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -2113,6 +2129,15 @@ "dev": true, "peer": true }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -2229,34 +2254,6 @@ "node": ">=0.10.0" } }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -2274,18 +2271,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -3347,6 +3332,29 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3416,6 +3424,18 @@ "is-callable": "^1.1.3" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3711,6 +3731,19 @@ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3909,21 +3942,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3972,24 +3990,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -4190,21 +4190,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -4997,6 +4982,43 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", @@ -5162,24 +5184,6 @@ "wrappy": "1" } }, - "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5239,6 +5243,18 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "dev": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6075,18 +6091,6 @@ "typescript": "^4.5 || ^5.0" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7054,6 +7058,15 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 633bdf7..ab6e3a8 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "uniforms-cli": "index.js" }, "devDependencies": { + "@types/jsdom": "^21.1.7", "@types/prompts": "2.4.2", "commander": "12.1.0", "eslint": "8.57.1", @@ -27,9 +28,11 @@ "eslint-config-airbnb-typescript": "18.0.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-react": "7.37.1", + "https-proxy-agent": "^7.0.5", "kolorist": "1.7.0", + "node-fetch": "3.3.2", "prettier": "3.3.3", - "prompts": "^2.4.2", + "prompts": "2.4.2", "typescript": "5.6.3", "typescript-eslint": "8.8.1", "unbuild": "2.0.0" diff --git a/src/commands/createTheme/index.ts b/src/commands/createTheme/index.ts new file mode 100644 index 0000000..7972486 --- /dev/null +++ b/src/commands/createTheme/index.ts @@ -0,0 +1,125 @@ +import { Command } from 'commander'; +import { execSync } from 'node:child_process'; +import prompts, { PromptObject } from 'prompts'; +import { bold, red } from 'kolorist'; +import { fetchFiles } from '../../lib/fetchFilesFromGithub'; +import { createTsConfigFileInFolder } from '../../lib/createTsConfigFileInFolder'; +import { fileTypes } from '../../consts'; +import { deleteSpecificFilesInFolder } from '../../lib/deleteSpecificFilesInFolder'; +import { createFolder } from '../../lib/createFolder'; +import { copyFiles } from '../../lib/copyFiles'; + +const extensionPrompt: PromptObject = { + type: 'select', + name: 'extension', + message: bold('Select extension:'), + choices: () => + fileTypes.map(({ title, color, value }) => ({ + title: color(title), + value, + })), +}; + +const themeNamePrompt: PromptObject = { + type: 'text', + name: 'themeName', + message: bold('Insert theme name:'), + initial: 'my-custom-theme', +}; + +const customDirPrompt: PromptObject = { + type: 'confirm', + name: 'customDir', + message: bold('Choose custom directory?:'), +}; +const customDirPathPrompt: PromptObject = { + type: 'text', + name: 'customDirPath', + message: bold('Insert path to custom directory:'), +}; + +export const createTheme = new Command() + .name('createTheme') + .description('Creates new uniforms theme template') + .option('-n, --name ', 'Insert theme name') + .option('-s, --skip', 'skip custom dir question, and create in current dir') + .option( + '-e, --extension ', + `Select extension (${fileTypes.map(({ value }) => value).join(', ')})`, + ) + .action(async (options) => { + const { + skip: skipFlag, + extension: extensionFlag, + name: themeName, + } = options; + const findExtension = fileTypes.find( + ({ value }) => value === extensionFlag, + ); + + let result: prompts.Answers<'extension' | 'customDir' | 'themeName'>; + try { + result = await prompts( + [ + // @ts-expect-error + ...[themeName ? [] : themeNamePrompt], + // @ts-expect-error + ...[findExtension ? [] : extensionPrompt], + // @ts-expect-error + ...[skipFlag ? [] : customDirPrompt], + ], + { + onCancel: (error) => { + console.log('error', error); + throw new Error(red('✖') + bold(' Operation cancelled')); + }, + }, + ); + } catch (error: any) { + console.log(error.message); + return; + } + + let customDirPath: string | undefined; + let dirPathPromptResult: prompts.Answers<'customDirPath'>; + if (result.customDir) { + try { + dirPathPromptResult = await prompts([customDirPathPrompt], { + onCancel: () => { + throw new Error(red('✖') + bold(' Operation cancelled')); + }, + }); + customDirPath = dirPathPromptResult.customDirPath; + } catch (error: any) { + console.log(error.message); + return; + } + } + + console.log('Fetching custom theme...'); + const { tempDir } = await fetchFiles(); + console.log('Custom theme fetched successfully.'); + + const extension = findExtension?.value || result.extension; + + const isJsx = extension === 'jsx'; + + if (isJsx) { + console.log('Parsing files...'); + createTsConfigFileInFolder(tempDir); + execSync( + `npm install -g typescript --quiet && cd ${tempDir} && npx --yes tsc --noCheck`, + ); + deleteSpecificFilesInFolder(`${tempDir}/striped`, ['types.js']); + console.log('Files parsed successfully.'); + } + + console.log('Creating theme...'); + const createdFolderPath = createFolder({ + folderName: themeName || result.themeName, + customDirPath, + directory: process.cwd(), + }); + copyFiles(isJsx ? `${tempDir}/striped` : `${tempDir}`, createdFolderPath); + console.log('Theme created successfully.'); + }); diff --git a/src/index.ts b/src/index.ts index 9cf6809..44c69c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,13 +2,14 @@ import { Command } from 'commander'; import { version } from '../package.json'; import { init } from './commands/init'; import { createForm } from './commands/createForm'; +import { createTheme } from './commands/createTheme'; (async () => { const program = new Command(); program.version(version).description('CLI for uniforms'); - program.addCommand(init).addCommand(createForm); + program.addCommand(init).addCommand(createForm).addCommand(createTheme); program.parse(); })(); diff --git a/src/lib/copyFiles.ts b/src/lib/copyFiles.ts new file mode 100644 index 0000000..35804bd --- /dev/null +++ b/src/lib/copyFiles.ts @@ -0,0 +1,23 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +export const copyFiles = (sourceFolder: string, destinationFolder: string) => { + if (!fs.existsSync(sourceFolder)) { + console.error(`Source folder not found: ${sourceFolder}`); + return; + } + + if (!fs.existsSync(destinationFolder)) { + fs.mkdirSync(destinationFolder, { recursive: true }); + } + + const files = fs.readdirSync(sourceFolder); + for (const file of files) { + const sourceFilePath = path.join(sourceFolder, file); + const destinationFilePath = path.join(destinationFolder, file); + + if (fs.lstatSync(sourceFilePath).isFile()) { + fs.copyFileSync(sourceFilePath, destinationFilePath); + } + } +}; diff --git a/src/lib/createFolder.ts b/src/lib/createFolder.ts new file mode 100644 index 0000000..b5812a5 --- /dev/null +++ b/src/lib/createFolder.ts @@ -0,0 +1,24 @@ +import path from 'node:path'; +import fs from 'node:fs'; + +export const createFolder = ({ + folderName, + directory = process.cwd(), + customDirPath, +}: { + folderName: string; + directory?: string; + customDirPath?: string; +}) => { + const dirPath = path.join( + directory, + customDirPath ? `/${customDirPath}` : '', + folderName, + ); + + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + + return dirPath; +}; diff --git a/src/lib/createTsConfigFileInFolder.ts b/src/lib/createTsConfigFileInFolder.ts new file mode 100644 index 0000000..959128d --- /dev/null +++ b/src/lib/createTsConfigFileInFolder.ts @@ -0,0 +1,20 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +export const createTsConfigFileInFolder = (folderPath: string) => { + const tsConfig = { + include: [`./**/*`], + compilerOptions: { + outDir: `./striped`, + target: 'es2020', + module: 'es2020', + strict: false, + esModuleInterop: true, + jsx: 'react', + moduleResolution: 'node', + }, + }; + + const filePath = path.join(folderPath, 'tsconfig.json'); + fs.writeFileSync(filePath, JSON.stringify(tsConfig, null, 2)); +}; diff --git a/src/lib/deleteSpecificFilesInFolder.ts b/src/lib/deleteSpecificFilesInFolder.ts new file mode 100644 index 0000000..7130768 --- /dev/null +++ b/src/lib/deleteSpecificFilesInFolder.ts @@ -0,0 +1,19 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { bold, red } from 'kolorist'; + +export const deleteSpecificFilesInFolder = ( + folderPath: string, + filesToDelete: string[], +) => { + if (!fs.existsSync(folderPath)) { + throw new Error(red('✖') + bold(' Operation cancelled')); + } + + for (const file of filesToDelete) { + const filePath = path.join(folderPath, file); + if (fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) { + fs.unlinkSync(filePath); + } + } +}; diff --git a/src/lib/fetchFilesFromGithub.ts b/src/lib/fetchFilesFromGithub.ts new file mode 100644 index 0000000..7d68f50 --- /dev/null +++ b/src/lib/fetchFilesFromGithub.ts @@ -0,0 +1,37 @@ +import fetch from 'node-fetch'; +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; + +const GITHUB_URL = + 'https://github.com/vazco/uniforms/tree/master/packages/uniforms-unstyled/src'; +const RAW_GITHUB_URL = + 'https://raw.githubusercontent.com/vazco/uniforms/master/packages/uniforms-unstyled/src'; + +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +export const fetchFiles = async () => { + const response = await fetch(GITHUB_URL); + const text = await response.text(); + + const fileLinks = Array.from( + text.matchAll( + /href="\/vazco\/uniforms\/blob\/master\/packages\/uniforms-unstyled\/src\/([^"]+)"/g, + ), + ).map((match) => match[1]); + + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'uniforms-unstyled-')); + + for (const fileLink of fileLinks) { + await delay(100); + const rawFileUrl = `${RAW_GITHUB_URL}/${fileLink}`; + const fileResponse = await fetch(rawFileUrl); + const fileContent = await fileResponse.text(); + const fileName = path.basename(fileLink); + fs.writeFileSync(path.join(tempDir, fileName), fileContent); + } + + return { + tempDir, + }; +}; From d462190127048b578e3671c4b2af34f7aa1d8936 Mon Sep 17 00:00:00 2001 From: Ernest Teluk Date: Tue, 29 Oct 2024 14:36:25 +0100 Subject: [PATCH 2/4] delete jsdom --- package-lock.json | 30 ------------------------------ package.json | 1 - 2 files changed, 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index baa9ff8..4afad4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "uniforms-cli": "index.js" }, "devDependencies": { - "@types/jsdom": "^21.1.7", "@types/prompts": "2.4.2", "commander": "12.1.0", "eslint": "8.57.1", @@ -1098,17 +1097,6 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, - "node_modules/@types/jsdom": { - "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1141,12 +1129,6 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -5243,18 +5225,6 @@ "node": ">=6" } }, - "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "dev": true, - "dependencies": { - "entities": "^4.5.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", diff --git a/package.json b/package.json index ab6e3a8..f9784ce 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "uniforms-cli": "index.js" }, "devDependencies": { - "@types/jsdom": "^21.1.7", "@types/prompts": "2.4.2", "commander": "12.1.0", "eslint": "8.57.1", From 0177b8190fcbf4f0f281dac398c9f7587f26ff42 Mon Sep 17 00:00:00 2001 From: Ernest Teluk Date: Tue, 29 Oct 2024 14:46:02 +0100 Subject: [PATCH 3/4] delete proxu agent --- package-lock.json | 26 -------------------------- package.json | 1 - 2 files changed, 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4afad4d..b4af2af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "eslint-config-airbnb-typescript": "18.0.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-react": "7.37.1", - "https-proxy-agent": "^7.0.5", "kolorist": "1.7.0", "node-fetch": "3.3.2", "prettier": "3.3.3", @@ -1396,18 +1395,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3713,19 +3700,6 @@ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", diff --git a/package.json b/package.json index f9784ce..9fea1fb 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "eslint-config-airbnb-typescript": "18.0.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-react": "7.37.1", - "https-proxy-agent": "^7.0.5", "kolorist": "1.7.0", "node-fetch": "3.3.2", "prettier": "3.3.3", From b581a6b14096aa536361b2368b84b616e1ef7d56 Mon Sep 17 00:00:00 2001 From: Ernest Teluk Date: Tue, 29 Oct 2024 14:54:33 +0100 Subject: [PATCH 4/4] change option copy --- src/commands/createForm/index.ts | 5 ++++- src/commands/createTheme/index.ts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/commands/createForm/index.ts b/src/commands/createForm/index.ts index 85d1cec..e1157d6 100644 --- a/src/commands/createForm/index.ts +++ b/src/commands/createForm/index.ts @@ -57,7 +57,10 @@ const customDirPathPrompt: PromptObject = { export const createForm = new Command() .name('createForm') .description('Creates new uniforms form template') - .option('-s, --skip', 'skip custom dir question, and create in current dir') + .option( + '-s, --skip', + 'skip custom directory question, and create in current directory', + ) .option( '-e, --extension ', `Select extension (${fileTypes.map(({ value }) => value).join(', ')})`, diff --git a/src/commands/createTheme/index.ts b/src/commands/createTheme/index.ts index 7972486..c5410f0 100644 --- a/src/commands/createTheme/index.ts +++ b/src/commands/createTheme/index.ts @@ -42,7 +42,10 @@ export const createTheme = new Command() .name('createTheme') .description('Creates new uniforms theme template') .option('-n, --name ', 'Insert theme name') - .option('-s, --skip', 'skip custom dir question, and create in current dir') + .option( + '-s, --skip', + 'skip custom directory question, and create in current directory', + ) .option( '-e, --extension ', `Select extension (${fileTypes.map(({ value }) => value).join(', ')})`,