diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 0b9a800..42d8e32 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -23,7 +23,7 @@ jobs: cache: 'npm' - name: ๐ฝ Install deps - run: npm install + run: npm ci - name: ๐งช Coverage Tests run: npm run test:coverage diff --git a/.gitignore b/.gitignore index 9c0c0e1..97cc807 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,5 @@ /build /lib /coverage - -/.clingon - lcov.info - .env \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index ecdf3e0..270e3da 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,6 +3,6 @@ "semi": false, "tabWidth": 2, "singleQuote": true, - "printWidth": 100, + "printWidth": 80, "trailingComma": "none" } diff --git a/README.md b/README.md index 9537a96..eb8a605 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@
- + + +
[![Build CI](https://github.com/ipetinate/clingon/actions/workflows/node.js.yml/badge.svg?branch=main)](https://github.com/ipetinate/clingon/actions/workflows/node.js.yml) @@ -27,7 +29,10 @@ Let's simplify all of this, execute a command, answer some questions, or select ## Links -- Official website: [clingon.dev](https://clingon.dev) ++ ๐ Official website ๐ +
+ - Releases - [CHANGELOG](https://github.com/ipetinate/clingon/blob/main/CHANGELOG.md) - Documentation diff --git a/clingon.json b/clingon.json deleted file mode 100644 index 0967ef4..0000000 --- a/clingon.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/package-lock.json b/package-lock.json index 94d9be0..899b81c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -161,26 +161,11 @@ "node": ">=8" } }, - "node_modules/@auto-it/core/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@auto-it/core/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -200,12 +185,6 @@ "node": ">=8" } }, - "node_modules/@auto-it/core/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@auto-it/npm": { "version": "11.1.6", "resolved": "https://registry.npmjs.org/@auto-it/npm/-/npm-11.1.6.tgz", @@ -228,26 +207,11 @@ "user-home": "^2.0.0" } }, - "node_modules/@auto-it/npm/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@auto-it/npm/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -255,12 +219,6 @@ "node": ">=10" } }, - "node_modules/@auto-it/npm/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@auto-it/package-json-utils": { "version": "11.1.6", "resolved": "https://registry.npmjs.org/@auto-it/package-json-utils/-/package-json-utils-11.1.6.tgz", @@ -301,26 +259,11 @@ "tslib": "1.10.0" } }, - "node_modules/@auto-it/version-file/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@auto-it/version-file/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -334,12 +277,6 @@ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, - "node_modules/@auto-it/version-file/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@babel/code-frame": { "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", @@ -711,11 +648,11 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.3.2.tgz", - "integrity": "sha512-lUXKA/5PhPBXz6SVDE+EbBmV3Wi3X77SPRet6Mc1pn6fSXAIivvu1OWpHDpVUxc+RiFflbrDjXUgLfCQeofrWg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.3.3.tgz", + "integrity": "sha512-R64X8RVjVrMLg9wmCB5WTy8R97a/zAYrPdjY1tOybadg4zwx7mk+0Fy69H1pT0x4PRdcMO/CyPmDI0gLooakmw==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "ansi-escapes": "^4.3.2", @@ -726,14 +663,14 @@ } }, "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -813,11 +750,11 @@ } }, "node_modules/@inquirer/confirm": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.6.tgz", - "integrity": "sha512-Mj4TU29g6Uy+37UtpA8UpEOI2icBfpCwSW1QDtfx60wRhUy90s/kHPif2OXSSvuwDQT1lhAYRWUfkNf9Tecxvg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.7.tgz", + "integrity": "sha512-BZjjj19W8gnh5UGFTdP5ZxpgMNRjy03Dzq3k28sB2MDlEUFrcyTkMEoGgvBmGpUw0vNBoCJkTcbHZ3e9tb+d+w==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1" }, "engines": { @@ -825,14 +762,14 @@ } }, "node_modules/@inquirer/confirm/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -999,11 +936,11 @@ } }, "node_modules/@inquirer/editor": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.6.tgz", - "integrity": "sha512-CWmp6XhfQye6xwH6/XV1HGvY95rUfzw7EXyNDHzj5s5Qr1t/X3t6c7uRkfK7OD91y+sbSy7aL6MJv2bbNrMoew==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.7.tgz", + "integrity": "sha512-CGZk//rg57zgXqMp8q8tE2HCc5/rwCC0IwIEtZeb1BF/GJIFlijp4wvN9PeXHsEQ+ul2qRz/0dEk1JqmZzbSbA==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1", "external-editor": "^3.1.0" }, @@ -1012,14 +949,14 @@ } }, "node_modules/@inquirer/editor/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -1099,11 +1036,11 @@ } }, "node_modules/@inquirer/expand": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.6.tgz", - "integrity": "sha512-mFW/vU6mSut0UjmvxPdLC81Sz+5b4t7sMZeF7RlHki1PJkZVZIQoT91MCvoJJN2S7lDqSAV/TxeYqF41RNkY2g==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.7.tgz", + "integrity": "sha512-zwdd5Zur3kdlpthXwk3O4kH5/bXAdZA/Qfl9v7MFf2Un68Cq8XLATp/gH3iMkHcQtyyBemPFgzD9pHNq0piToQ==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1", "chalk": "^4.1.2" }, @@ -1112,14 +1049,14 @@ } }, "node_modules/@inquirer/expand/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -1207,11 +1144,11 @@ } }, "node_modules/@inquirer/input": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.1.6.tgz", - "integrity": "sha512-M8bUFOlcn/kQcVYskl4kkB6dYrHtymJJ1S4nSg/khXT3W3l71u2qhSzfo6PdBG3jUe6ILJZ0gUh4Kef2uJ5pxw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.1.7.tgz", + "integrity": "sha512-eRdwlHJI4bpYsi4icIthsz1rZGIrlfufzRZdCf2i1qfQZ8d3vLTWcILIWV7cnjD4v/nrZ81RthRaQog/uxlcGA==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1" }, "engines": { @@ -1219,14 +1156,14 @@ } }, "node_modules/@inquirer/input/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -1306,11 +1243,11 @@ } }, "node_modules/@inquirer/password": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.6.tgz", - "integrity": "sha512-fkiTIijBRxotoMw0/ljA2BaSsz6PlGoiav9QyAjBXCZoyFsYoItstDKvJXbWwS9NrN42fXYvXn1ljBpldnJaeA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.7.tgz", + "integrity": "sha512-RshkS0CRJYJO4Yxbl6MqkC3OQlU4Dmv4mNxxvoYYfRcPtC/UBLYcddm+lIDHi3zegkto9kmSNYXTCQKYNxinvg==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1", "ansi-escapes": "^4.3.2" }, @@ -1319,14 +1256,14 @@ } }, "node_modules/@inquirer/password/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -1425,11 +1362,11 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.6.tgz", - "integrity": "sha512-xnGBfjatdUqyBMqHi1kHHBh4ggQGZz42vYH0kFdQDnOtx4Ouo7baqVZhBRuQfZTL8tAXuOYI9X6r6BXBl8cnqw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.7.tgz", + "integrity": "sha512-r4tsdYWsYanwEl7MBqmf8GaZTbUAh51C3tMwozOYrAl2wT9YEQVSMDlkcMToFsisRCSq6mQ6zppv92masx4WRQ==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/type": "^1.3.1", "chalk": "^4.1.2" }, @@ -1438,14 +1375,14 @@ } }, "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -1525,11 +1462,11 @@ } }, "node_modules/@inquirer/select": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.2.tgz", - "integrity": "sha512-VzLHVpaobBpI3o/CWSG2sCDqrjHZEYAfT1bowbR8Q72fEi0WfBO3Fnh595QqBit9kQhI1uJbVHaaovg1I7eE7Q==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.3.3.tgz", + "integrity": "sha512-0ptHMogTnyTNKIJVEfCl4fFDQSzIR2/SjgBoD1MLXDszP3UbkYroZ9ii3e6x7dMCWrPGkGWZPyxpy3Rs55vWLw==", "dependencies": { - "@inquirer/core": "^8.1.0", + "@inquirer/core": "^8.2.0", "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "ansi-escapes": "^4.3.2", @@ -1540,14 +1477,14 @@ } }, "node_modules/@inquirer/select/node_modules/@inquirer/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", - "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.0.tgz", + "integrity": "sha512-pexNF9j2orvMMTgoQ/uKOw8V6/R7x/sIDwRwXRhl4i0pPSh6paRzFehpFKpfMbqix1/+gzCekhYTmVbQpWkVjQ==", "dependencies": { "@inquirer/figures": "^1.0.1", "@inquirer/type": "^1.3.1", "@types/mute-stream": "^0.0.4", - "@types/node": "^20.12.7", + "@types/node": "^20.12.11", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", @@ -2266,9 +2203,9 @@ } }, "node_modules/@types/node": { - "version": "20.12.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", - "integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dependencies": { "undici-types": "~5.26.4" } @@ -2599,9 +2536,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001615", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001615.tgz", - "integrity": "sha512-1IpazM5G3r38meiae0bHRnPhz+CBQ3ZLqbQMtrg+AsTPKAXgW38JNsXkyZ+v8waCsDmPq87lmfun5Q2AGysNEQ==", + "version": "1.0.30001620", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", + "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", "dev": true, "funding": [ { @@ -2895,9 +2832,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.756", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.756.tgz", - "integrity": "sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw==", + "version": "1.4.774", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.774.tgz", + "integrity": "sha512-132O1XCd7zcTkzS3FgkAzKmnBuNJjK8WjcTtNuoylj7MYbqw5eXehjQ5OK91g0zm7OTKIPeaAG4CPoRfD9M1Mg==", "dev": true, "peer": true }, @@ -3087,18 +3024,6 @@ "node": ">=4.0.0" } }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fp-ts": { "version": "2.16.5", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.5.tgz", @@ -3582,19 +3507,6 @@ "node": ">=4" } }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -3891,39 +3803,6 @@ "node": ">=0.10.0" } }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3987,15 +3866,6 @@ "node": ">=6" } }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -4030,9 +3900,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -4069,6 +3939,73 @@ "node": ">=4" } }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", @@ -4795,9 +4732,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", - "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -4816,7 +4753,7 @@ "peer": true, "dependencies": { "escalade": "^3.1.2", - "picocolors": "^1.0.0" + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/src/actions/guided.js b/src/actions/guided.js index 46699ef..a164295 100644 --- a/src/actions/guided.js +++ b/src/actions/guided.js @@ -26,7 +26,7 @@ export async function guidedAction(resourceName) { /** * Selected preset * - * @type {string } + * @type { string | boolean } */ let preset = false @@ -71,14 +71,14 @@ export async function guidedAction(resourceName) { message: 'Do you want to save the answers as a preset to use later?' }) - /** - * Save answers as new preset - * - * @type {boolean} - */ - const presetName = await presetNamePrompt() - if (savePreset) { + /** + * Save answers as new preset + * + * @type {boolean} + */ + const presetName = await presetNamePrompt() + const { success, path } = saveAnswersAsPreset(presetName, answers) if (success) { diff --git a/src/actions/init.js b/src/actions/init.js new file mode 100644 index 0000000..7bd3bd2 --- /dev/null +++ b/src/actions/init.js @@ -0,0 +1,22 @@ +import { compose } from '../utils/compose.js' +import { + checkIfPresetFolderAlreadyExists, + createFileIfNotExists, + createPresetFolderIfNotExists, + getConfigContent, + getConfigFilePath +} from '../utils/init-action.js' + +export async function initAction() { + /* + * Global Config + */ + + compose(getConfigFilePath, createFileIfNotExists, getConfigContent) + + /* + * Preset Folder + */ + + compose(checkIfPresetFolderAlreadyExists, createPresetFolderIfNotExists) +} diff --git a/src/constants/config.js b/src/constants/config.js new file mode 100644 index 0000000..6c0056f --- /dev/null +++ b/src/constants/config.js @@ -0,0 +1,18 @@ +export const defaultConfig = { + /** + * Alias for text ocurrences replacement + * + * ๐จ Be careful, do not replace "resourcePath" or "ResourceName", to avoid generating strange behavior in the templates, + * causing auto-completion to be unconfigured + */ + alias: { + /** + * Will replace all `src` occurrences on templates to `@`, Example: `src/components/...` become `@/components/...` + */ + src: '@' + }, + /** + * If `true` will default export functions, components, pages, etc. Example: + */ + exportDefault: false +} diff --git a/src/flows/coldStart.js b/src/flows/coldStart.js new file mode 100644 index 0000000..e3c7bec --- /dev/null +++ b/src/flows/coldStart.js @@ -0,0 +1,25 @@ +import { join } from 'node:path' +import { readFileContent } from '../utils/file.js' +import { getConfigContent } from '../utils/init-action.js' + +export async function coldStart() { + const configPath = join(process.cwd(), 'clingon.config.json') + + /** + * App data + */ + const data = { + /** + * @type {import('../types').GlobalConfig | undefined} + */ + globalConfig: undefined + } + + try { + data.globalConfig = getConfigContent(configPath) + } catch (error) { + console.error(error) + } + + return data +} diff --git a/src/generators/components.js b/src/generators/components.js index be92458..f1bee67 100644 --- a/src/generators/components.js +++ b/src/generators/components.js @@ -2,7 +2,8 @@ import path, { join } from 'node:path' import { CssFrameworkEnum, FrameworkEnum } from '../enums/frameworks.js' -import { localDirname } from '../main.js' +import { globalConfig, localDirname } from '../main.js' + import { frameworkTemplates } from '../constants/templates.js' import { compose } from '../utils/compose.js' @@ -16,6 +17,10 @@ import { checkDirectoriesTree, createDir } from '../utils/directory.js' * @typedef {Record<2 | 3, "options" | "setup">} VueApi - Vue API variant options or setup (composition) */ +/* + * Data Variables + */ + /** * Component generator * @@ -32,8 +37,7 @@ export function generateComponent(answers) { ) if (success) { - console.info('\n') - console.info('Component created successfully: ' + path) + console.info('\nComponent created successfully: ' + path) } else { console.error('Error on create component, try again') } @@ -77,12 +81,18 @@ export function defineComponentTemplate(data) { switch (data.framework) { case FrameworkEnum.react: { - templatePath = frameworkTemplates.react[variant].component.functional[data.cssFramework] + templatePath = + frameworkTemplates.react[variant].component.functional[ + data.cssFramework + ] break } case FrameworkEnum.vue: { - templatePath = frameworkTemplates.vue[vueVersion][variant].component[api][data.cssFramework] + templatePath = + frameworkTemplates.vue[vueVersion][variant].component[api][ + data.cssFramework + ] break } @@ -133,7 +143,9 @@ export function makeFolderWrapperOrBypass(data) { data.name = convertCase('PascalCase', data.name) const folderWrapperPath = join(data.resourcePath, data.name) - const folderWrapperExists = checkDirectoriesTree(splitPathString(folderWrapperPath)) + const folderWrapperExists = checkDirectoriesTree( + splitPathString(folderWrapperPath) + ) if (data.folderWrapper && !folderWrapperExists) { const created = createDir(folderWrapperPath) @@ -197,6 +209,17 @@ export function makePathWithExtension(data) { export function replaceAllComponentTextOccurrences(data) { switch (data.framework) { case FrameworkEnum.react: { + if (!data.folderWrapper) { + if (globalConfig?.exportDefault) { + console.log({ globalConfig }) + + data.fileContent = data.fileContent.replace( + /export function/g, + 'export default function' + ) + } + } + data.fileContent = data.fileContent.replace(/ResourceName/g, data.name) return data @@ -239,9 +262,20 @@ export function generateComponentFile(data) { const success = createFileWithContent(data.pathWithFileName, data.fileContent) if (data.folderWrapper) { - const filePath = join(data.resourcePath, data.name, 'index.' + data.extension) - - createFileWithContent(filePath, `export * from './${data.name}'`) + const filePath = join( + data.resourcePath, + data.name, + 'index.' + data.extension + ) + + if (globalConfig?.exportDefault) { + createFileWithContent( + filePath, + `import { ${data.name} } from './${data.name}'\n\nexport * from './${data.name}'\nexport default ${data.name}\n` + ) + } else { + createFileWithContent(filePath, `export * from './${data.name}'`) + } } return { success, path } diff --git a/src/generators/functions.js b/src/generators/functions.js index e6c735f..aa1d706 100644 --- a/src/generators/functions.js +++ b/src/generators/functions.js @@ -1,6 +1,6 @@ import path from 'node:path' -import { localDirname } from '../main.js' +import { globalConfig, localDirname } from '../main.js' import { functionTemplates } from '../constants/templates.js' import { compose } from '../utils/compose.js' @@ -83,6 +83,15 @@ export function getTemplateContent(data) { * @returns {() => data} */ export function replaceAllFunctionTextOccurrences(data) { + if (!data.folderWrapper) { + if (globalConfig?.exportDefault) { + data.fileContent = data.fileContent.replace( + /export function/g, + 'export default function' + ) + } + } + data.name = convertCase('camelCase', data.name) data.fileContent = data.fileContent.replace('FunctionName', data.name) diff --git a/src/generators/storybook-story.js b/src/generators/storybook-story.js index cc66464..0951c0a 100644 --- a/src/generators/storybook-story.js +++ b/src/generators/storybook-story.js @@ -2,12 +2,15 @@ import path from 'node:path' import { FrameworkEnum } from '../enums/frameworks.js' -import { localDirname } from '../main.js' +import { globalConfig, localDirname } from '../main.js' import { storiesTemplates } from '../constants/templates.js' import { compose } from '../utils/compose.js' import { convertCase } from '../utils/string.js' -import { getFileExtension, removePostfixAndExt } from '../utils/file-extension.js' +import { + getFileExtension, + removePostfixAndExt +} from '../utils/file-extension.js' import { createFileWithContent, readFileContent } from '../utils/file.js' /** @@ -157,6 +160,15 @@ export function makePathWithExtension(data) { * }} */ export function replaceAllTestTextOccurrences(data) { + if (globalConfig?.exportDefault) { + const regex = new RegExp(`import { ResourceName } from`) + + data.fileContent = data.fileContent.replace( + regex, + `import ResourceName from` + ) + } + data.fileContent = data.fileContent.replace(/ResourceName/g, data.name) if (data.framework === FrameworkEnum.vue) { @@ -171,6 +183,10 @@ export function replaceAllTestTextOccurrences(data) { data.fileContent = data.fileContent.replace(/resourcePath/g, resourcePath) } + if (globalConfig?.alias?.src) { + data.fileContent = data.fileContent.replace(/src/g, globalConfig.alias.src) + } + return data } diff --git a/src/generators/tests.js b/src/generators/tests.js index e2de7e5..6176004 100644 --- a/src/generators/tests.js +++ b/src/generators/tests.js @@ -2,11 +2,14 @@ import path from 'node:path' import { FrameworkEnum } from '../enums/frameworks.js' -import { localDirname } from '../main.js' +import { globalConfig, localDirname } from '../main.js' import { unitTestTemplates } from '../constants/templates.js' import { compose } from '../utils/compose.js' -import { getFileExtension, removePostfixAndExt } from '../utils/file-extension.js' +import { + getFileExtension, + removePostfixAndExt +} from '../utils/file-extension.js' import { capitalizeLetter, convertCase } from '../utils/string.js' import { createFileWithContent, readFileContent } from '../utils/file.js' @@ -29,7 +32,9 @@ export function generateTests(answers) { ) if (success) { - console.info(capitalizeLetter(answers.testPostfix) + ' created successfully: ' + path) + console.info( + capitalizeLetter(answers.testPostfix) + ' created successfully: ' + path + ) } else { console.error(`Error on create ${answers.testPostfix}, try again`) } @@ -70,7 +75,8 @@ export function defineTestTemplate(data) { if (data.testFramework === 'vitest') { if (data.withTestingLibrary) { - templatePath = unitTestTemplates.react[variant].vitestTestingLibrary + templatePath = + unitTestTemplates.react[variant].vitestTestingLibrary } else { templatePath = unitTestTemplates.react[variant].vitest } @@ -197,6 +203,15 @@ export function makePathWithExtension(data) { * }} */ export function replaceAllTestTextOccurrences(data) { + if (globalConfig?.exportDefault) { + const regex = new RegExp(`import { ResourceName } from`) + + data.fileContent = data.fileContent.replace( + regex, + `import ResourceName from` + ) + } + if (['function'].includes(data.type)) { data.name = convertCase('camelCase', data.name) } @@ -231,6 +246,10 @@ export function replaceAllTestTextOccurrences(data) { } } + if (globalConfig?.alias?.src) { + data.fileContent = data.fileContent.replace(/src/g, globalConfig.alias.src) + } + return data } diff --git a/src/main.js b/src/main.js index 83be976..c3df857 100755 --- a/src/main.js +++ b/src/main.js @@ -2,17 +2,26 @@ import { Command } from 'commander' +import { coldStart } from './flows/coldStart.js' + +import { initAction } from './actions/init.js' import { guidedAction } from './actions/guided.js' import { createAction } from './actions/create.js' -import { getLocalLibDirname } from './utils/directory.js' import { TestFrameworkEnum } from './enums/frameworks.js' +import { getLocalLibDirname } from './utils/directory.js' /* * Global Variables */ -export const localDirname = getLocalLibDirname() +const localDirname = getLocalLibDirname() + +/* + * Start app + */ + +const { globalConfig } = await coldStart() /* * Resources @@ -27,7 +36,7 @@ const program = new Command() program .name('clingon') .description('CLI to generate files based on templates') - .version('0.9.4', '-v, --version', 'Current version') + .version('0.9.5', '-v, --version', 'Current version') /* * Guided flow - generate components based on prompt answers @@ -37,7 +46,9 @@ program .command('gen') .argument('[name]', 'Resource name') .action(guidedAction) - .description('Start a guided flow to generate resources (components, functions, pages, etc)') + .description( + 'Start a guided flow to generate resources (components, functions, pages, etc)' + ) /* * Preset flow - create instantly resources with presets @@ -46,39 +57,53 @@ program program .command('create') .argument('