From d0bcf800cebf26abd98ec1c81a33137aa061b3bd Mon Sep 17 00:00:00 2001 From: coldbreu Date: Sat, 10 Aug 2024 00:52:33 +0000 Subject: [PATCH] chore(template): merge template changes :up: Signed-off-by: coldbreu --- CITATION.cff | 14 +-- CONTRIBUTING.md | 26 +++++- README.md | 166 +++++++++++++++++------------------ assets/logo.png | Bin 0 -> 28409 bytes assets/transparent-logo.svg | 1 + dist/io-util.js | 2 +- dist/parser.js | 16 ++++ dist/resolver.js | 35 ++++++++ dist/setup.js | 36 +++++--- dist/term.js | 10 +++ package-lock.json | 14 +-- src/io-util.ts | 2 +- src/parser.ts | 20 +++++ src/resolver.ts | 37 ++++++++ src/setup.ts | 75 +++++++++++----- src/term.ts | 13 +++ src/types.ts | 13 +++ template/CONTRIBUTING.md | 27 +++++- template/README.md | 167 ++++++++++++++---------------------- tests/io-util.test.ts | 4 +- 20 files changed, 434 insertions(+), 244 deletions(-) create mode 100644 assets/logo.png create mode 100644 assets/transparent-logo.svg create mode 100644 dist/parser.js create mode 100644 dist/resolver.js create mode 100644 dist/term.js create mode 100644 src/parser.ts create mode 100644 src/resolver.ts create mode 100644 src/term.ts diff --git a/CITATION.cff b/CITATION.cff index 6ec27b4e..9f2b12e2 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -6,17 +6,21 @@ authors: orcid: https://orcid.org/0009-0001-1641-9397 identifiers: - type: url - value: https://github.com/caffeine-addictt/template/releases/tag/v1.12.3 - description: The GitHub release URL of tag v1.12.3. + value: https://github.com/caffeine-addictt/template/releases/tag/v1.14.0 + description: The GitHub release URL of tag v1.14.0. cff-version: 1.2.0 -date-released: 2024-05-12 +date-released: 2024-08-09 keywords: - template - - bash + - node + - nodejs + - setup + - script + - typescript - github license: MIT message: If you use this software, please cite it using these metadata. repository-code: https://github.com/caffeine-addictt/template title: template type: software -version: 1.12.3 +version: 1.14.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01832652..0650df9e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,10 +12,11 @@ please follow it in all your interactions with the project. -1. [Pull Request Process](#pull-request-process) -2. [Issue Report Process](#issue-report-process) -3. [Commit Message Guidelines](#commit-message-guidelines) -4. [Code Quality](#code-quality) +1. [Getting started](#getting-started) +2. [Pull Request Process](#pull-request-process) +3. [Issue Report Process](#issue-report-process) +4. [Commit Message Guidelines](#commit-message-guidelines) +5. [Code Quality](#code-quality) - [Testing](#testing) - [Linting](#linting) - [Building](#building) @@ -23,6 +24,23 @@ please follow it in all your interactions with the project. +## Getting started + +Contributions are what make the open source community +such an amazing place to learn, inspire, and create. +Any contributions you make are **greatly appreciated**. ( ˶ˆᗜˆ˵ ) + +If you have a suggestion that would make this better, +please fork the repo and create a pull request. +You can also simply open an issue with the tag "enhancement". +Don't forget to give the project a star! Thanks again! + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the Branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + ## Pull Request Process 1. Ensure any install or build dependencies are removed before the end of the layer diff --git a/README.md b/README.md index 251918ff..d8cbf35b 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,75 @@ - - +###### _
// made with <3
_ - - +
- + - -
+ + + -[![Forks][forks-shield]][forks-url] -[![Stargazers][stars-shield]][stars-url] -[![MIT License][license-shield]][license-url] +
-
+ - -
-
-

Repository Template

- -

- Simple repository template to get started with GitHub. -
-
- Report Bug - · - Request Feature -

-
+![badge-workflow] +[![badge-license]][license] +![badge-language] +[![badge-pr]][prs] +[![badge-issues]][issues] - +

-## About The Project + A simple repository template to get started with GitHub. - -Starting a new project? Say goodbye to repetitive setup tasks and configuration headaches! Simplify your workflow, save time, and ensure consistency across projects. -Let's make starting new projects feel like a _breeze_ again. +Let's make starting new projects feel like a **_breeze_** again. + +

+ +--- -

(back to top)

+ -## Getting Started +**[
 Features 
](#features)** +**[
 Quick Start 
](#quick-start)** +**[
 Contribute 
][contribute]** + +--- + +
+ +
+ +# Features + +- Beautiful README +- Matrix testing CI +- Draft Releasing CI +- Pull Request Labeler CI +- Code of Conduct +- Code Style Documentation +- Security Policy Documentation +- 7 Issue Templates +- Pull Request Template +- And more... + +
+
+
 🡅 
+
+ +# Quick Start ### 1. Creating a repository Click the green "Use this template" button in the top right corner of the page or the button below to create your new repository. -[![Use Template][use-shield]][use-url] +[![Use Template][badge-use]][use-url] ### 2. Run the setup script @@ -85,67 +103,45 @@ Just a few more steps and you're ready to go! Want to support this project? **✨ Star it on GitHub** and help us spread the word! -

(back to top)

- - - -## Contributing - -Contributions are what make the open source community -such an amazing place to learn, inspire, and create. -Any contributions you make are **greatly appreciated**. ( ˶ˆᗜˆ˵ ) - -If you have a suggestion that would make this better, -please fork the repo and create a pull request. -You can also simply open an issue with the tag "enhancement". -Don't forget to give the project a star! Thanks again! - -1. Fork the Project -2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) -3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) -4. Push to the Branch (`git push origin feature/AmazingFeature`) -5. Open a Pull Request - -Read our [contributing guide](./CONTRIBUTING.md) for more information. - -

(back to top)

- - - -## License +
+
+
 🡅 
+
-Distributed under the MIT License. See [LICENSE.txt](./LICENSE.txt) for more information. +## Special Thanks -

(back to top)

+- **[Img Shields][img-shields]** - _For the awesome README badges_ +- **[Hyprland][hyprland]** - _For showing how to make beautiful READMEs_ +- **[Hyprdots][hyprdots]** - _For showing how to make beautiful READMEs_ - +--- -## Contact +![stars-graph] -Alex - [contact@ngjx.org](mailto:contact@ngjx.org) + + -

(back to top)

+[stars-graph]: https://starchart.cc/caffeine-addictt/template.svg?variant=adaptive +[prs]: https://github.com/caffeine-addictt/template/pulls +[issues]: https://github.com/caffeine-addictt/template/issues +[license]: https://github.com/caffeine-addictt/template/blob/main/LICENSE - + -## Acknowledgments +[use-url]: https://github.com/new?template_name=template&template_owner=caffeine-addictt +[contribute]: https://github.com/caffeine-addictt/template/blob/main/CONTRIBUTING.md -- [Choose an Open Source License](https://choosealicense.com) -- [GitHub Emoji Cheat Sheet](https://www.webpagefx.com/tools/emoji-cheat-sheet) -- [Malven's Flexbox Cheatsheet](https://flexbox.malven.co/) -- [Malven's Grid Cheatsheet](https://grid.malven.co/) -- [Img Shields](https://shields.io) + -

(back to top)

+[hyprland]: https://github.com/hyprwm/Hyprland +[hyprdots]: https://github.com/prasanthrangan/hyprdots +[img-shields]: https://shields.io - - + -[forks-shield]: https://img.shields.io/github/forks/caffeine-addictt/template.svg?style=for-the-badge -[forks-url]: https://github.com/caffeine-addictt/template/network/members -[stars-shield]: https://img.shields.io/github/stars/caffeine-addictt/template.svg?style=for-the-badge&color=yellow -[stars-url]: https://github.com/caffeine-addictt/template/stargazers -[license-shield]: https://img.shields.io/github/license/caffeine-addictt/template.svg?style=for-the-badge -[license-url]: https://github.com/caffeine-addictt/template/blob/master/LICENSE.txt -[use-shield]: https://img.shields.io/badge/Use%20template-FFFFFF?style=for-the-badge -[use-url]: https://github.com/new?template_name=template&template_owner=caffeine-addictt +[badge-workflow]: https://github.com/caffeine-addictt/template/actions/workflows/test-worker.yml/badge.svg +[badge-issues]: https://img.shields.io/github/issues/caffeine-addictt/template +[badge-pr]: https://img.shields.io/github/issues-pr/caffeine-addictt/template +[badge-language]: https://img.shields.io/github/languages/top/caffeine-addictt/template +[badge-license]: https://img.shields.io/github/license/caffeine-addictt/template +[badge-use]: https://img.shields.io/badge/Use%20template-FFFFFF?style=for-the-badge diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e91940ad5cf9269d22e5f16e1fa891a2a66ef1 GIT binary patch literal 28409 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 \ No newline at end of file diff --git a/dist/io-util.js b/dist/io-util.js index e049a53d..0e3b6af0 100644 --- a/dist/io-util.js +++ b/dist/io-util.js @@ -25,7 +25,7 @@ const replaceInFile = (filePath, _tempDir, data) => new Promise((resolve) => { // Revert to legacy let fileContent = fs_1.default.readFileSync(filePath, 'utf8'); fileContent = fileContent - .replace(/{{REPOSITORY}}/g, data.repository) + .replace(/{{REPOSITORY}}/g, `${data.username}/${data.repository}`) .replace(/{{PROJECT_NAME}}/g, data.proj_name) .replace(/{{PROJECT_SHORT_DESCRIPTION}}/g, data.proj_short_desc) .replace(/{{PROJECT_LONG_DESCRIPTION}}/g, data.proj_long_desc) diff --git a/dist/parser.js b/dist/parser.js new file mode 100644 index 00000000..3d7e7d8e --- /dev/null +++ b/dist/parser.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.extractRepoInfo = void 0; +/** Extract username/org and repo from url */ +const extractRepoInfo = (url) => { + const originUrl = url.trim(); + const match = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/.exec(originUrl); + if (!match || !match[1] || !match[2]) + throw new AggregateError(`Could not extract user and repo from git remote: ${originUrl}`); + return { + url: originUrl, + org: match[1], + repo: match[2], + }; +}; +exports.extractRepoInfo = extractRepoInfo; diff --git a/dist/resolver.js b/dist/resolver.js new file mode 100644 index 00000000..80db13b4 --- /dev/null +++ b/dist/resolver.js @@ -0,0 +1,35 @@ +"use strict"; +/** + * This file will hold the configuration options to make the setup script not so annoying + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resolveUserInfo = exports.resolveRepoInfo = void 0; +const parser_1 = require("./parser"); +const term_1 = require("./term"); +const resolveRepoInfo = () => (0, term_1.execute)('git', ['remote', 'get-url', 'origin']) + .then((_originUrl) => (0, parser_1.extractRepoInfo)(_originUrl.toString())) + .catch(() => ({})); +exports.resolveRepoInfo = resolveRepoInfo; +const resolveUserInfo = async () => { + const promises = await Promise.all([ + (0, term_1.execute)('git', ['config', '--global', 'user.name']) + .then((r) => r.toString().trim()) + .catch(() => undefined), + (0, term_1.execute)('git', ['config', '--global', 'user.email']) + .then((r) => r.toString().trim()) + .catch(() => undefined), + ]); + return { + name: promises[0], + email: promises[1], + }; +}; +exports.resolveUserInfo = resolveUserInfo; +const resolveGitInfo = async () => { + const promises = await Promise.all([(0, exports.resolveRepoInfo)(), (0, exports.resolveUserInfo)()]); + return { + ...promises[0], + ...promises[1], + }; +}; +exports.default = resolveGitInfo; diff --git a/dist/setup.js b/dist/setup.js index 045aba85..17f11fe1 100644 --- a/dist/setup.js +++ b/dist/setup.js @@ -7,6 +7,7 @@ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const readline_1 = __importDefault(require("readline")); const io_util_1 = require("./io-util"); +const resolver_1 = __importDefault(require("./resolver")); /** * For interacting with stdin/stdout */ @@ -28,15 +29,25 @@ const question = (query, validator = [], trimWhitespace = true) => new Promise(( })); /** Ask for project information */ const fetchInfo = async (cleanup) => { - const name = await question('Name? (This will go on the LICENSE)\n=> '); - const email = await question('Email?\n=> ', [ + const resolved = await (0, resolver_1.default)(); + // Ask user + const name = await question(`Name? (This will go on the LICENSE)${resolved.name ? ` [Resolved: ${resolved.name}]` : ''}\n=> `) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.name ?? '')); + const email = await question(`Email?${resolved.email ? ` [Resolved: ${resolved.email}]` : ''}\n=> `, [ { - validate: (s) => /.+@.+\..+/.test(s), + validate: (s) => !!resolved.email || /.+@.+\..+/.test(s), onError: () => console.log('Invalid email!'), }, - ]); - const username = await question('Username? (https://github.com/)\n=> '); - const repository = await question('Repository? ((https://github.com/$username/\n=> '); + ]) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.email ?? '')); + const username = await question(`Username? (https://github.com/)${resolved.org ? ` [Resolved: ${resolved.org}]` : ''}\n=> `) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.org ?? '')); + const repository = await question(`Repository? (https://github.com/${username}/)${resolved.repo ? ` [Resolved: ${resolved.repo}]` : ''}\n=> `) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.repo ?? '')); const proj_name = await question('Project name?\n=> '); const proj_short_desc = await question('Short description?\n=> '); const proj_long_desc = await question('Long description?\n=> '); @@ -90,14 +101,14 @@ const { func: main } = (0, io_util_1.withTempDir)('caffeine-addictt-template-', recursive: true, }); // Use async - await Promise.all(filesToUpdate.map((filename) => async () => { + await Promise.all(filesToUpdate.map((filename) => (async () => { const filePath = path_1.default.join('./template', filename); const fileInfo = fs_1.default.statSync(filePath); if (fileInfo.isDirectory()) { return; } await (0, io_util_1.replaceInFile)(filePath, tempDir, data); - })); + })())); // Write CODEOWNERS fs_1.default.appendFileSync('./template/.github/CODEOWNERS', `* @${data.username}`); // ########################################## // @@ -122,6 +133,9 @@ const { func: main } = (0, io_util_1.withTempDir)('caffeine-addictt-template-', // ################# // // Stage 3: Clean up // // ################# // + // Only add `force: true` for files or directories that + // will only exist if some development task was carried out + // like eslintcache console.log('Cleaning up...'); // Js fs_1.default.unlinkSync('package.json'); @@ -133,19 +147,21 @@ const { func: main } = (0, io_util_1.withTempDir)('caffeine-addictt-template-', fs_1.default.unlinkSync('babel.config.cjs'); fs_1.default.rmSync('tests', { recursive: true }); // Linting - fs_1.default.unlinkSync('.eslintcache'); fs_1.default.unlinkSync('.eslintignore'); fs_1.default.unlinkSync('.prettierignore'); fs_1.default.unlinkSync('eslint.config.mjs'); + fs_1.default.rmSync('.eslintcache', { force: true }); // Syncing fs_1.default.unlinkSync('.templatesyncignore'); // Git fs_1.default.unlinkSync('.gitignore'); // Node - fs_1.default.rmSync('node_modules', { recursive: true }); + fs_1.default.rmSync('node_modules', { recursive: true, force: true }); // Clean up dist fs_1.default.unlinkSync(__filename); fs_1.default.rmSync('dist', { recursive: true }); + // Assets + fs_1.default.rmSync('assets', { recursive: true }); // Generate src and test fs_1.default.mkdirSync('src'); fs_1.default.mkdirSync('tests'); diff --git a/dist/term.js b/dist/term.js new file mode 100644 index 00000000..29ff8f2a --- /dev/null +++ b/dist/term.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.execute = void 0; +const child_process_1 = require("child_process"); +const execute = (command, args, spawnOptions) => new Promise((resolve, reject) => { + const cmd = (0, child_process_1.spawn)(command, args, spawnOptions); + cmd.stdout.on('data', resolve); + cmd.stderr.on('data', reject); +}); +exports.execute = execute; diff --git a/package-lock.json b/package-lock.json index 2afe8a63..a5b5caaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3255,12 +3255,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4015,9 +4015,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" diff --git a/src/io-util.ts b/src/io-util.ts index da384456..70580dbe 100644 --- a/src/io-util.ts +++ b/src/io-util.ts @@ -42,7 +42,7 @@ export const replaceInFile = ( let fileContent = fs.readFileSync(filePath, 'utf8'); fileContent = fileContent - .replace(/{{REPOSITORY}}/g, data.repository) + .replace(/{{REPOSITORY}}/g, `${data.username}/${data.repository}`) .replace(/{{PROJECT_NAME}}/g, data.proj_name) .replace(/{{PROJECT_SHORT_DESCRIPTION}}/g, data.proj_short_desc) .replace(/{{PROJECT_LONG_DESCRIPTION}}/g, data.proj_long_desc) diff --git a/src/parser.ts b/src/parser.ts new file mode 100644 index 00000000..97ae7e7b --- /dev/null +++ b/src/parser.ts @@ -0,0 +1,20 @@ +import type { RepoInfo } from './types'; + +/** Extract username/org and repo from url */ +export const extractRepoInfo = (url: string): RepoInfo => { + const originUrl = url.trim(); + const match = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/.exec( + originUrl, + ); + + if (!match || !match[1] || !match[2]) + throw new AggregateError( + `Could not extract user and repo from git remote: ${originUrl}`, + ); + + return { + url: originUrl, + org: match[1], + repo: match[2], + } satisfies RepoInfo; +}; diff --git a/src/resolver.ts b/src/resolver.ts new file mode 100644 index 00000000..e99a82b3 --- /dev/null +++ b/src/resolver.ts @@ -0,0 +1,37 @@ +/** + * This file will hold the configuration options to make the setup script not so annoying + */ + +import { extractRepoInfo } from './parser'; +import { execute } from './term'; +import type { GitInfo, RepoInfo, UserInfo } from './types'; + +export const resolveRepoInfo = (): Promise => + execute('git', ['remote', 'get-url', 'origin']) + .then((_originUrl) => extractRepoInfo(_originUrl.toString())) + .catch(() => ({})); + +export const resolveUserInfo = async (): Promise => { + const promises = await Promise.all([ + execute('git', ['config', '--global', 'user.name']) + .then((r) => r.toString().trim()) + .catch(() => undefined), + execute('git', ['config', '--global', 'user.email']) + .then((r) => r.toString().trim()) + .catch(() => undefined), + ]); + + return { + name: promises[0], + email: promises[1], + } satisfies UserInfo; +}; + +const resolveGitInfo = async (): Promise => { + const promises = await Promise.all([resolveRepoInfo(), resolveUserInfo()]); + return { + ...promises[0], + ...promises[1], + } as GitInfo; +}; +export default resolveGitInfo; diff --git a/src/setup.ts b/src/setup.ts index 71050a88..66a54b8f 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -4,6 +4,7 @@ import readline from 'readline'; import type { ProjectInfo } from './types'; import { replaceInFile, withTempDir } from './io-util'; +import resolveGitInfo from './resolver'; /** * For interacting with stdin/stdout @@ -41,19 +42,39 @@ const question = ( const fetchInfo = async ( cleanup: () => void | unknown, ): Promise => { - const name = await question('Name? (This will go on the LICENSE)\n=> '); - const email = await question('Email?\n=> ', [ - { - validate: (s: string) => /.+@.+\..+/.test(s), - onError: () => console.log('Invalid email!'), - }, - ]); + const resolved = await resolveGitInfo(); + + // Ask user + const name = await question( + `Name? (This will go on the LICENSE)${resolved.name ? ` [Resolved: ${resolved.name}]` : ''}\n=> `, + ) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.name ?? '')); + + const email = await question( + `Email?${resolved.email ? ` [Resolved: ${resolved.email}]` : ''}\n=> `, + [ + { + validate: (s: string) => !!resolved.email || /.+@.+\..+/.test(s), + onError: () => console.log('Invalid email!'), + }, + ], + ) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.email ?? '')); + const username = await question( - 'Username? (https://github.com/)\n=> ', - ); + `Username? (https://github.com/)${resolved.org ? ` [Resolved: ${resolved.org}]` : ''}\n=> `, + ) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.org ?? '')); + const repository = await question( - 'Repository? ((https://github.com/$username/\n=> ', - ); + `Repository? (https://github.com/${username}/)${resolved.repo ? ` [Resolved: ${resolved.repo}]` : ''}\n=> `, + ) + .then((val) => val.trim()) + .then((val) => (val.length ? val : resolved.repo ?? '')); + const proj_name = await question('Project name?\n=> '); const proj_short_desc = await question('Short description?\n=> '); const proj_long_desc = await question('Long description?\n=> '); @@ -126,16 +147,18 @@ const { func: main } = withTempDir( // Use async await Promise.all( - filesToUpdate.map((filename) => async () => { - const filePath = path.join('./template', filename); - - const fileInfo = fs.statSync(filePath); - if (fileInfo.isDirectory()) { - return; - } - - await replaceInFile(filePath, tempDir, data); - }), + filesToUpdate.map((filename) => + (async () => { + const filePath = path.join('./template', filename); + + const fileInfo = fs.statSync(filePath); + if (fileInfo.isDirectory()) { + return; + } + + await replaceInFile(filePath, tempDir, data); + })(), + ), ); // Write CODEOWNERS @@ -167,6 +190,9 @@ const { func: main } = withTempDir( // ################# // // Stage 3: Clean up // // ################# // + // Only add `force: true` for files or directories that + // will only exist if some development task was carried out + // like eslintcache console.log('Cleaning up...'); // Js @@ -182,10 +208,10 @@ const { func: main } = withTempDir( fs.rmSync('tests', { recursive: true }); // Linting - fs.unlinkSync('.eslintcache'); fs.unlinkSync('.eslintignore'); fs.unlinkSync('.prettierignore'); fs.unlinkSync('eslint.config.mjs'); + fs.rmSync('.eslintcache', { force: true }); // Syncing fs.unlinkSync('.templatesyncignore'); @@ -194,12 +220,15 @@ const { func: main } = withTempDir( fs.unlinkSync('.gitignore'); // Node - fs.rmSync('node_modules', { recursive: true }); + fs.rmSync('node_modules', { recursive: true, force: true }); // Clean up dist fs.unlinkSync(__filename); fs.rmSync('dist', { recursive: true }); + // Assets + fs.rmSync('assets', { recursive: true }); + // Generate src and test fs.mkdirSync('src'); fs.mkdirSync('tests'); diff --git a/src/term.ts b/src/term.ts new file mode 100644 index 00000000..53478fb1 --- /dev/null +++ b/src/term.ts @@ -0,0 +1,13 @@ +import { SpawnOptionsWithoutStdio, spawn } from 'child_process'; + +export const execute = ( + command: string, + args?: string[], + spawnOptions?: SpawnOptionsWithoutStdio, +): Promise => + new Promise((resolve, reject): void => { + const cmd = spawn(command, args, spawnOptions); + + cmd.stdout.on('data', resolve); + cmd.stderr.on('data', reject); + }); diff --git a/src/types.ts b/src/types.ts index 47037077..51150e4e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,3 +11,16 @@ export interface ProjectInfo { docs_url: string; assignees: string; } + +export interface RepoInfo { + url?: string; + org?: string; + repo?: string; +} + +export interface UserInfo { + name?: string; + email?: string; +} + +export type GitInfo = RepoInfo & UserInfo; diff --git a/template/CONTRIBUTING.md b/template/CONTRIBUTING.md index 4725d3ff..cd8906c1 100644 --- a/template/CONTRIBUTING.md +++ b/template/CONTRIBUTING.md @@ -12,16 +12,35 @@ please follow it in all your interactions with the project. -1. [Pull Request Process](#pull-request-process) -2. [Issue Report Process](#issue-report-process) -3. [Commit Message Guidelines](#commit-message-guidelines) -4. [Code Quality](#code-quality) +1. [Getting started](#getting-started) +2. [Pull Request Process](#pull-request-process) +3. [Issue Report Process](#issue-report-process) +4. [Commit Message Guidelines](#commit-message-guidelines) +5. [Code Quality](#code-quality) - [Testing](#testing) - [Linting](#linting) + - [Building](#building) +## Getting started + +Contributions are what make the open source community +such an amazing place to learn, inspire, and create. +Any contributions you make are **greatly appreciated**. ( ˶ˆᗜˆ˵ ) + +If you have a suggestion that would make this better, +please fork the repo and create a pull request. +You can also simply open an issue with the tag "enhancement". +Don't forget to give the project a star! Thanks again! + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the Branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + ## Pull Request Process 1. Ensure any install or build dependencies are removed before the end of the layer diff --git a/template/README.md b/template/README.md index 76b4c5da..b63af7c7 100644 --- a/template/README.md +++ b/template/README.md @@ -1,140 +1,103 @@ - - +###### _

// made with <3
_ - - - - - - - - - -
- - Logo - - -

{{PROJECT_NAME}}

- -

- {{PROJECT_SHORT_DESCRIPTION}} -
- Explore the docs » -
-
- Report Bug - · - Request Feature -

-
- - - -## About The Project -![Social Card](images/socialcard.png) + -{{PROJECT_LONG_DESCRIPTION}} - -

(back to top)

- - + + + -## Getting Started +
-This is an example of how you can set up your project locally. -To get a local copy up and running follow these simple example steps. + -### Prerequisites +![badge-workflow] +[![badge-license]][license] +![badge-language] +[![badge-pr]][prs] +[![badge-issues]][issues] -- +

-### Installation + -_Below is an example of how you can install and use {{PROJECT_NAME}}._ +{{PROJECT_LONG_DESCRIPTION}} -1. -2. +{{PROJECT_SHORT_DESCRIPTION}} -

(back to top)

+

- +--- -## Documentation + -Our docs are [here]({{DOCS_URL}})! +**[
 Quick Start 
](#quick-start)** +**[
 Documentation 
]({{DOCS_URL}})** +**[
 Thanks 
](#special-thanks)** +**[
 Contribute 
][contribute]** -See the [open issues](https://github.com/{{REPOSITORY}}/issues) -for a full list of proposed features (and known issues). +--- -

(back to top)

+
- + -## Contributing +# Quick Start -Contributions are what make the open source community -such an amazing place to learn, inspire, and create. -Any contributions you make are **greatly appreciated**. ( ˶ˆᗜˆ˵ ) +_This is an example of how you can set up your project locally. +To get a local copy up and running, follow these simple steps._ -If you have a suggestion that would make this better, -please fork the repo and create a pull request. -You can also simply open an issue with the tag "enhancement". -Don't forget to give the project a star! Thanks again! +## Prerequisites -1. Fork the Project -2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) -3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) -4. Push to the Branch (`git push origin feature/AmazingFeature`) -5. Open a Pull Request +- Language 1 -Read our [contributing guide](./CONTRIBUTING.md) for more information. +## Installation -

(back to top)

+_Below is an example of how you can install and use {{PROJECT_NAME}}_ - +1. Step 1 +2. Step 2 -## License + -Distributed under the MIT License. See [LICENSE.txt](./LICENSE.txt) for more information. +## Special Thanks -

(back to top)

+- **[Caffeine-addictt][template-repo]** - _For the repository template_ +- **[Img Shields][img-shields]** - _For the awesome README badges_ +- **[Hyprland][hyprland]** - _For showing how to make beautiful READMEs_ +- **[Hyprdots][hyprdots]** - _For showing how to make beautiful READMEs_ - +--- -## Contact +![stars-graph] -{{NAME}} - [{{EMAIL}}](mailto:{{EMAIL}}) + + -

(back to top)

+[stars-graph]: https://starchart.cc/{{REPOSITORY}}.svg?variant=adaptive +[prs]: https://github.com/{{REPOSITORY}}/pulls +[issues]: https://github.com/{{REPOSITORY}}/issues +[license]: https://github.com/{{REPOSITORY}}/blob/main/LICENSE - + -## Acknowledgments +[contribute]: https://github.com/{{REPOSITORY}}/blob/main/CONTRIBUTING.md -- [Repository Template](https://github.com/caffeine-addictt/template) -- [Choose an Open Source License](https://choosealicense.com) -- [GitHub Emoji Cheat Sheet](https://www.webpagefx.com/tools/emoji-cheat-sheet) -- [Malven's Flexbox Cheatsheet](https://flexbox.malven.co/) -- [Malven's Grid Cheatsheet](https://grid.malven.co/) -- [Img Shields](https://shields.io) + -

(back to top)

+[template-repo]: https://github.com/caffeine-addictt/template +[hyprland]: https://github.com/hyprwm/Hyprland +[hyprdots]: https://github.com/prasanthrangan/hyprdots +[img-shields]: https://shields.io - - + -[forks-shield]: https://img.shields.io/github/forks/{{REPOSITORY}}.svg?style=for-the-badge -[forks-url]: https://github.com/{{REPOSITORY}}/network/members -[stars-shield]: https://img.shields.io/github/stars/{{REPOSITORY}}.svg?style=for-the-badge&color=yellow -[stars-url]: https://github.com/{{REPOSITORY}}/stargazers -[license-shield]: https://img.shields.io/github/license/{{REPOSITORY}}.svg?style=for-the-badge -[license-url]: https://github.com/{{REPOSITORY}}/blob/master/LICENSE.txt +[badge-workflow]: https://github.com/{{REPOSITORY}}/actions/workflows/test-worker.yml/badge.svg +[badge-issues]: https://img.shields.io/github/issues/{{REPOSITORY}} +[badge-pr]: https://img.shields.io/github/issues-pr/{{REPOSITORY}} +[badge-language]: https://img.shields.io/github/languages/top/{{REPOSITORY}} +[badge-license]: https://img.shields.io/github/license/{{REPOSITORY}} diff --git a/tests/io-util.test.ts b/tests/io-util.test.ts index deed0b9e..17462490 100644 --- a/tests/io-util.test.ts +++ b/tests/io-util.test.ts @@ -23,7 +23,7 @@ assignees: ['{{ASSIGNEES}}'] const replaced = ` My name is: John -The repo is https://github.com/username/repo +The repo is johnny/repo HbVYf@example.com https://example.com/docs Project with some description @@ -65,7 +65,7 @@ describe('replace the correct content', () => { name: 'John', email: 'HbVYf@example.com', username: 'johnny', - repository: 'https://github.com/username/repo', + repository: 'repo', proj_name: 'My Project', proj_short_desc: 'Project with some description', proj_long_desc: 'Project with some description that is really long',