mirror of
https://github.com/sern-handler/cli
synced 2026-06-06 17:36:53 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f12d541dfe | ||
|
|
642bf11608 | ||
|
|
827ffb7ad9 | ||
|
|
2348e3e9ab | ||
|
|
14df4a9b65 | ||
|
|
4bc7d1b081 | ||
|
|
acbec3e733 | ||
|
|
dbc3154101 | ||
|
|
7252c533bc | ||
|
|
dce78c0945 | ||
|
|
58fa3253f6 | ||
|
|
1421136181 | ||
|
|
f29c7881fe | ||
|
|
0d37da5689 | ||
|
|
504d36729e | ||
|
|
e391fddf20 | ||
|
|
e5d6de4841 | ||
|
|
fc47847eeb | ||
|
|
386b30aedd | ||
|
|
f2531a6f9b | ||
| 69287ab1bd | |||
|
|
aa398a871c | ||
|
|
0855abfea3 |
4
.github/workflows/auto-deprecate.yml
vendored
4
.github/workflows/auto-deprecate.yml
vendored
@@ -12,10 +12,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org/'
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
4
.github/workflows/continuous-delivery.yml
vendored
4
.github/workflows/continuous-delivery.yml
vendored
@@ -15,10 +15,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
8
.github/workflows/continuous-integration.yml
vendored
8
.github/workflows/continuous-integration.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
|
||||
@@ -37,10 +37,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
|
||||
|
||||
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
@@ -14,16 +14,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm i
|
||||
run: npm i && npm run build
|
||||
|
||||
- name: Link Project
|
||||
run: npm link
|
||||
|
||||
8
.github/workflows/release-please.yml
vendored
8
.github/workflows/release-please.yml
vendored
@@ -12,15 +12,15 @@ jobs:
|
||||
with:
|
||||
release-type: node
|
||||
bump-patch-for-minor-pre-major: true
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- run: npm i
|
||||
- run: npm i && npm run build
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- run: npm link
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
@@ -29,4 +29,4 @@ jobs:
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"singleQuote": true
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 140
|
||||
}
|
||||
|
||||
30
CHANGELOG.md
30
CHANGELOG.md
@@ -2,6 +2,36 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.6.0](https://github.com/sern-handler/cli/compare/v0.5.1...v0.6.0) (2023-08-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* publish command ([#105](https://github.com/sern-handler/cli/issues/105)) ([827ffb7](https://github.com/sern-handler/cli/commit/827ffb7ad9252e3cda257bed1febdca2da03e253))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* change file path for sern/extras ([#109](https://github.com/sern-handler/cli/issues/109)) ([2348e3e](https://github.com/sern-handler/cli/commit/2348e3e9ab055fddab3f44d574af79fd7ccd4485))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* release 0.6.0 ([642bf11](https://github.com/sern-handler/cli/commit/642bf11608cf5d9b4256999e3bdb48e762ca88ee))
|
||||
|
||||
## [0.5.1](https://github.com/sern-handler/cli/compare/v0.5.0...v0.5.1) (2023-06-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **init:** deprecate init and bump deps ([#102](https://github.com/sern-handler/cli/issues/102)) ([dce78c0](https://github.com/sern-handler/cli/commit/dce78c0945de6da79bf1e268f29651da0c44c1eb))
|
||||
* version injector ([#90](https://github.com/sern-handler/cli/issues/90)) ([58fa325](https://github.com/sern-handler/cli/commit/58fa3253f62da9fb66d1b2ae901b568367f065d0))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* git not installed errors during init ([#79](https://github.com/sern-handler/cli/issues/79)) ([69287ab](https://github.com/sern-handler/cli/commit/69287ab1bd0c4960384144f90fea8ebded3b0cc5))
|
||||
|
||||
## [0.5.0](https://github.com/sern-handler/cli/compare/v0.4.2...v0.5.0) (2022-09-16)
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ npm install -g @sern/cli@latest
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn add -g @sern/cli@latest
|
||||
yarn global add @sern/cli@latest
|
||||
```
|
||||
|
||||
```sh
|
||||
|
||||
8552
package-lock.json
generated
8552
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
114
package.json
114
package.json
@@ -1,56 +1,62 @@
|
||||
{
|
||||
"name": "@sern/cli",
|
||||
"version": "0.5.0",
|
||||
"description": "Official CLI for @sern/handler",
|
||||
"exports": "./dist/index.js",
|
||||
"bin": {
|
||||
"sern": "./dist/index.js"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"format": "prettier --check .",
|
||||
"fix": "prettier --write .",
|
||||
"build": "tsc",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sern-handler/cli.git"
|
||||
},
|
||||
"keywords": [
|
||||
"cli",
|
||||
"discord",
|
||||
"discord.js",
|
||||
"sern",
|
||||
"sern-handler"
|
||||
],
|
||||
"author": "EvolutionX",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sern-handler/cli/issues"
|
||||
},
|
||||
"homepage": "https://sern-handler.js.org",
|
||||
"dependencies": {
|
||||
"colorette": "^2.0.16",
|
||||
"commander": "^9.3.0",
|
||||
"execa": "^6.1.0",
|
||||
"find-up": "6.3.0",
|
||||
"ora": "^6.1.0",
|
||||
"prompts": "2.4.2",
|
||||
"undici": "^5.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@favware/npm-deprecate": "1.0.5",
|
||||
"@types/prompts": "2.0.14",
|
||||
"prettier": "2.7.1",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16.10.x"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"access": "public"
|
||||
}
|
||||
"name": "@sern/cli",
|
||||
"version": "0.6.0",
|
||||
"description": "Official CLI for @sern/handler",
|
||||
"exports": "./dist/index.js",
|
||||
"bin": {
|
||||
"sern": "./dist/index.js"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"format": "prettier --check .",
|
||||
"fix": "prettier --write .",
|
||||
"build": "tsup",
|
||||
"watch": "tsup --watch"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sern-handler/cli.git"
|
||||
},
|
||||
"keywords": [
|
||||
"cli",
|
||||
"discord",
|
||||
"discord.js",
|
||||
"sern",
|
||||
"sern-handler"
|
||||
],
|
||||
"author": "EvolutionX",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sern-handler/cli/issues"
|
||||
},
|
||||
"homepage": "https://sern.dev",
|
||||
"dependencies": {
|
||||
"@esbuild-kit/cjs-loader": "^2.4.2",
|
||||
"@esbuild-kit/esm-loader": "^2.5.5",
|
||||
"colorette": "2.0.20",
|
||||
"commander": "11.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"execa": "7.1.1",
|
||||
"find-up": "6.3.0",
|
||||
"ora": "6.3.1",
|
||||
"prompts": "2.4.2",
|
||||
"undici": "5.22.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@favware/npm-deprecate": "1.0.7",
|
||||
"@types/prompts": "2.4.4",
|
||||
"esbuild-plugin-version-injector": "1.1.0",
|
||||
"prettier": "2.8.8",
|
||||
"tsup": "6.7.0",
|
||||
"typescript": "5.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.16.x"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:base"],
|
||||
"major": {
|
||||
"dependencyDashboardApproval": true
|
||||
},
|
||||
"schedule": ["every weekend"],
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"matchCurrentVersion": "!/^0/"
|
||||
}
|
||||
]
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:base", "group:allNonMajor"],
|
||||
"major": {
|
||||
"dependencyDashboardApproval": true
|
||||
},
|
||||
"schedule": ["every weekend"],
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"matchCurrentVersion": "!/^0/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ import { extraPrompt } from '../prompts/extra.js';
|
||||
import { create } from '../utilities/create.js';
|
||||
|
||||
export async function extra() {
|
||||
const extra = await prompt([extraPrompt]);
|
||||
const extra = await prompt([extraPrompt]);
|
||||
|
||||
if (Object.keys(extra).length < 1) process.exit(1);
|
||||
const lang = extra.extra.includes('typescript') ? 'TS' : 'JS';
|
||||
await create(extra.extra.split('-')[0], lang, process.cwd(), true);
|
||||
if (Object.keys(extra).length < 1) process.exit(1);
|
||||
const lang = extra.extra.includes('typescript') ? 'TS' : 'JS';
|
||||
await create(extra.extra.split('-')[0], lang, process.cwd(), true);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import { cyanBright, green, magentaBright } from 'colorette';
|
||||
|
||||
export function help() {
|
||||
return `
|
||||
export const help = `
|
||||
___ ___ _ __ _ __
|
||||
/ __|/ _ \\ '__| '_ \\
|
||||
\\__ \\ __/ | | | | |
|
||||
|___/\\___|_| |_| |_|
|
||||
|
||||
Welcome!
|
||||
If you're new to ${cyanBright('sern')}, run ${magentaBright(
|
||||
'sern init'
|
||||
)} for an interactive setup to your new bot project!
|
||||
If you're new to ${cyanBright('sern')}, run ${magentaBright('npm create @sern/bot')} 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`
|
||||
)}`;
|
||||
}
|
||||
${green(`If you have any ideas, suggestions, bug reports, kindly join our support server: https://sern.dev/discord`)}`;
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
import { greenBright, redBright } from 'colorette';
|
||||
import { greenBright, redBright, underline, yellowBright } from 'colorette';
|
||||
import { execa } from 'execa';
|
||||
import { findUp } from 'find-up';
|
||||
import ora from 'ora';
|
||||
import prompt from 'prompts';
|
||||
import {
|
||||
cmds_dir,
|
||||
gitInit,
|
||||
lang,
|
||||
main_dir,
|
||||
name,
|
||||
skip_install_dep,
|
||||
which_manager,
|
||||
} from '../prompts/init.js';
|
||||
import { cmds_dir, gitInit, lang, main_dir, name, skip_install_dep, which_manager } from '../prompts/init.js';
|
||||
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { editDirs, editMain } from '../utilities/edits.js';
|
||||
@@ -19,118 +11,113 @@ import { cloneRepo, installDeps } from '../utilities/install.js';
|
||||
import { npm } from '../utilities/npm.js';
|
||||
import type { PackageManagerChoice } from '../utilities/types.js';
|
||||
|
||||
/** @deprecated Use npm create instead */
|
||||
export async function init(flags: Flags) {
|
||||
let data: PromptData;
|
||||
let git_init = true; // the default;
|
||||
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
||||
console.log(`${yellowBright('[WARN]:')} This command is deprecated, use ${greenBright('npm create @sern/bot')} instead`);
|
||||
|
||||
if (flags.y) {
|
||||
const projectName = await prompt([name]);
|
||||
git_init = true;
|
||||
data = {
|
||||
name: projectName.name,
|
||||
lang: 'typescript',
|
||||
main_dir: 'src',
|
||||
cmds_dir: 'commands',
|
||||
};
|
||||
} else if (flags.sync) {
|
||||
data = (await prompt([lang, main_dir, cmds_dir])) as PromptData;
|
||||
} else {
|
||||
data = (await prompt([name, lang, main_dir, cmds_dir])) as PromptData;
|
||||
git_init = (await prompt([gitInit])).gitinit;
|
||||
}
|
||||
let data: PromptData;
|
||||
let git_init = true; // the default;
|
||||
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
||||
|
||||
const language = data.lang === 'javascript-esm' ? 'javascript' : data.lang;
|
||||
const config = {
|
||||
language,
|
||||
paths: {
|
||||
base: data.main_dir,
|
||||
commands: data.cmds_dir,
|
||||
},
|
||||
};
|
||||
const file = JSON.stringify(config, null, 2);
|
||||
if (flags.y) {
|
||||
const projectName = await prompt([name]);
|
||||
git_init = true;
|
||||
data = {
|
||||
name: projectName.name,
|
||||
lang: 'typescript',
|
||||
main_dir: 'src',
|
||||
cmds_dir: 'commands',
|
||||
};
|
||||
} else if (flags.sync) {
|
||||
data = (await prompt([lang, main_dir, cmds_dir])) as PromptData;
|
||||
} else {
|
||||
data = (await prompt([name, lang, main_dir, cmds_dir])) as PromptData;
|
||||
git_init = (await prompt([gitInit])).gitinit;
|
||||
}
|
||||
|
||||
const requiredData = flags.sync !== undefined ? 3 : 4;
|
||||
const receivedData = Object.keys(data).length;
|
||||
const incompleteDataCondition = receivedData < requiredData;
|
||||
const language = data.lang === 'javascript-esm' ? 'javascript' : data.lang;
|
||||
const config = {
|
||||
language,
|
||||
paths: {
|
||||
base: data.main_dir,
|
||||
commands: data.cmds_dir,
|
||||
},
|
||||
};
|
||||
const file = JSON.stringify(config, null, 2);
|
||||
|
||||
if (incompleteDataCondition) process.exit(1);
|
||||
const requiredData = flags.sync !== undefined ? 3 : 4;
|
||||
const receivedData = Object.keys(data).length;
|
||||
const incompleteDataCondition = receivedData < requiredData;
|
||||
|
||||
if (!flags.sync) await cloneRepo(data.lang, data.name);
|
||||
if (incompleteDataCondition) process.exit(1);
|
||||
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + data.name,
|
||||
});
|
||||
if (!flags.sync) await cloneRepo(data.lang, data.name);
|
||||
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + data.name,
|
||||
});
|
||||
|
||||
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
|
||||
if (flags.sync) {
|
||||
console.log('Project was successfully synced!');
|
||||
process.exit(0);
|
||||
}
|
||||
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
||||
|
||||
git_init ? await git(data) : console.log(`Skipping git init...\n`);
|
||||
if (flags.sync) {
|
||||
console.log('Project was successfully synced!');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let choice: PackageManagerChoice;
|
||||
git_init ? await git(data) : console.log(`Skipping git init...\n`);
|
||||
|
||||
if (pm === 'both') {
|
||||
choice = (await prompt([which_manager])).manager;
|
||||
} else {
|
||||
choice = (
|
||||
(await prompt([skip_install_dep])).skip_install_dep ? pm : 'skip'
|
||||
) as PackageManagerChoice;
|
||||
}
|
||||
let choice: PackageManagerChoice;
|
||||
|
||||
await installDeps(choice, data.name);
|
||||
await editMain(data.name);
|
||||
await editDirs(data.main_dir, data.cmds_dir, data.name, data.lang);
|
||||
if (pm === 'both') {
|
||||
choice = (await prompt([which_manager])).manager;
|
||||
} else {
|
||||
choice = ((await prompt([skip_install_dep])).skip_install_dep ? pm : 'skip') as PackageManagerChoice;
|
||||
}
|
||||
|
||||
console.log(`${greenBright('Success, project was initialised!')}`);
|
||||
process.exit(0);
|
||||
await installDeps(choice, data.name);
|
||||
await editMain(data.name);
|
||||
await editDirs(data.main_dir, data.cmds_dir, data.name, data.lang);
|
||||
|
||||
console.log(`${greenBright('Success, project was initialised!')}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/** It initializes git */
|
||||
async function git(data: Data) {
|
||||
const spin = ora({
|
||||
text: 'Initializing git...',
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
const spin = ora({
|
||||
text: 'Initializing git...',
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
|
||||
const exe = await execa('git', ['init', data.name]);
|
||||
|
||||
await wait(300);
|
||||
|
||||
if (!exe || exe?.failed) {
|
||||
spin.fail(
|
||||
`${redBright('Failed')} to initialize git!` +
|
||||
'\nMaybe you should run git init?'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
spin.succeed('Git initialized!');
|
||||
try {
|
||||
await execa('git', ['init', data.name]);
|
||||
await wait(300);
|
||||
spin.succeed('Git initialized!');
|
||||
} catch (error) {
|
||||
spin.fail(`${redBright('Failed')} to initialize git!\nTry to install it at ${underline('https://git-scm.com')}\nSkipping for now.`);
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait for a specified number of milliseconds, then return a promise that resolves to undefined. */
|
||||
async function wait(ms: number) {
|
||||
const wait = (await import('util')).promisify(setTimeout);
|
||||
return wait(ms);
|
||||
const wait = (await import('util')).promisify(setTimeout);
|
||||
return wait(ms);
|
||||
}
|
||||
|
||||
interface Data {
|
||||
name: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
y: boolean;
|
||||
sync: boolean;
|
||||
y: boolean;
|
||||
sync: boolean;
|
||||
}
|
||||
|
||||
interface PromptData {
|
||||
name: string;
|
||||
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
||||
main_dir: string;
|
||||
cmds_dir: string;
|
||||
name: string;
|
||||
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
||||
main_dir: string;
|
||||
cmds_dir: string;
|
||||
}
|
||||
|
||||
@@ -9,32 +9,28 @@ import { fromCwd } from '../utilities/fromCwd.js';
|
||||
* Installs plugins to project
|
||||
*/
|
||||
export async function plugins() {
|
||||
const e: string[] = (await prompt([await pluginsQ()])).list;
|
||||
if (!e) process.exit(1);
|
||||
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')
|
||||
)}`
|
||||
);
|
||||
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 download(url: string) {
|
||||
const data = await fetch(url, { method: 'GET' })
|
||||
.then((res) => res.text())
|
||||
.catch(() => null);
|
||||
const data = await fetch(url, { method: 'GET' })
|
||||
.then((res) => res.text())
|
||||
.catch(() => null);
|
||||
|
||||
if (!data) throw new Error('Download failed! Kindly contact developers');
|
||||
if (!data) throw new Error('Download failed! Kindly contact developers');
|
||||
|
||||
const dir = `${fromCwd('/src/plugins')}`;
|
||||
const filedir = `${process.cwd()}/src/plugins/${url.split('/').pop()}`;
|
||||
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);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(filedir, data);
|
||||
}
|
||||
|
||||
37
src/commands/publish.ts
Normal file
37
src/commands/publish.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { getConfig } from '../utilities/getConfig';
|
||||
import { fork } from 'node:child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
export async function publish(commandDir: string | undefined, args: Partial<PublishArgs>) {
|
||||
const config = await getConfig();
|
||||
// pass in args into the command.
|
||||
const rootPath = new URL('../', import.meta.url),
|
||||
publishScript = new URL('./dist/create-publish.js', rootPath);
|
||||
// assign args.import to empty array if non existent
|
||||
args.import ??= [];
|
||||
|
||||
args.token && console.info('token passed through command line');
|
||||
args.applicationId && console.info('applicationId passed through command line');
|
||||
commandDir && console.info('Publishing with override path: ', commandDir);
|
||||
|
||||
const dotenvLocation = new URL('./node_modules/dotenv/config.js', rootPath),
|
||||
esmLoader = new URL('./node_modules/@esbuild-kit/esm-loader/dist/index.js', rootPath);
|
||||
|
||||
// We dynamically load the create-publish script in a child process so that we can pass the special
|
||||
// loader flag to require typescript files
|
||||
const command = fork(fileURLToPath(publishScript), [], {
|
||||
execArgv: ['--loader', esmLoader.toString(), '-r', fileURLToPath(dotenvLocation), '--no-warnings'],
|
||||
env: {
|
||||
token: args.token ?? '',
|
||||
applicationId: args.applicationId ?? '',
|
||||
},
|
||||
});
|
||||
// send paths object so we dont have to recalculate it in script
|
||||
command.send({ config, preloads: args.import, commandDir });
|
||||
}
|
||||
|
||||
interface PublishArgs {
|
||||
import: string[];
|
||||
token: string;
|
||||
applicationId: string;
|
||||
}
|
||||
17
src/create-publish.d.ts
vendored
Normal file
17
src/create-publish.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface PublishableData {
|
||||
name: string;
|
||||
type: number;
|
||||
description: string;
|
||||
absPath: string;
|
||||
options: Typeable[];
|
||||
}
|
||||
export interface Typeable {
|
||||
type: number;
|
||||
}
|
||||
export interface Config {
|
||||
guildIds?: string[];
|
||||
}
|
||||
export interface PublishableModule {
|
||||
data: PublishableData;
|
||||
config: Config;
|
||||
}
|
||||
241
src/create-publish.mts
Normal file
241
src/create-publish.mts
Normal file
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* This file is meant to be run with the esm / cjs esbuild-kit loader to properly import typescript modules
|
||||
*/
|
||||
|
||||
import { readdir, stat, mkdir, writeFile } from 'fs/promises';
|
||||
import { join, basename, extname, resolve } from 'node:path';
|
||||
import { pathExistsSync } from 'find-up';
|
||||
import assert from 'assert';
|
||||
import { once } from 'node:events';
|
||||
import * as Rest from './rest';
|
||||
import type { sernConfig } from './utilities/getConfig';
|
||||
import type { PublishableData, PublishableModule, Typeable } from './create-publish.d.ts';
|
||||
import { cyanBright, greenBright, redBright } from 'colorette';
|
||||
import ora from 'ora';
|
||||
|
||||
async function deriveFileInfo(dir: string, file: string) {
|
||||
const fullPath = join(dir, file);
|
||||
return {
|
||||
fullPath,
|
||||
fileStats: await stat(fullPath),
|
||||
base: basename(file),
|
||||
};
|
||||
}
|
||||
|
||||
function isSkippable(filename: string) {
|
||||
// empty string is for non extension files (directories)
|
||||
const validExtensions = ['.js', '.cjs', '.mts', '.mjs', '.cts', '.ts', ''];
|
||||
return filename[0] === '!' || !validExtensions.includes(extname(filename));
|
||||
}
|
||||
|
||||
async function* readPaths(dir: string, shouldDebug: boolean): AsyncGenerator<string> {
|
||||
try {
|
||||
const files = await readdir(dir);
|
||||
for (const file of files) {
|
||||
const { fullPath, fileStats, base } = await deriveFileInfo(dir, file);
|
||||
|
||||
if (fileStats.isDirectory()) {
|
||||
// TODO: refactor so that i dont repeat myself for files (line 71)
|
||||
if (isSkippable(base)) {
|
||||
if (shouldDebug) console.info(`ignored directory: ${fullPath}`);
|
||||
} else {
|
||||
yield* readPaths(fullPath, shouldDebug);
|
||||
}
|
||||
} else {
|
||||
if (isSkippable(base)) {
|
||||
if (shouldDebug) console.info(`ignored: ${fullPath}`);
|
||||
} else {
|
||||
yield 'file:///' + fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// recieved sern config
|
||||
const [{ config, preloads, commandDir }] = await once(process, 'message'),
|
||||
{ paths } = config as sernConfig;
|
||||
for (const preload of preloads) {
|
||||
await import('file:///' + resolve(preload));
|
||||
}
|
||||
|
||||
const commandsPath = commandDir ? resolve(commandDir) : resolve(paths.base, paths.commands);
|
||||
const filePaths = readPaths(commandsPath, true);
|
||||
const modules = [];
|
||||
const PUBLISHABLE = 0b1110;
|
||||
|
||||
for await (const absPath of filePaths) {
|
||||
let mod = await import(absPath);
|
||||
let commandModule = mod.default;
|
||||
let config = mod.config;
|
||||
|
||||
if ('default' in commandModule) {
|
||||
commandModule = commandModule.default;
|
||||
}
|
||||
|
||||
if (typeof config === 'function') {
|
||||
config = config(absPath, commandModule);
|
||||
}
|
||||
|
||||
try {
|
||||
commandModule = commandModule.getInstance();
|
||||
} catch {}
|
||||
|
||||
if ((PUBLISHABLE & commandModule.type) != 0) {
|
||||
// assign defaults
|
||||
const filename = basename(absPath);
|
||||
const filenameNoExtension = filename.substring(0, filename.lastIndexOf('.'));
|
||||
commandModule.name ??= filenameNoExtension;
|
||||
commandModule.description ??= '';
|
||||
commandModule.absPath = absPath;
|
||||
modules.push({ commandModule, config });
|
||||
}
|
||||
}
|
||||
|
||||
const cacheDir = resolve('./.sern');
|
||||
if (!pathExistsSync(cacheDir)) {
|
||||
// TODO: add this in verbose flag
|
||||
// console.log('Making .sern directory: ', cacheDir);
|
||||
await mkdir(cacheDir);
|
||||
}
|
||||
|
||||
const optionsTransformer = (ops: Array<Typeable>) => {
|
||||
return ops.map((el) => {
|
||||
if ('command' in el) {
|
||||
const { command, ...rest } = el;
|
||||
return rest;
|
||||
}
|
||||
return el;
|
||||
});
|
||||
};
|
||||
|
||||
const intoApplicationType = (type: number) => {
|
||||
if (type === 3) {
|
||||
return 1;
|
||||
}
|
||||
return Math.log2(type);
|
||||
};
|
||||
|
||||
const makeDescription = (type: number, desc: string) => {
|
||||
if (type !== 1 && desc !== '') {
|
||||
console.warn('Found context menu that has non empty description field. Implictly publishing with empty description');
|
||||
return '';
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
const makePublishData = ({ commandModule, config }: Record<string, Record<string, unknown>>) => {
|
||||
const applicationType = intoApplicationType(commandModule.type as number);
|
||||
return {
|
||||
data: {
|
||||
name: commandModule.name as string,
|
||||
type: applicationType,
|
||||
description: makeDescription(applicationType, commandModule.description as string),
|
||||
absPath: commandModule.absPath as string,
|
||||
options: optionsTransformer((commandModule?.options ?? []) as Typeable[]),
|
||||
dm_permission: config?.dmPermission,
|
||||
default_member_permissions: config?.defaultMemberPermissions ?? null,
|
||||
},
|
||||
config,
|
||||
};
|
||||
};
|
||||
|
||||
// We can use these objects to publish to DAPI
|
||||
const publishableData = modules.map(makePublishData),
|
||||
token = process.env.DISCORD_TOKEN ?? process.env.token,
|
||||
appid = process.env.APPLICATION_ID ?? process.env.applicationId;
|
||||
|
||||
assert(token, 'Could not find a token for this bot in .env or commandline. Do you have DISCORD_TOKEN in env?');
|
||||
assert(appid, 'Could not find an application id for this bot in .env or commandline. Do you have APPLICATION_ID in env?');
|
||||
|
||||
// partition globally published and guilded commands
|
||||
const [globalCommands, guildedCommands] = publishableData.reduce(
|
||||
([globals, guilded], module) => {
|
||||
const isPublishableGlobally = !module.config || !Array.isArray(module.config.guildIds);
|
||||
if (isPublishableGlobally) {
|
||||
return [[module, ...globals], guilded];
|
||||
}
|
||||
return [globals, [module, ...guilded]];
|
||||
},
|
||||
[[], []] as [PublishableModule[], PublishableModule[]]
|
||||
);
|
||||
|
||||
const spin = ora(`Publishing ${cyanBright('Global')} commands`);
|
||||
|
||||
globalCommands.length && spin.start();
|
||||
|
||||
const rest = Rest.create(appid, token);
|
||||
const res = await rest.updateGlobal(globalCommands);
|
||||
|
||||
let globalCommandsResponse: unknown;
|
||||
|
||||
if (res.ok) {
|
||||
spin.succeed(`All ${cyanBright('Global')} commands published`);
|
||||
globalCommandsResponse = await res.json();
|
||||
} else {
|
||||
spin.fail(`Failed to publish global commands [Code: ${redBright(res.status)}]`);
|
||||
if (res.status === 429) {
|
||||
throw Error('Chill out homie, too many requests');
|
||||
}
|
||||
console.error(
|
||||
'errors:',
|
||||
await res.json().then((res) => {
|
||||
const errors = Object.values(res.errors);
|
||||
// @ts-ignore
|
||||
return errors.map((err) => err?.name?._errors);
|
||||
})
|
||||
);
|
||||
console.error(res.statusText);
|
||||
}
|
||||
|
||||
function associateGuildIdsWithData(data: PublishableModule[]): Map<string, PublishableData[]> {
|
||||
const guildIdMap: Map<string, PublishableData[]> = new Map();
|
||||
|
||||
data.forEach((entry) => {
|
||||
const { data, config } = entry;
|
||||
const { guildIds } = config || {};
|
||||
|
||||
if (guildIds) {
|
||||
guildIds.forEach((guildId) => {
|
||||
if (guildIdMap.has(guildId)) {
|
||||
guildIdMap.get(guildId)?.push(data);
|
||||
} else {
|
||||
guildIdMap.set(guildId, [data]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return guildIdMap;
|
||||
}
|
||||
const guildCommandMap = associateGuildIdsWithData(guildedCommands);
|
||||
|
||||
let guildCommandMapResponse = new Map<string, Record<string, unknown>>();
|
||||
|
||||
for (const [guildId, array] of guildCommandMap.entries()) {
|
||||
const spin = ora(`[${cyanBright(guildId)}] Updating commands for guild`);
|
||||
spin.start();
|
||||
|
||||
const response = await rest.putGuildCommands(guildId, array);
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
guildCommandMapResponse.set(guildId, result);
|
||||
spin.succeed(`[${greenBright(guildId)}] Successfully updated commands for guild`);
|
||||
} else {
|
||||
spin.fail(`[${redBright(guildId)}] Failed to update commands for guild, Reason: ${result.message}`);
|
||||
throw Error(result.message);
|
||||
}
|
||||
}
|
||||
const remoteData = {
|
||||
global: globalCommandsResponse,
|
||||
...Object.fromEntries(guildCommandMapResponse),
|
||||
};
|
||||
|
||||
await writeFile(resolve(cacheDir, 'command-data-remote.json'), JSON.stringify(remoteData, null, 4), 'utf8');
|
||||
|
||||
// TODO: add this in a verbose flag
|
||||
// console.info('View json output in ' + resolve(cacheDir, 'command-data-remote.json'));
|
||||
process.exit(0);
|
||||
60
src/index.ts
60
src/index.ts
@@ -3,36 +3,50 @@
|
||||
import { extra } from './commands/extra.js';
|
||||
import { help } from './commands/help.js';
|
||||
import { init } from './commands/init.js';
|
||||
import { publish } from './commands/publish.js';
|
||||
|
||||
import { Command } from 'commander';
|
||||
import { plugins } from './commands/plugins.js';
|
||||
import { version } from './utilities/version.js';
|
||||
import { yellowBright } from 'colorette';
|
||||
export const program = new Command();
|
||||
|
||||
program
|
||||
.name('sern')
|
||||
.description(help())
|
||||
.version(version())
|
||||
.exitOverride(() => process.exit(0));
|
||||
const version: string = '[VI]{{inject}}[/VI]';
|
||||
|
||||
program
|
||||
.command(init.name)
|
||||
.description('Quickest way to scaffold a new project')
|
||||
.option('-y', 'Finishes setup as default')
|
||||
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
||||
.action(init);
|
||||
program //
|
||||
.name('sern')
|
||||
.description(help)
|
||||
.version(`sern CLI v${version}`, '-v, --version')
|
||||
.exitOverride(() => process.exit(0));
|
||||
|
||||
program
|
||||
.command(plugins.name)
|
||||
.description(
|
||||
'Install plugins from https://github.com/sern-handler/awesome-plugins'
|
||||
)
|
||||
.option('-n --name', 'Name of plugin')
|
||||
.action(plugins);
|
||||
program //
|
||||
.command(init.name)
|
||||
.description(`Quickest way to scaffold a new project ${yellowBright('[DEPRECATED]')}`)
|
||||
.option('-y', 'Finishes setup as default')
|
||||
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
||||
.action(init);
|
||||
|
||||
program
|
||||
.command(extra.name)
|
||||
.description('Easy way to add extra things in your sern project')
|
||||
.action(extra);
|
||||
program //
|
||||
.command(plugins.name)
|
||||
.description('Install plugins from https://github.com/sern-handler/awesome-plugins')
|
||||
.option('-n --name', 'Name of plugin')
|
||||
.action(plugins);
|
||||
|
||||
program //
|
||||
.command(extra.name)
|
||||
.description('Easy way to add extra things in your sern project')
|
||||
.action(extra);
|
||||
|
||||
program //
|
||||
.command('commands')
|
||||
.description('Defacto way to manage your slash commands')
|
||||
.addCommand(
|
||||
new Command(publish.name)
|
||||
.description('New way to manage your slash commands')
|
||||
.option('-i, --import [scriptPath...]', 'Prerequire a script to load into publisher')
|
||||
.option('-t, --token [token]')
|
||||
.option('--appId [applicationId]')
|
||||
.argument('[path]', 'path with respect to current working directory that will locate all published files')
|
||||
.action(publish)
|
||||
);
|
||||
|
||||
program.parse();
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import type { PromptObject } from 'prompts';
|
||||
|
||||
export const extraPrompt: PromptObject = {
|
||||
message: 'What extra feature do you want to add?',
|
||||
name: 'extra',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'Dockerfile (TypeScript)',
|
||||
description: 'Dockerfile for TypeScript',
|
||||
value: 'Dockerfile-typescript',
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
title: 'Dockerfile (JavaScript)',
|
||||
description: 'Dockerfile for JavaScript',
|
||||
value: 'Dockerfile-javascript',
|
||||
},
|
||||
],
|
||||
message: 'What extra feature do you want to add?',
|
||||
name: 'extra',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'Dockerfile (TypeScript)',
|
||||
description: 'Dockerfile for TypeScript',
|
||||
value: 'Dockerfile-typescript',
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
title: 'Dockerfile (JavaScript)',
|
||||
description: 'Dockerfile for JavaScript',
|
||||
value: 'Dockerfile-javascript',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -2,95 +2,91 @@ import { blueBright } from 'colorette';
|
||||
import type { PromptObject } from 'prompts';
|
||||
|
||||
export const lang: PromptObject = {
|
||||
message: 'What language do you want the project to be in?',
|
||||
name: 'lang',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'JavaScript',
|
||||
description: 'JS',
|
||||
value: 'javascript',
|
||||
},
|
||||
{
|
||||
title: 'JavaScript (ESM)',
|
||||
description: 'JS',
|
||||
value: 'javascript-esm',
|
||||
},
|
||||
{
|
||||
title: 'TypeScript',
|
||||
description: 'TS - (Recommended)',
|
||||
value: 'typescript',
|
||||
},
|
||||
],
|
||||
message: 'What language do you want the project to be in?',
|
||||
name: 'lang',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'JavaScript',
|
||||
description: 'JS',
|
||||
value: 'javascript',
|
||||
},
|
||||
{
|
||||
title: 'JavaScript (ESM)',
|
||||
description: 'JS',
|
||||
value: 'javascript-esm',
|
||||
},
|
||||
{
|
||||
title: 'TypeScript',
|
||||
description: 'TS - (Recommended)',
|
||||
value: 'typescript',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const main_dir: PromptObject = {
|
||||
message: 'What is the main directory of your project?',
|
||||
name: 'main_dir',
|
||||
type: 'text',
|
||||
initial: 'src',
|
||||
message: 'What is the main directory of your project?',
|
||||
name: 'main_dir',
|
||||
type: 'text',
|
||||
initial: 'src',
|
||||
};
|
||||
|
||||
export const cmds_dir: PromptObject = {
|
||||
message: 'What is the directory of your commands?',
|
||||
name: 'cmds_dir',
|
||||
type: 'text',
|
||||
initial: 'commands',
|
||||
validate: (dir: string) =>
|
||||
dir === 'src' ? 'You can not use src as a directory' : true,
|
||||
message: 'What is the directory of your commands?',
|
||||
name: 'cmds_dir',
|
||||
type: 'text',
|
||||
initial: 'commands',
|
||||
validate: (dir: string) => (dir === 'src' ? 'You can not use src as a directory' : true),
|
||||
};
|
||||
|
||||
export const npmInit: PromptObject = {
|
||||
name: 'npm_init',
|
||||
type: 'confirm',
|
||||
message: `Do you want ${blueBright('me')} to initialize npm?`,
|
||||
initial: true,
|
||||
name: 'npm_init',
|
||||
type: 'confirm',
|
||||
message: `Do you want ${blueBright('me')} to initialize npm?`,
|
||||
initial: true,
|
||||
};
|
||||
|
||||
export const gitInit: PromptObject = {
|
||||
name: 'gitinit',
|
||||
type: 'confirm',
|
||||
message: `Do you want to ${blueBright('me')} to initialize git?`,
|
||||
initial: true,
|
||||
name: 'gitinit',
|
||||
type: 'confirm',
|
||||
message: `Do you want to ${blueBright('me')} to initialize git?`,
|
||||
initial: true,
|
||||
};
|
||||
|
||||
export const which_manager: PromptObject = {
|
||||
message: `Which manager do you want to use?`,
|
||||
name: 'manager',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'NPM',
|
||||
description: 'Default Package Manager',
|
||||
selected: true,
|
||||
value: 'npm',
|
||||
},
|
||||
{
|
||||
title: 'Yarn',
|
||||
description: 'Yarn Package Manager',
|
||||
value: 'yarn',
|
||||
},
|
||||
{
|
||||
title: 'Skip',
|
||||
description: 'Skip selection',
|
||||
value: 'skip',
|
||||
},
|
||||
],
|
||||
message: `Which manager do you want to use?`,
|
||||
name: 'manager',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'NPM',
|
||||
description: 'Default Package Manager',
|
||||
selected: true,
|
||||
value: 'npm',
|
||||
},
|
||||
{
|
||||
title: 'Yarn',
|
||||
description: 'Yarn Package Manager',
|
||||
value: 'yarn',
|
||||
},
|
||||
{
|
||||
title: 'Skip',
|
||||
description: 'Skip selection',
|
||||
value: 'skip',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const skip_install_dep: PromptObject = {
|
||||
name: 'skip_install_dep',
|
||||
type: 'confirm',
|
||||
message: `Do you want ${blueBright('me')} to install dependencies?`,
|
||||
initial: false,
|
||||
name: 'skip_install_dep',
|
||||
type: 'confirm',
|
||||
message: `Do you want ${blueBright('me')} to install dependencies?`,
|
||||
initial: false,
|
||||
};
|
||||
|
||||
export const name: PromptObject = {
|
||||
message: 'What is your project name?',
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
validate: (name: string) =>
|
||||
name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$')
|
||||
? true
|
||||
: 'Invalid name',
|
||||
message: 'What is your project name?',
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
validate: (name: string) => (name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$') ? true : 'Invalid name'),
|
||||
};
|
||||
|
||||
@@ -3,41 +3,40 @@ 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';
|
||||
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 lang = upperCase(await getLang().catch(() => null));
|
||||
|
||||
const link = `https://api.github.com/repos/sern-handler/awesome-plugins/contents/${lang}`;
|
||||
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 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;
|
||||
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,
|
||||
};
|
||||
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;
|
||||
name: string;
|
||||
download_url: string;
|
||||
}
|
||||
|
||||
41
src/rest.ts
Normal file
41
src/rest.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { PublishableModule } from './create-publish.d.ts';
|
||||
|
||||
const baseURL = new URL('https://discord.com/api/v10/applications/');
|
||||
|
||||
const excludedKeys = new Set(['command', 'absPath']);
|
||||
|
||||
const publishablesIntoJson = (ps: PublishableModule[]) =>
|
||||
JSON.stringify(
|
||||
ps.map((module) => module.data),
|
||||
(key, value) => (excludedKeys.has(key) ? undefined : value),
|
||||
4
|
||||
);
|
||||
|
||||
export const create = (appid: string, token: string) => {
|
||||
const globalURL = new URL(`${appid}/commands`, baseURL);
|
||||
const headers = {
|
||||
Authorization: 'Bot ' + token,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
return {
|
||||
updateGlobal: (commands: PublishableModule[]) =>
|
||||
fetch(globalURL, {
|
||||
method: 'PUT',
|
||||
body: publishablesIntoJson(commands),
|
||||
headers,
|
||||
}),
|
||||
getGuildCommands: (id: string) => {
|
||||
const guildCommandURL = new URL(`${appid}/guilds/${id}/commands`, baseURL);
|
||||
return fetch(guildCommandURL, { headers });
|
||||
},
|
||||
|
||||
putGuildCommands: (guildId: string, guildCommand: any) => {
|
||||
const guildCommandURL = new URL(`${appid}/guilds/${guildId}/commands`, baseURL);
|
||||
return fetch(guildCommandURL, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(guildCommand),
|
||||
headers,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -2,8 +2,9 @@ import { mkdir, readFile, writeFile } from 'fs/promises';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath, URL } from 'url';
|
||||
const root = new URL('../../', import.meta.url);
|
||||
|
||||
const templates = new URL('./templates/', root);
|
||||
const sern = new URL('./@sern/', root);
|
||||
const cli = new URL('./cli/', sern);
|
||||
const templates = new URL('./templates/', cli);
|
||||
const extraURL = new URL('./extra/', templates);
|
||||
const extraFolder = fileURLToPath(extraURL);
|
||||
|
||||
@@ -14,19 +15,12 @@ const extraFolder = fileURLToPath(extraURL);
|
||||
* @param location - The location of the file to be created.
|
||||
* @param no_ext - If true, the file will be created without an extension.
|
||||
*/
|
||||
export async function create(
|
||||
name: string,
|
||||
lang: string,
|
||||
location: string,
|
||||
no_ext: boolean
|
||||
) {
|
||||
const file = `${name}.${lang}.sern`;
|
||||
export async function create(name: string, lang: string, location: string, no_ext: boolean) {
|
||||
const file = `${name}.${lang}.sern`;
|
||||
|
||||
const target = no_ext
|
||||
? `${location}/${name}`
|
||||
: `${location}/${name}.${lang}`;
|
||||
const target = no_ext ? `${location}/${name}` : `${location}/${name}.${lang}`;
|
||||
|
||||
return createFile(file, target);
|
||||
return createFile(file, target);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,11 +29,11 @@ export async function create(
|
||||
* @param target - The location of the file to be created.
|
||||
*/
|
||||
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');
|
||||
|
||||
await writeFileRecursive(target, file);
|
||||
await writeFileRecursive(target, file);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,10 +43,10 @@ async function createFile(template: string, target: string) {
|
||||
* @returns A promise that resolves to the result of the writeFile function.
|
||||
*/
|
||||
async function writeFileRecursive(target: string, data: string) {
|
||||
const resolvedTarget = resolve(target);
|
||||
const dir = dirname(resolvedTarget);
|
||||
const resolvedTarget = resolve(target);
|
||||
const dir = dirname(resolvedTarget);
|
||||
|
||||
await mkdir(dir, { recursive: true });
|
||||
await mkdir(dir, { recursive: true });
|
||||
|
||||
return writeFile(resolvedTarget, data);
|
||||
return writeFile(resolvedTarget, data);
|
||||
}
|
||||
|
||||
@@ -8,16 +8,16 @@ import { fromCwd } from './fromCwd.js';
|
||||
* @param name - The name of the project.
|
||||
*/
|
||||
export async function editMain(name: string) {
|
||||
const pjLocation = (await findUp('package.json', {
|
||||
cwd: fromCwd('/' + name),
|
||||
})) as string;
|
||||
const pjLocation = (await findUp('package.json', {
|
||||
cwd: fromCwd('/' + name),
|
||||
})) as string;
|
||||
|
||||
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
||||
if (!output) throw new Error("Can't read your package.json.");
|
||||
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
||||
if (!output) throw new Error("Can't read your package.json.");
|
||||
|
||||
output.name = name;
|
||||
output.name = name;
|
||||
|
||||
return writeFile(pjLocation, JSON.stringify(output, null, 2));
|
||||
return writeFile(pjLocation, JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,55 +29,52 @@ export async function editMain(name: string) {
|
||||
* @param lang - The language you want to use.
|
||||
*/
|
||||
export async function editDirs(
|
||||
srcName: string,
|
||||
cmds_dirName: string,
|
||||
name: string,
|
||||
lang: 'javascript' | 'typescript' | 'javascript-esm' = 'typescript'
|
||||
srcName: string,
|
||||
cmds_dirName: string,
|
||||
name: string,
|
||||
lang: 'javascript' | 'typescript' | 'javascript-esm' = 'typescript'
|
||||
) {
|
||||
const path = (await findUp('src', {
|
||||
cwd: fromCwd(name),
|
||||
type: 'directory',
|
||||
})) as string;
|
||||
const path = (await findUp('src', {
|
||||
cwd: fromCwd(name),
|
||||
type: 'directory',
|
||||
})) as string;
|
||||
|
||||
const ext = lang === 'typescript' ? 'ts' : 'js';
|
||||
const ext = lang === 'typescript' ? 'ts' : 'js';
|
||||
|
||||
const newMainDir = path?.replace('src', srcName);
|
||||
await rename(path, newMainDir);
|
||||
const newMainDir = path?.replace('src', srcName);
|
||||
await rename(path, newMainDir);
|
||||
|
||||
const cmdsPath = (await findUp('commands', {
|
||||
cwd: fromCwd(name, srcName),
|
||||
type: 'directory',
|
||||
})) as string;
|
||||
const cmdsPath = (await findUp('commands', {
|
||||
cwd: fromCwd(name, srcName),
|
||||
type: 'directory',
|
||||
})) as string;
|
||||
|
||||
const index = (await findUp(`index.${ext}`, {
|
||||
cwd: fromCwd(name, srcName),
|
||||
})) as string;
|
||||
const index = (await findUp(`index.${ext}`, {
|
||||
cwd: fromCwd(name, srcName),
|
||||
})) as string;
|
||||
|
||||
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
||||
await rename(cmdsPath, newCmdsPath);
|
||||
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
||||
await rename(cmdsPath, newCmdsPath);
|
||||
|
||||
const tsconfig = await findUp('tsconfig.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
const tsconfig = await findUp('tsconfig.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
|
||||
if (tsconfig) {
|
||||
const output = JSON.parse(await readFile(tsconfig, 'utf8'));
|
||||
if (!output) throw new Error("Can't read your tsconfig.json.");
|
||||
output.compilerOptions.rootDir = srcName;
|
||||
if (tsconfig) {
|
||||
const output = JSON.parse(await readFile(tsconfig, 'utf8'));
|
||||
if (!output) throw new Error("Can't read your tsconfig.json.");
|
||||
output.compilerOptions.rootDir = srcName;
|
||||
|
||||
await 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');
|
||||
|
||||
const oldfold = ext === 'ts' ? 'dist' : 'src';
|
||||
const newfold = ext === 'ts' ? 'dist' : srcName;
|
||||
const oldfold = ext === 'ts' ? 'dist' : 'src';
|
||||
const newfold = ext === 'ts' ? 'dist' : srcName;
|
||||
|
||||
const regex = new RegExp(`commands: '${oldfold}/commands'`);
|
||||
const edit = output.replace(
|
||||
regex,
|
||||
`commands: '${newfold}/${cmds_dirName}'`
|
||||
);
|
||||
const regex = new RegExp(`commands: '${oldfold}/commands'`);
|
||||
const edit = output.replace(regex, `commands: '${newfold}/${cmds_dirName}'`);
|
||||
|
||||
return writeFile(index, edit);
|
||||
return writeFile(index, edit);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import path from 'path';
|
||||
|
||||
export function fromCwd(...dir: string[]) {
|
||||
return path.join(...[process.cwd(), ...dir]);
|
||||
return path.join(...[process.cwd(), ...dir]);
|
||||
}
|
||||
|
||||
23
src/utilities/getConfig.ts
Normal file
23
src/utilities/getConfig.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { findUp } from 'find-up';
|
||||
import assert from 'node:assert';
|
||||
export async function getConfig(): Promise<sernConfig> {
|
||||
const sernLocation = await findUp('sern.config.json');
|
||||
assert(sernLocation, "Can't find sern.config.json");
|
||||
|
||||
const output = JSON.parse(await readFile(sernLocation, 'utf8')) as sernConfig;
|
||||
|
||||
assert(output, "Can't read your sern.config.json.");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
export interface sernConfig {
|
||||
language: 'typescript' | 'javascript';
|
||||
defaultPrefix?: string;
|
||||
paths: {
|
||||
base: string;
|
||||
commands: string;
|
||||
events?: string;
|
||||
};
|
||||
}
|
||||
@@ -6,13 +6,13 @@ import { readFile } from 'node:fs/promises';
|
||||
* @returns The language of the project.
|
||||
*/
|
||||
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");
|
||||
|
||||
const output = JSON.parse(await readFile(sernLocation, 'utf8'));
|
||||
const output = JSON.parse(await readFile(sernLocation, 'utf8'));
|
||||
|
||||
if (!output) throw new Error("Can't read your sern.config.json.");
|
||||
if (!output) throw new Error("Can't read your sern.config.json.");
|
||||
|
||||
return output.language;
|
||||
return output.language;
|
||||
}
|
||||
|
||||
@@ -13,33 +13,34 @@ import type { PackageManagerChoice } from './types';
|
||||
* @param name - The name of the project
|
||||
*/
|
||||
export async function installDeps(choice: PackageManagerChoice, name: string) {
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
|
||||
const output = JSON.parse(await readFile(pkg, 'utf8'));
|
||||
if (!output) throw new Error("Can't read file.");
|
||||
const output = JSON.parse(await readFile(pkg, 'utf8'));
|
||||
if (!output) throw new Error("Can't read file.");
|
||||
|
||||
const deps = output.dependencies;
|
||||
if (!deps) throw new Error("Can't find dependencies.");
|
||||
const deps = output.dependencies;
|
||||
if (!deps) throw new Error("Can't find dependencies.");
|
||||
|
||||
if (choice === 'skip') {
|
||||
return console.log('Dependency installation skipped...');
|
||||
}
|
||||
if (choice === 'skip') {
|
||||
return console.log('Dependency installation skipped...');
|
||||
}
|
||||
|
||||
const spin = ora({
|
||||
text: `Installing dependencies...`,
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
const spin = ora({
|
||||
text: `Installing dependencies...`,
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
|
||||
const result = await execa(choice, ['install'], {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
}).catch(() => null);
|
||||
if (!result || result?.failed) {
|
||||
spin.fail(`${redBright('Failed')} to install dependencies!`);
|
||||
process.exit(1);
|
||||
} else spin.succeed(`Dependencies installed!`);
|
||||
const result = await execa(choice, ['install'], {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
}).catch(() => null);
|
||||
|
||||
if (!result || result?.failed) {
|
||||
spin.fail(`${redBright('Failed')} to install dependencies!`);
|
||||
process.exit(1);
|
||||
} else spin.succeed(`Dependencies installed!`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,12 +49,14 @@ export async function installDeps(choice: PackageManagerChoice, name: string) {
|
||||
* @param name - The name of the project
|
||||
*/
|
||||
export async function cloneRepo(lang: string, name: string) {
|
||||
await execa('git', [
|
||||
'clone',
|
||||
`https://github.com/sern-handler/templates.git`,
|
||||
]);
|
||||
copyRecursiveSync(`templates/templates/${lang}`, name);
|
||||
fs.rmSync(`templates/`, { recursive: true, force: true });
|
||||
try {
|
||||
await execa('git', ['clone', `https://github.com/sern-handler/templates.git`]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,21 +67,18 @@ export async function cloneRepo(lang: string, name: string) {
|
||||
* @param dest - The destination folder where the files will be copied to.
|
||||
*/
|
||||
export function copyRecursiveSync(src: string, dest: string) {
|
||||
const exists = fs.existsSync(src);
|
||||
const exists = fs.existsSync(src);
|
||||
|
||||
const stats = (exists && fs.statSync(src)) as fs.Stats;
|
||||
const stats = (exists && fs.statSync(src)) as fs.Stats;
|
||||
|
||||
const isDirectory = exists && stats.isDirectory();
|
||||
if (isDirectory) {
|
||||
fs.mkdirSync(dest);
|
||||
const isDirectory = exists && stats.isDirectory();
|
||||
if (isDirectory) {
|
||||
fs.mkdirSync(dest);
|
||||
|
||||
fs.readdirSync(src).forEach(function (childItemName) {
|
||||
copyRecursiveSync(
|
||||
path.join(src, childItemName),
|
||||
path.join(dest, childItemName)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
fs.readdirSync(src).forEach(function (childItemName) {
|
||||
copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
|
||||
});
|
||||
} else {
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,21 +5,21 @@ import { execa } from 'execa';
|
||||
* @returns A promise that resolves to a string.
|
||||
*/
|
||||
export async function npm() {
|
||||
const npm = await execa('npm', ['-v']).catch(() => null);
|
||||
const npm_version = npm?.stdout;
|
||||
const npm = await execa('npm', ['-v']).catch(() => null);
|
||||
const npm_version = npm?.stdout;
|
||||
|
||||
const yarn = await execa('yarn', ['-v']).catch(() => null);
|
||||
const yarn_version = yarn?.stdout;
|
||||
const yarn = await execa('yarn', ['-v']).catch(() => null);
|
||||
const yarn_version = yarn?.stdout;
|
||||
|
||||
if (npm_version && !yarn_version) {
|
||||
return 'npm';
|
||||
}
|
||||
if (npm_version && !yarn_version) {
|
||||
return 'npm';
|
||||
}
|
||||
|
||||
if (!npm_version && yarn_version) {
|
||||
return 'yarn';
|
||||
}
|
||||
if (!npm_version && yarn_version) {
|
||||
return 'yarn';
|
||||
}
|
||||
|
||||
if (npm_version && yarn_version) {
|
||||
return 'both';
|
||||
}
|
||||
if (npm_version && yarn_version) {
|
||||
return 'both';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"importsNotUsedAsValues": "error",
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"outDir": "dist",
|
||||
"rootDir": ".",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
}
|
||||
|
||||
18
tsup.config.ts
Normal file
18
tsup.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
import { esbuildPluginVersionInjector } from 'esbuild-plugin-version-injector';
|
||||
const shared = {
|
||||
entry: ['src/index.ts', 'src/create-publish.mts'],
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
};
|
||||
export default defineConfig({
|
||||
format: 'esm',
|
||||
target: 'node18',
|
||||
tsconfig: './tsconfig.json',
|
||||
outDir: './dist',
|
||||
treeshake: true,
|
||||
esbuildPlugins: [esbuildPluginVersionInjector()],
|
||||
platform: 'node',
|
||||
splitting: false,
|
||||
...shared,
|
||||
});
|
||||
Reference in New Issue
Block a user