mirror of
https://github.com/sern-handler/cli
synced 2026-06-15 04:12:33 +00:00
Compare commits
39 Commits
v0.4.2
...
plugin-ver
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
088c3eb6ac | ||
|
|
68c096e689 | ||
|
|
34bf4d004c | ||
|
|
309bf5224a | ||
|
|
4382ce6d5e | ||
|
|
58fa3253f6 | ||
|
|
1421136181 | ||
|
|
f29c7881fe | ||
|
|
0d37da5689 | ||
|
|
504d36729e | ||
|
|
e391fddf20 | ||
|
|
e5d6de4841 | ||
|
|
fc47847eeb | ||
|
|
731017f637 | ||
|
|
a3f5f1bf52 | ||
|
|
386b30aedd | ||
|
|
f2531a6f9b | ||
| 69287ab1bd | |||
|
|
aa398a871c | ||
|
|
0855abfea3 | ||
|
|
6212fb3588 | ||
|
|
2018c4381e | ||
|
|
5b0214a073 | ||
|
|
6e6ed3136d | ||
|
|
c302e1e4be | ||
|
|
e60fb42e3e | ||
|
|
5e48f27584 | ||
|
|
276b9656b8 | ||
|
|
75dff367f5 | ||
|
|
90429523c3 | ||
|
|
bed31c1f49 | ||
|
|
9271da3076 | ||
|
|
2009d1fdca | ||
|
|
f9aa2c3d20 | ||
|
|
3fa93bd903 | ||
|
|
e7c50c4d32 | ||
|
|
b1190efee3 | ||
|
|
55b1fff28e | ||
|
|
7bcbf55fb5 |
10
.github/workflows/auto-deprecate.yml
vendored
10
.github/workflows/auto-deprecate.yml
vendored
@@ -12,17 +12,21 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Project
|
- name: Checkout Project
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
registry-url: 'https://registry.npmjs.org/'
|
registry-url: 'https://registry.npmjs.org/'
|
||||||
|
|
||||||
- name: Install Node.js dependencies
|
- name: Install Node.js dependencies
|
||||||
run: npm i
|
run: npm i
|
||||||
- name: Deprecate versions
|
- name: Deprecate dev versions
|
||||||
run: npx npm-deprecate --name "*dev*" --package "@sern/cli" --message "This is a deprecated version of @sern/cli@dev. Please use the latest dev version."
|
run: npx npm-deprecate --name "*dev*" --package "@sern/cli" --message "This is a deprecated version of @sern/cli@dev. Please use the latest dev version."
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
- name: Deprecate pr versions
|
||||||
|
run: npx npm-deprecate --name "*pr*" --package "@sern/cli" --message "This is a deprecated version of @sern/cli. Please use the latest version."
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
|
|||||||
6
.github/workflows/continuous-delivery.yml
vendored
6
.github/workflows/continuous-delivery.yml
vendored
@@ -15,16 +15,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- name: Install Node.js dependencies
|
- name: Install Node.js dependencies
|
||||||
run: npm i
|
run: npm i && npm run build
|
||||||
|
|
||||||
- name: Link Project
|
- name: Link Project
|
||||||
run: npm link
|
run: npm link
|
||||||
|
|||||||
10
.github/workflows/continuous-integration.yml
vendored
10
.github/workflows/continuous-integration.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
|
|
||||||
@@ -37,15 +37,15 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
|
|
||||||
- name: Install Node.js dependencies
|
- name: Install Node.js dependencies
|
||||||
run: npm i
|
run: npm i && npm run build
|
||||||
|
|
||||||
- name: Link Project
|
- name: Link Project
|
||||||
run: npm link
|
run: npm link
|
||||||
|
|||||||
15
.github/workflows/publish.yml
vendored
15
.github/workflows/publish.yml
vendored
@@ -2,6 +2,10 @@ name: Publish
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
prNumber:
|
||||||
|
description: The number of the PR that is being deployed
|
||||||
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Publish:
|
Publish:
|
||||||
@@ -10,16 +14,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- name: Install Node.js dependencies
|
- name: Install Node.js dependencies
|
||||||
run: npm i
|
run: npm i && npm run build
|
||||||
|
|
||||||
- name: Link Project
|
- name: Link Project
|
||||||
run: npm link
|
run: npm link
|
||||||
@@ -28,6 +32,9 @@ jobs:
|
|||||||
run: sern
|
run: sern
|
||||||
|
|
||||||
- name: Publish to npm
|
- name: Publish to npm
|
||||||
run: npm publish
|
run: |
|
||||||
|
TAG=$(echo 'pr-${{ github.event.inputs.prNumber }}')
|
||||||
|
npm version premajor --preid "${TAG}.$(git rev-parse --verify --short HEAD)" --git-tag-version=false
|
||||||
|
npm publish --tag ${TAG}
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
8
.github/workflows/release-please.yml
vendored
8
.github/workflows/release-please.yml
vendored
@@ -12,15 +12,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
release-type: node
|
release-type: node
|
||||||
bump-patch-for-minor-pre-major: true
|
bump-patch-for-minor-pre-major: true
|
||||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 17
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
- run: npm i
|
- run: npm i && npm run build
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
- run: npm link
|
- run: npm link
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
@@ -29,4 +29,4 @@ jobs:
|
|||||||
- run: npm publish
|
- run: npm publish
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
.github/
|
.github/
|
||||||
CHANGELOG.md
|
CHANGELOG.md
|
||||||
|
dist/
|
||||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -2,6 +2,24 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [0.5.0](https://github.com/sern-handler/cli/compare/v0.4.2...v0.5.0) (2022-09-16)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* re-write to TypeScript
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add engine for node version & remove manual version check ([#72](https://github.com/sern-handler/cli/issues/72)) ([2009d1f](https://github.com/sern-handler/cli/commit/2009d1fdca9a383d219304fd3cb48a622355b7dc))
|
||||||
|
* adds the esm template option + refactors ([#73](https://github.com/sern-handler/cli/issues/73)) ([9271da3](https://github.com/sern-handler/cli/commit/9271da30764f86225385e8ae6448b99d66687294))
|
||||||
|
* re-write to TypeScript ([bed31c1](https://github.com/sern-handler/cli/commit/bed31c1f4995bbf7d8d0a483f562788172e29919))
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* release 0.5.0 ([2018c43](https://github.com/sern-handler/cli/commit/2018c4381e665b9b0c5e70a203aa0dfd9fdd3cef))
|
||||||
|
|
||||||
## [0.4.2](https://github.com/sern-handler/cli/compare/v0.4.1...v0.4.2) (2022-07-28)
|
## [0.4.2](https://github.com/sern-handler/cli/compare/v0.4.1...v0.4.2) (2022-07-28)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# sern CLI
|
<div align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/sern-handler/.github/main/cli.png" width="900px">
|
||||||
|
</div>
|
||||||
|
|
||||||
Our CLI allows you to setup and manage Discord bot projects without writing a single line of code!
|
# Features
|
||||||
|
|
||||||
😁 **User Friendly** <br>
|
😁 **User Friendly** <br>
|
||||||
💦 **Simple** <br>
|
💦 **Simple** <br>
|
||||||
@@ -14,7 +16,7 @@ npm install -g @sern/cli@latest
|
|||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn add -g @sern/cli@latest
|
yarn global add @sern/cli@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
3058
package-lock.json
generated
3058
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -1,16 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "@sern/cli",
|
"name": "@sern/cli",
|
||||||
"version": "0.4.2",
|
"version": "0.5.0",
|
||||||
"description": "A CLI for @sern/handler",
|
"description": "Official CLI for @sern/handler",
|
||||||
"exports": "./src/index.js",
|
"exports": "./dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sern": "./src/index.js"
|
"sern": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"format": "prettier --check .",
|
"format": "prettier --check .",
|
||||||
"fix": "prettier --write ."
|
"fix": "prettier --write .",
|
||||||
|
"build": "tsup",
|
||||||
|
"watch": "tsc --watch"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -28,7 +30,7 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/sern-handler/cli/issues"
|
"url": "https://github.com/sern-handler/cli/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://sern-handler.js.org",
|
"homepage": "https://sern.dev",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colorette": "^2.0.16",
|
"colorette": "^2.0.16",
|
||||||
"commander": "^9.3.0",
|
"commander": "^9.3.0",
|
||||||
@@ -39,9 +41,15 @@
|
|||||||
"undici": "^5.6.1"
|
"undici": "^5.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@favware/npm-deprecate": "1.0.4",
|
"@favware/npm-deprecate": "1.0.7",
|
||||||
"@types/prompts": "2.0.14",
|
"@types/prompts": "2.4.3",
|
||||||
"prettier": "2.7.1"
|
"esbuild-plugin-version-injector": "^1.0.3",
|
||||||
|
"prettier": "2.8.4",
|
||||||
|
"tsup": "^6.6.3",
|
||||||
|
"typescript": "4.9.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16.10.x"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npmjs.org/",
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import prompts from 'prompts';
|
import prompt from 'prompts';
|
||||||
import { extraPrompt } from '../prompts/extra.js';
|
import { extraPrompt } from '../prompts/extra.js';
|
||||||
import { create } from '../utilities/create.js';
|
import { create } from '../utilities/create.js';
|
||||||
const { prompt } = prompts;
|
|
||||||
|
|
||||||
export async function extra() {
|
export async function extra() {
|
||||||
const extra = await prompt([extraPrompt]);
|
const extra = await prompt([extraPrompt]);
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { cyanBright, green, yellowBright } from 'colorette';
|
|
||||||
|
|
||||||
export function help() {
|
|
||||||
return `
|
|
||||||
___ ___ _ __ _ __
|
|
||||||
/ __|/ _ \\ '__| '_ \\
|
|
||||||
\\__ \\ __/ | | | | |
|
|
||||||
|___/\\___|_| |_| |_|
|
|
||||||
|
|
||||||
Welcome!
|
|
||||||
If you're new to ${cyanBright('sern')}, run ${yellowBright(
|
|
||||||
'sern init'
|
|
||||||
)} for an interactive setup to your new bot project!
|
|
||||||
|
|
||||||
${green(
|
|
||||||
`If you have any ideas, suggestions, bug reports, kindly join our support server: https://discord.gg/xzK5fUKT4r`
|
|
||||||
)}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
16
src/commands/help.ts
Normal file
16
src/commands/help.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { cyanBright, green, magentaBright } from 'colorette';
|
||||||
|
|
||||||
|
export const help = `
|
||||||
|
___ ___ _ __ _ __
|
||||||
|
/ __|/ _ \\ '__| '_ \\
|
||||||
|
\\__ \\ __/ | | | | |
|
||||||
|
|___/\\___|_| |_| |_|
|
||||||
|
|
||||||
|
Welcome!
|
||||||
|
If you're new to ${cyanBright('sern')}, run ${magentaBright(
|
||||||
|
'sern init'
|
||||||
|
)} for an interactive setup to your new bot project!
|
||||||
|
|
||||||
|
${green(
|
||||||
|
`If you have any ideas, suggestions, bug reports, kindly join our support server: https://sern.dev/discord`
|
||||||
|
)}`;
|
||||||
@@ -1,52 +1,32 @@
|
|||||||
import prompts from 'prompts';
|
import { greenBright, redBright, underline } from 'colorette';
|
||||||
import ora from 'ora';
|
|
||||||
import { greenBright, redBright, yellowBright } from 'colorette';
|
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
import { findUp } from 'find-up';
|
import { findUp } from 'find-up';
|
||||||
|
import ora from 'ora';
|
||||||
|
import prompt from 'prompts';
|
||||||
import {
|
import {
|
||||||
cmds_dir,
|
cmds_dir,
|
||||||
|
gitInit,
|
||||||
lang,
|
lang,
|
||||||
main_dir,
|
main_dir,
|
||||||
gitInit,
|
|
||||||
which_manager,
|
|
||||||
skip_install_dep,
|
|
||||||
name,
|
name,
|
||||||
|
skip_install_dep,
|
||||||
|
which_manager,
|
||||||
} from '../prompts/init.js';
|
} from '../prompts/init.js';
|
||||||
|
|
||||||
import { npm } from '../utilities/npm.js';
|
|
||||||
import { cloneRepo, installDeps } from '../utilities/install.js';
|
|
||||||
import { editDirs, editMain } from '../utilities/edits.js';
|
|
||||||
import { writeFile } from 'fs/promises';
|
import { writeFile } from 'fs/promises';
|
||||||
const { prompt } = prompts;
|
import { editDirs, editMain } from '../utilities/edits.js';
|
||||||
|
import { cloneRepo, installDeps } from '../utilities/install.js';
|
||||||
|
import { npm } from '../utilities/npm.js';
|
||||||
|
import type { PackageManagerChoice } from '../utilities/types.js';
|
||||||
|
|
||||||
/**
|
export async function init(flags: Flags) {
|
||||||
* @param {{ y: string; sync: string; }} flags
|
let data: PromptData;
|
||||||
*/
|
let git_init = true; // the default;
|
||||||
export async function init(flags) {
|
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
||||||
// * Check if node version is valid
|
|
||||||
const { version } = process;
|
|
||||||
const [major, minor] = version.split('.');
|
|
||||||
const majorNum = parseInt(major.slice(1));
|
|
||||||
const minorNum = parseInt(minor);
|
|
||||||
|
|
||||||
if (majorNum < 16 || (majorNum === 16 && minorNum < 10)) {
|
|
||||||
console.log(
|
|
||||||
yellowBright(
|
|
||||||
`\nYou are using Node ${version}\nPlease upgrade to Node 16.10.x or higher!\n`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data;
|
|
||||||
let git_init;
|
|
||||||
let pm;
|
|
||||||
|
|
||||||
if (flags.y) {
|
if (flags.y) {
|
||||||
const projectName = await prompt([name]);
|
const projectName = await prompt([name]);
|
||||||
git_init = true;
|
git_init = true;
|
||||||
pm = 'npm';
|
|
||||||
data = {
|
data = {
|
||||||
name: projectName.name,
|
name: projectName.name,
|
||||||
lang: 'typescript',
|
lang: 'typescript',
|
||||||
@@ -54,21 +34,20 @@ export async function init(flags) {
|
|||||||
cmds_dir: 'commands',
|
cmds_dir: 'commands',
|
||||||
};
|
};
|
||||||
} else if (flags.sync) {
|
} else if (flags.sync) {
|
||||||
data = await prompt([lang, main_dir, cmds_dir]);
|
data = (await prompt([lang, main_dir, cmds_dir])) as PromptData;
|
||||||
} else {
|
} else {
|
||||||
data = await prompt([name, lang, main_dir, cmds_dir]);
|
data = (await prompt([name, lang, main_dir, cmds_dir])) as PromptData;
|
||||||
git_init = (await prompt([gitInit])).gitinit;
|
git_init = (await prompt([gitInit])).gitinit;
|
||||||
pm = await npm();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const language = data.lang === 'javascript-esm' ? 'javascript' : data.lang;
|
||||||
const config = {
|
const config = {
|
||||||
language: data.lang,
|
language,
|
||||||
paths: {
|
paths: {
|
||||||
base: data.main_dir,
|
base: data.main_dir,
|
||||||
commands: data.cmds_dir,
|
commands: data.cmds_dir,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const file = JSON.stringify(config, null, 2);
|
const file = JSON.stringify(config, null, 2);
|
||||||
|
|
||||||
const requiredData = flags.sync !== undefined ? 3 : 4;
|
const requiredData = flags.sync !== undefined ? 3 : 4;
|
||||||
@@ -85,9 +64,7 @@ export async function init(flags) {
|
|||||||
|
|
||||||
if (!pkg) throw new Error('No package.json found!');
|
if (!pkg) throw new Error('No package.json found!');
|
||||||
|
|
||||||
if (pkg) {
|
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
||||||
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.sync) {
|
if (flags.sync) {
|
||||||
console.log('Project was successfully synced!');
|
console.log('Project was successfully synced!');
|
||||||
@@ -96,14 +73,14 @@ export async function init(flags) {
|
|||||||
|
|
||||||
git_init ? await git(data) : console.log(`Skipping git init...\n`);
|
git_init ? await git(data) : console.log(`Skipping git init...\n`);
|
||||||
|
|
||||||
let choice;
|
let choice: PackageManagerChoice;
|
||||||
|
|
||||||
if (pm === 'both') {
|
if (pm === 'both') {
|
||||||
const chosen = await prompt([which_manager]);
|
choice = (await prompt([which_manager])).manager;
|
||||||
choice = chosen.manager;
|
|
||||||
} else {
|
} else {
|
||||||
const chosen = await prompt([skip_install_dep]);
|
choice = (
|
||||||
choice = chosen.skip_install_dep ? pm : 'skip';
|
(await prompt([skip_install_dep])).skip_install_dep ? pm : 'skip'
|
||||||
|
) as PackageManagerChoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
await installDeps(choice, data.name);
|
await installDeps(choice, data.name);
|
||||||
@@ -114,38 +91,46 @@ export async function init(flags) {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** It initializes git */
|
||||||
* It initializes git
|
async function git(data: Data) {
|
||||||
* @param data - The data object that contains the name of the project.
|
|
||||||
*/
|
|
||||||
async function git(data) {
|
|
||||||
const spin = ora({
|
const spin = ora({
|
||||||
text: 'Initializing git...',
|
text: 'Initializing git...',
|
||||||
spinner: 'aesthetic',
|
spinner: 'aesthetic',
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
const exe = await execa('git', ['init', data.name]);
|
try {
|
||||||
|
await execa('git', ['init', data.name]);
|
||||||
await wait(300);
|
await wait(300);
|
||||||
|
spin.succeed('Git initialized!');
|
||||||
if (!exe || exe?.failed) {
|
} catch (error) {
|
||||||
spin.fail(
|
spin.fail(
|
||||||
`${redBright('Failed')} to initialize git!` +
|
`${redBright(
|
||||||
'\nMaybe you should run git init?'
|
'Failed'
|
||||||
|
)} to initialize git!\nTry to install it at ${underline(
|
||||||
|
'https://git-scm.com'
|
||||||
|
)}\nSkipping for now.`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin.succeed('Git initialized!');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Wait for a specified number of milliseconds, then return a promise that resolves to undefined. */
|
||||||
* Wait for a specified number of milliseconds, then return a promise that resolves to undefined.
|
async function wait(ms: number) {
|
||||||
* @param {number} ms - The number of milliseconds to wait.
|
|
||||||
* @returns A function that takes a single argument, ms, and returns a promise that resolves after ms
|
|
||||||
* milliseconds.
|
|
||||||
*/
|
|
||||||
async function wait(ms) {
|
|
||||||
const wait = (await import('util')).promisify(setTimeout);
|
const wait = (await import('util')).promisify(setTimeout);
|
||||||
return wait(ms);
|
return wait(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Flags {
|
||||||
|
y: boolean;
|
||||||
|
sync: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PromptData {
|
||||||
|
name: string;
|
||||||
|
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
||||||
|
main_dir: string;
|
||||||
|
cmds_dir: string;
|
||||||
|
}
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import { pluginsQ } from '../prompts/plugin.js';
|
|
||||||
import prompts from 'prompts';
|
|
||||||
import { fetch } from 'undici';
|
|
||||||
import fs from 'fs';
|
|
||||||
import { greenBright } from 'colorette';
|
|
||||||
const { prompt } = prompts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Installs plugins to project
|
|
||||||
*/
|
|
||||||
export async function plugins() {
|
|
||||||
/**
|
|
||||||
* @type {string[]}
|
|
||||||
*/
|
|
||||||
const e = (await prompt([await pluginsQ()])).list;
|
|
||||||
if (!e) process.exit(1);
|
|
||||||
|
|
||||||
for await (const url of e) {
|
|
||||||
await download(url);
|
|
||||||
}
|
|
||||||
const pluginNames = e.map((e) => e.split('/').pop());
|
|
||||||
console.log(
|
|
||||||
`Successfully downloaded plugin(s):\n${greenBright(
|
|
||||||
pluginNames.join('\n')
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} url
|
|
||||||
* @returns File
|
|
||||||
*/
|
|
||||||
async function download(url) {
|
|
||||||
const data = await fetch(url, { method: 'GET' })
|
|
||||||
.then((res) => res.text())
|
|
||||||
.catch(() => null);
|
|
||||||
|
|
||||||
if (!data) throw new Error('Download failed! Kindly contact developers');
|
|
||||||
|
|
||||||
const dir = `${process.cwd()}/src/plugins`;
|
|
||||||
const filedir = `${process.cwd()}/src/plugins/${url.split('/').pop()}`;
|
|
||||||
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
|
||||||
}
|
|
||||||
const file = fs.writeFileSync(filedir, data);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
73
src/commands/plugins.ts
Normal file
73
src/commands/plugins.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { greenBright } from 'colorette';
|
||||||
|
import fs from 'fs';
|
||||||
|
import prompt from 'prompts';
|
||||||
|
import { fetch, type Response } from 'undici';
|
||||||
|
import { pluginsQ } from '../prompts/plugin.js';
|
||||||
|
import { fromCwd } from '../utilities/fromCwd.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs plugins to project
|
||||||
|
*/
|
||||||
|
|
||||||
|
function dispatchSave() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispatchInstall() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function plugins(options: PluginOptions) {
|
||||||
|
if(options.save) {
|
||||||
|
dispatchSave()
|
||||||
|
}
|
||||||
|
//Download instead based on names given. Must be a full filename ie: (publish)
|
||||||
|
if(options.name) {
|
||||||
|
|
||||||
|
const pluginSource = await downloa();
|
||||||
|
|
||||||
|
}
|
||||||
|
const e: string[] = (await prompt([await pluginsQ()])).list;
|
||||||
|
if (!e) process.exit(1);
|
||||||
|
|
||||||
|
for await (const url of e) {
|
||||||
|
await download(url);
|
||||||
|
}
|
||||||
|
const pluginNames = e.map((e) => e.split('/').pop());
|
||||||
|
console.log(
|
||||||
|
`Successfully downloaded plugin(s):\n${greenBright(
|
||||||
|
pluginNames.join('\n')
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloa(url: string | URL) {
|
||||||
|
const formatText = (res: Response) => res.text()
|
||||||
|
return fetch(url, { method: 'GET' })
|
||||||
|
.then(formatText)
|
||||||
|
.catch(() => {
|
||||||
|
throw Error('Download failed! Kindly contact developers')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function download(url: string) {
|
||||||
|
const data = await fetch(url, { method: 'GET' })
|
||||||
|
.then((res) => res.text())
|
||||||
|
.catch(() => null);
|
||||||
|
|
||||||
|
if (!data) throw new Error('Download failed! Kindly contact developers');
|
||||||
|
|
||||||
|
const dir = fromCwd('/src/plugins');
|
||||||
|
const filedir = `${process.cwd()}/src/plugins/${url.split('/').pop()}`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
fs.writeFileSync(filedir, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
name?: string[];
|
||||||
|
save: boolean
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { init } from './commands/init.js';
|
|
||||||
import { help } from './commands/help.js';
|
|
||||||
import { extra } from './commands/extra.js';
|
import { extra } from './commands/extra.js';
|
||||||
|
import { help } from './commands/help.js';
|
||||||
|
import { init } from './commands/init.js';
|
||||||
|
|
||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import { version } from './utilities/version.js';
|
|
||||||
import { plugins } from './commands/plugins.js';
|
import { plugins } from './commands/plugins.js';
|
||||||
export const program = new Command();
|
export const program = new Command();
|
||||||
|
|
||||||
|
const version: string = '[VI]{{inject}}[/VI]';
|
||||||
|
|
||||||
program
|
program
|
||||||
.name('sern')
|
.name('sern')
|
||||||
.description(help())
|
.description(help)
|
||||||
.version(version())
|
.version(`sern CLI v${version}`)
|
||||||
.exitOverride(() => process.exit(0));
|
.exitOverride(() => process.exit(0));
|
||||||
|
|
||||||
program
|
program
|
||||||
@@ -22,14 +23,15 @@ program
|
|||||||
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
||||||
.action(init);
|
.action(init);
|
||||||
|
|
||||||
program
|
const pluginCommand = program.command(plugins.name)
|
||||||
.command(plugins.name)
|
pluginCommand
|
||||||
.description(
|
.description(
|
||||||
'Install plugins from https://github.com/sern-handler/awesome-plugins'
|
'Get plugins from https://github.com/sern-handler/awesome-plugins'
|
||||||
)
|
)
|
||||||
.option('-n --name', 'Name of plugin')
|
.option('-n --name <string...>', 'Name(s) of plugin to install')
|
||||||
.action(plugins);
|
.option('-S --save', 'Save and keep plugins updated')
|
||||||
|
.action(plugins);
|
||||||
|
|
||||||
program
|
program
|
||||||
.command(extra.name)
|
.command(extra.name)
|
||||||
.description('Easy way to add extra things in your sern project')
|
.description('Easy way to add extra things in your sern project')
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export const extraPrompt = {
|
import type { PromptObject } from 'prompts';
|
||||||
|
|
||||||
|
export const extraPrompt: PromptObject = {
|
||||||
message: 'What extra feature do you want to add?',
|
message: 'What extra feature do you want to add?',
|
||||||
name: 'extra',
|
name: 'extra',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { blueBright } from 'colorette';
|
import { blueBright } from 'colorette';
|
||||||
|
import type { PromptObject } from 'prompts';
|
||||||
|
|
||||||
export const lang = {
|
export const lang: PromptObject = {
|
||||||
message: 'What language do you want the project to be in?',
|
message: 'What language do you want the project to be in?',
|
||||||
name: 'lang',
|
name: 'lang',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -10,6 +11,11 @@ export const lang = {
|
|||||||
description: 'JS',
|
description: 'JS',
|
||||||
value: 'javascript',
|
value: 'javascript',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'JavaScript (ESM)',
|
||||||
|
description: 'JS',
|
||||||
|
value: 'javascript-esm',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'TypeScript',
|
title: 'TypeScript',
|
||||||
description: 'TS - (Recommended)',
|
description: 'TS - (Recommended)',
|
||||||
@@ -18,40 +24,37 @@ export const lang = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const main_dir = {
|
export const main_dir: PromptObject = {
|
||||||
message: 'What is the main directory of your project?',
|
message: 'What is the main directory of your project?',
|
||||||
name: 'main_dir',
|
name: 'main_dir',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
initial: 'src',
|
initial: 'src',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cmds_dir = {
|
export const cmds_dir: PromptObject = {
|
||||||
message: 'What is the directory of your commands?',
|
message: 'What is the directory of your commands?',
|
||||||
name: 'cmds_dir',
|
name: 'cmds_dir',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
initial: 'commands',
|
initial: 'commands',
|
||||||
validate: (/** @type {string} */ dir) =>
|
validate: (dir: string) =>
|
||||||
dir === 'src' ? 'You can not use src as a directory' : true,
|
dir === 'src' ? 'You can not use src as a directory' : true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const npmInit: PromptObject = {
|
||||||
* @type {import('prompts').PromptObject}
|
|
||||||
*/
|
|
||||||
export const npmInit = {
|
|
||||||
name: 'npm_init',
|
name: 'npm_init',
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
message: `Do you want ${blueBright('me')} to initialize npm?`,
|
message: `Do you want ${blueBright('me')} to initialize npm?`,
|
||||||
initial: true,
|
initial: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const gitInit = {
|
export const gitInit: PromptObject = {
|
||||||
name: 'gitinit',
|
name: 'gitinit',
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
message: `Do you want to ${blueBright('me')} to initialize git?`,
|
message: `Do you want to ${blueBright('me')} to initialize git?`,
|
||||||
initial: true,
|
initial: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const which_manager = {
|
export const which_manager: PromptObject = {
|
||||||
message: `Which manager do you want to use?`,
|
message: `Which manager do you want to use?`,
|
||||||
name: 'manager',
|
name: 'manager',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -75,21 +78,18 @@ export const which_manager = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const skip_install_dep = {
|
export const skip_install_dep: PromptObject = {
|
||||||
name: 'skip_install_dep',
|
name: 'skip_install_dep',
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
message: `Do you want ${blueBright('me')} to install dependencies?`,
|
message: `Do you want ${blueBright('me')} to install dependencies?`,
|
||||||
initial: false,
|
initial: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const name: PromptObject = {
|
||||||
* @type {import('prompts').PromptObject}
|
|
||||||
*/
|
|
||||||
export const name = {
|
|
||||||
message: 'What is your project name?',
|
message: 'What is your project name?',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
validate: (/**@type {string}*/ name) =>
|
validate: (name: string) =>
|
||||||
name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$')
|
name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$')
|
||||||
? true
|
? true
|
||||||
: 'Invalid name',
|
: 'Invalid name',
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import { fetch } from 'undici';
|
|
||||||
import { getLang } from '../utilities/getLang.js';
|
|
||||||
async function gimmechoices() {
|
|
||||||
const lang =
|
|
||||||
(await getLang().catch(() => null)) === 'typescript'
|
|
||||||
? 'TypeScript'
|
|
||||||
: 'JavaScript';
|
|
||||||
const link = `https://api.github.com/repos/sern-handler/awesome-plugins/contents/${lang}`;
|
|
||||||
|
|
||||||
const resp = await fetch(link).catch(() => null);
|
|
||||||
|
|
||||||
if (!resp) return { title: 'No plugins found!', value: '', disabled: true };
|
|
||||||
|
|
||||||
const data = await resp.json();
|
|
||||||
const choices = data.map(
|
|
||||||
(/** @type {{ name: string; download_url: string; }} */ e) => ({
|
|
||||||
title: e.name,
|
|
||||||
value: e.download_url,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return choices;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function pluginsQ() {
|
|
||||||
return {
|
|
||||||
name: 'list',
|
|
||||||
type: 'autocompleteMultiselect',
|
|
||||||
message: 'What plugins do you want to install?',
|
|
||||||
choices: await gimmechoices(),
|
|
||||||
min: 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
45
src/prompts/plugin.ts
Normal file
45
src/prompts/plugin.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import type { Choice, PromptObject } from 'prompts';
|
||||||
|
import { fetch } from 'undici';
|
||||||
|
import { getLang } from '../utilities/getLang.js';
|
||||||
|
|
||||||
|
function upperCase(string: string | null) {
|
||||||
|
if (string === null) {
|
||||||
|
console.error('Lang property not found!');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
return string === 'typescript' ? 'TypeScript' : 'JavaScript';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gimmechoices(): Promise<Choice[]> {
|
||||||
|
const lang = upperCase(await getLang().catch(() => null));
|
||||||
|
|
||||||
|
const link = `https://api.github.com/repos/sern-handler/awesome-plugins/contents/${lang}`;
|
||||||
|
|
||||||
|
const resp = await fetch(link).catch(() => null);
|
||||||
|
if (!resp)
|
||||||
|
return [{ title: 'No plugins found!', value: '', disabled: true }];
|
||||||
|
|
||||||
|
const data = (await resp.json()) as Data[];
|
||||||
|
const choices = data.map((e) => ({
|
||||||
|
title: e.name,
|
||||||
|
value: e.download_url,
|
||||||
|
}));
|
||||||
|
return choices;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function pluginsQ(): Promise<PromptObject> {
|
||||||
|
return {
|
||||||
|
name: 'list',
|
||||||
|
type: 'autocompleteMultiselect',
|
||||||
|
message: 'What plugins do you want to install?',
|
||||||
|
choices: await gimmechoices(),
|
||||||
|
min: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
name: string;
|
||||||
|
download_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { URL, fileURLToPath } from 'url';
|
import { mkdir, readFile, writeFile } from 'fs/promises';
|
||||||
import { resolve, dirname } from 'node:path';
|
import { dirname, resolve } from 'node:path';
|
||||||
import { readFile, mkdir, writeFile } from 'fs/promises';
|
import { fileURLToPath, URL } from 'url';
|
||||||
const root = new URL('../', import.meta.url);
|
const root = new URL('../../', import.meta.url);
|
||||||
|
|
||||||
const templates = new URL('./templates/', root);
|
const templates = new URL('./templates/', root);
|
||||||
const extraURL = new URL('./extra/', templates);
|
const extraURL = new URL('./extra/', templates);
|
||||||
@@ -9,13 +9,17 @@ const extraFolder = fileURLToPath(extraURL);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* It creates a file with the name `name.lang.sern` in the `location` directory
|
* It creates a file with the name `name.lang.sern` in the `location` directory
|
||||||
* @param {string} name - The name of the file.
|
* @param name - The name of the file.
|
||||||
* @param {string} lang - The language you want to use.
|
* @param lang - The language you want to use.
|
||||||
* @param {string} location - The location of the file to be created.
|
* @param location - The location of the file to be created.
|
||||||
* @param {boolean} no_ext - If true, the file will be created without an extension.
|
* @param no_ext - If true, the file will be created without an extension.
|
||||||
* @returns File
|
|
||||||
*/
|
*/
|
||||||
export async function create(name, lang, location, no_ext) {
|
export async function create(
|
||||||
|
name: string,
|
||||||
|
lang: string,
|
||||||
|
location: string,
|
||||||
|
no_ext: boolean
|
||||||
|
) {
|
||||||
const file = `${name}.${lang}.sern`;
|
const file = `${name}.${lang}.sern`;
|
||||||
|
|
||||||
const target = no_ext
|
const target = no_ext
|
||||||
@@ -27,10 +31,10 @@ export async function create(name, lang, location, no_ext) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* It reads a file from a template folder, and writes it to a target folder
|
* It reads a file from a template folder, and writes it to a target folder
|
||||||
* @param {string} template - The name of the file to be created.
|
* @param template - The name of the file to be created.
|
||||||
* @param {string} target - The location of the file to be created.
|
* @param target - The location of the file to be created.
|
||||||
*/
|
*/
|
||||||
async function createFile(template, target) {
|
async function createFile(template: string, target: string) {
|
||||||
const location = `${extraFolder}${template}`;
|
const location = `${extraFolder}${template}`;
|
||||||
|
|
||||||
const file = await readFile(location, 'utf8');
|
const file = await readFile(location, 'utf8');
|
||||||
@@ -40,11 +44,11 @@ async function createFile(template, target) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* It creates a directory recursively, then writes a file to it
|
* It creates a directory recursively, then writes a file to it
|
||||||
* @param {string} target - The path to the file you want to write to.
|
* @param target - The path to the file you want to write to.
|
||||||
* @param {string} data - The data to write to the file.
|
* @param data - The data to write to the file.
|
||||||
* @returns A promise that resolves to the result of the writeFile function.
|
* @returns A promise that resolves to the result of the writeFile function.
|
||||||
*/
|
*/
|
||||||
async function writeFileRecursive(target, data) {
|
async function writeFileRecursive(target: string, data: string) {
|
||||||
const resolvedTarget = resolve(target);
|
const resolvedTarget = resolve(target);
|
||||||
const dir = dirname(resolvedTarget);
|
const dir = dirname(resolvedTarget);
|
||||||
|
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { readFile, rename, writeFile } from 'node:fs/promises';
|
|
||||||
import { findUp } from 'find-up';
|
import { findUp } from 'find-up';
|
||||||
|
import { readFile, rename, writeFile } from 'node:fs/promises';
|
||||||
|
import { fromCwd } from './fromCwd.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It takes a string, finds the package.json file in the directory of the string, and changes the name
|
* It takes a string, finds the package.json file in the directory of the string, and changes the name
|
||||||
* of the package.json file to the string.
|
* of the package.json file to the string.
|
||||||
* @param {string} name - The name of the project.
|
* @param name - The name of the project.
|
||||||
* @returns A promise.
|
|
||||||
*/
|
*/
|
||||||
export async function editMain(name) {
|
export async function editMain(name: string) {
|
||||||
const pjLocation = await findUp('package.json', {
|
const pjLocation = (await findUp('package.json', {
|
||||||
cwd: process.cwd() + '/' + name,
|
cwd: fromCwd('/' + name),
|
||||||
});
|
})) as string;
|
||||||
|
|
||||||
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
||||||
if (!output) throw new Error("Can't read your package.json.");
|
if (!output) throw new Error("Can't read your package.json.");
|
||||||
@@ -23,36 +23,35 @@ export async function editMain(name) {
|
|||||||
/**
|
/**
|
||||||
* It renames the `src` and `commands` directories, and edits the `index.ts` file to reflect the
|
* It renames the `src` and `commands` directories, and edits the `index.ts` file to reflect the
|
||||||
* changes
|
* changes
|
||||||
* @param {string} srcName - The name of the folder that will contain your main files.
|
* @param srcName - The name of the folder that will contain your main files.
|
||||||
* @param {string} cmds_dirName - The name of the directory where your commands will be stored.
|
* @param cmds_dirName - The name of the directory where your commands will be stored.
|
||||||
* @param {string} name - The name of the folder you want to edit.
|
* @param name - The name of the folder you want to edit.
|
||||||
* @param {'javascript' | 'typescript'} lang - The language you want to use.
|
* @param lang - The language you want to use.
|
||||||
* @returns void
|
|
||||||
*/
|
*/
|
||||||
export async function editDirs(
|
export async function editDirs(
|
||||||
srcName,
|
srcName: string,
|
||||||
cmds_dirName,
|
cmds_dirName: string,
|
||||||
name,
|
name: string,
|
||||||
lang = 'typescript'
|
lang: 'javascript' | 'typescript' | 'javascript-esm' = 'typescript'
|
||||||
) {
|
) {
|
||||||
const path = await findUp('src', {
|
const path = (await findUp('src', {
|
||||||
cwd: process.cwd() + '/' + name,
|
cwd: fromCwd(name),
|
||||||
type: 'directory',
|
type: 'directory',
|
||||||
});
|
})) as string;
|
||||||
|
|
||||||
const ext = lang === 'typescript' ? 'ts' : 'js';
|
const ext = lang === 'typescript' ? 'ts' : 'js';
|
||||||
|
|
||||||
const newMainDir = path?.replace('src', srcName);
|
const newMainDir = path?.replace('src', srcName);
|
||||||
await rename(path, newMainDir);
|
await rename(path, newMainDir);
|
||||||
|
|
||||||
const cmdsPath = await findUp('commands', {
|
const cmdsPath = (await findUp('commands', {
|
||||||
cwd: process.cwd() + '/' + name + '/' + srcName,
|
cwd: fromCwd(name, srcName),
|
||||||
type: 'directory',
|
type: 'directory',
|
||||||
});
|
})) as string;
|
||||||
|
|
||||||
const index = await findUp(`index.${ext}`, {
|
const index = (await findUp(`index.${ext}`, {
|
||||||
cwd: process.cwd() + '/' + name + '/' + srcName,
|
cwd: fromCwd(name, srcName),
|
||||||
});
|
})) as string;
|
||||||
|
|
||||||
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
||||||
await rename(cmdsPath, newCmdsPath);
|
await rename(cmdsPath, newCmdsPath);
|
||||||
@@ -66,7 +65,7 @@ export async function editDirs(
|
|||||||
if (!output) throw new Error("Can't read your tsconfig.json.");
|
if (!output) throw new Error("Can't read your tsconfig.json.");
|
||||||
output.compilerOptions.rootDir = srcName;
|
output.compilerOptions.rootDir = srcName;
|
||||||
|
|
||||||
writeFile(tsconfig, JSON.stringify(output, null, 2));
|
await writeFile(tsconfig, JSON.stringify(output, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = await readFile(index, 'utf8');
|
const output = await readFile(index, 'utf8');
|
||||||
5
src/utilities/fromCwd.ts
Normal file
5
src/utilities/fromCwd.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export function fromCwd(...dir: string[]) {
|
||||||
|
return path.join(...[process.cwd(), ...dir]);
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@ import { readFile } from 'node:fs/promises';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* It finds the sern.config.json file, reads it, and returns the language property
|
* It finds the sern.config.json file, reads it, and returns the language property
|
||||||
* @returns {Promise<string>} The language of the project.
|
* @returns The language of the project.
|
||||||
*/
|
*/
|
||||||
export async function getLang() {
|
export async function getLang(): Promise<'typescript' | 'javascript'> {
|
||||||
const sernLocation = await findUp('sern.config.json');
|
const sernLocation = await findUp('sern.config.json');
|
||||||
|
|
||||||
if (!sernLocation) throw new Error("Can't find sern.config.json");
|
if (!sernLocation) throw new Error("Can't find sern.config.json");
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { execa } from 'execa';
|
|
||||||
import { redBright } from 'colorette';
|
import { redBright } from 'colorette';
|
||||||
import fs from 'fs';
|
import { execa } from 'execa';
|
||||||
import path from 'path';
|
|
||||||
import { readFile } from 'fs/promises';
|
|
||||||
import { findUp } from 'find-up';
|
import { findUp } from 'find-up';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { readFile } from 'fs/promises';
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
|
import path from 'path';
|
||||||
|
import type { PackageManagerChoice } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It installs dependencies from a package.json file
|
* It installs dependencies from a package.json file
|
||||||
* @param {'skip' | 'npm' | 'yarn'} choice - The package manager to use.
|
* @param choice - The package manager to use.
|
||||||
* @param {string} name - The name of the project
|
* @param name - The name of the project
|
||||||
* @returns a promise.
|
|
||||||
*/
|
*/
|
||||||
export async function installDeps(choice, name) {
|
export async function installDeps(choice: PackageManagerChoice, name: string) {
|
||||||
const pkg = await findUp('package.json', {
|
const pkg = await findUp('package.json', {
|
||||||
cwd: process.cwd() + '/' + name,
|
cwd: process.cwd() + '/' + name,
|
||||||
});
|
});
|
||||||
@@ -36,6 +36,7 @@ export async function installDeps(choice, name) {
|
|||||||
const result = await execa(choice, ['install'], {
|
const result = await execa(choice, ['install'], {
|
||||||
cwd: process.cwd() + '/' + name,
|
cwd: process.cwd() + '/' + name,
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
|
|
||||||
if (!result || result?.failed) {
|
if (!result || result?.failed) {
|
||||||
spin.fail(`${redBright('Failed')} to install dependencies!`);
|
spin.fail(`${redBright('Failed')} to install dependencies!`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -44,29 +45,38 @@ export async function installDeps(choice, name) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the repo, copy the files from the repo to the new project directory, and delete the repo
|
* Clone the repo, copy the files from the repo to the new project directory, and delete the repo
|
||||||
* @param {string} lang - The language of the template
|
* @param lang - The language of the template
|
||||||
* @param {string} name - The name of the project
|
* @param name - The name of the project
|
||||||
*/
|
*/
|
||||||
export async function cloneRepo(lang, name) {
|
export async function cloneRepo(lang: string, name: string) {
|
||||||
await execa('git', [
|
try {
|
||||||
'clone',
|
await execa('git', [
|
||||||
`https://github.com/sern-handler/templates.git`,
|
'clone',
|
||||||
]);
|
`https://github.com/sern-handler/templates.git`,
|
||||||
copyRecursiveSync(`templates/templates/${lang}`, name);
|
]);
|
||||||
fs.rmSync(`templates/`, { recursive: true, force: true });
|
copyRecursiveSync(`templates/templates/${lang}`, name);
|
||||||
|
fs.rmSync(`templates/`, { recursive: true, force: true });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(
|
||||||
|
`${redBright(
|
||||||
|
'✖ Failed'
|
||||||
|
)} to clone github templates repo. Install git and try again!`
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the source is a directory, create the destination directory and then recursively copy the
|
* If the source is a directory, create the destination directory and then recursively copy the
|
||||||
* contents of the source directory to the destination directory. If the source is not a directory,
|
* contents of the source directory to the destination directory. If the source is not a directory,
|
||||||
* copy the source file to the destination file
|
* copy the source file to the destination file
|
||||||
* @param {string} src - The source path.
|
* @param src - The source path.
|
||||||
* @param {string} dest - The destination folder where the files will be copied to.
|
* @param dest - The destination folder where the files will be copied to.
|
||||||
*/
|
*/
|
||||||
export function copyRecursiveSync(src, dest) {
|
export function copyRecursiveSync(src: string, dest: string) {
|
||||||
const exists = fs.existsSync(src);
|
const exists = fs.existsSync(src);
|
||||||
|
|
||||||
const stats = exists && fs.statSync(src);
|
const stats = (exists && fs.statSync(src)) as fs.Stats;
|
||||||
|
|
||||||
const isDirectory = exists && stats.isDirectory();
|
const isDirectory = exists && stats.isDirectory();
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
@@ -82,8 +92,3 @@ export function copyRecursiveSync(src, dest) {
|
|||||||
fs.copyFileSync(src, dest);
|
fs.copyFileSync(src, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function wait(ms) {
|
|
||||||
// const wait = (await import('util')).promisify(setTimeout);
|
|
||||||
// return wait(ms);
|
|
||||||
// }
|
|
||||||
10
src/utilities/types.ts
Normal file
10
src/utilities/types.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export type PackageManagerChoice = 'skip' | 'npm' | 'yarn';
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
language: string;
|
||||||
|
paths : {
|
||||||
|
base: string;
|
||||||
|
commands: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { createRequire } from 'module';
|
|
||||||
const require = createRequire(import.meta.url);
|
|
||||||
|
|
||||||
export function version() {
|
|
||||||
const { version: v } = require('../../package.json');
|
|
||||||
return `SernHandler CLI v${v}`;
|
|
||||||
}
|
|
||||||
6
src/utilities/version.ts
Normal file
6
src/utilities/version.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { requiree } from "..";
|
||||||
|
|
||||||
|
export function version() {
|
||||||
|
const { version: v } = requiree('../../package.json');
|
||||||
|
return `@sern/cli v${v}`;
|
||||||
|
}
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "Node",
|
||||||
"lib": ["es2017", "dom"],
|
"outDir": "dist",
|
||||||
"allowJs": true,
|
"rootDir": "src",
|
||||||
"checkJs": true,
|
"declaration": true,
|
||||||
"noEmit": true,
|
"declarationMap": true,
|
||||||
"strict": false,
|
"strict": true,
|
||||||
"noImplicitThis": true,
|
|
||||||
"alwaysStrict": true,
|
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true
|
"noImplicitAny": true,
|
||||||
},
|
"strictNullChecks": true,
|
||||||
"include": ["test", "src"]
|
"importsNotUsedAsValues": "error",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
tsup.config.ts
Normal file
19
tsup.config.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { defineConfig } from 'tsup'
|
||||||
|
import { esbuildPluginVersionInjector } from 'esbuild-plugin-version-injector';
|
||||||
|
const shared = {
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
platform: 'node',
|
||||||
|
clean: true,
|
||||||
|
sourcemap: true,
|
||||||
|
};
|
||||||
|
export default defineConfig(
|
||||||
|
{
|
||||||
|
format: 'esm',
|
||||||
|
target: 'node16',
|
||||||
|
tsconfig: './tsconfig.json',
|
||||||
|
outDir: './dist',
|
||||||
|
treeshake: true,
|
||||||
|
esbuildPlugins: [esbuildPluginVersionInjector()],
|
||||||
|
...shared,
|
||||||
|
}
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user