mirror of
https://github.com/sern-handler/cli
synced 2026-06-13 11:22:24 +00:00
Compare commits
10 Commits
plugin-ver
...
v0.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f12d541dfe | ||
|
|
642bf11608 | ||
|
|
827ffb7ad9 | ||
|
|
2348e3e9ab | ||
|
|
14df4a9b65 | ||
|
|
4bc7d1b081 | ||
|
|
acbec3e733 | ||
|
|
dbc3154101 | ||
|
|
7252c533bc | ||
|
|
dce78c0945 |
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"tabWidth": 4,
|
"tabWidth": 4,
|
||||||
"useTabs": true,
|
"useTabs": false,
|
||||||
"singleQuote": true
|
"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.
|
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)
|
## [0.5.0](https://github.com/sern-handler/cli/compare/v0.4.2...v0.5.0) (2022-09-16)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10523
package-lock.json
generated
10523
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
116
package.json
116
package.json
@@ -1,58 +1,62 @@
|
|||||||
{
|
{
|
||||||
"name": "@sern/cli",
|
"name": "@sern/cli",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"description": "Official CLI for @sern/handler",
|
"description": "Official CLI for @sern/handler",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sern": "./dist/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",
|
"build": "tsup",
|
||||||
"watch": "tsc --watch"
|
"watch": "tsup --watch"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/sern-handler/cli.git"
|
"url": "git+https://github.com/sern-handler/cli.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cli",
|
"cli",
|
||||||
"discord",
|
"discord",
|
||||||
"discord.js",
|
"discord.js",
|
||||||
"sern",
|
"sern",
|
||||||
"sern-handler"
|
"sern-handler"
|
||||||
],
|
],
|
||||||
"author": "EvolutionX",
|
"author": "EvolutionX",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"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",
|
"@esbuild-kit/cjs-loader": "^2.4.2",
|
||||||
"commander": "^9.3.0",
|
"@esbuild-kit/esm-loader": "^2.5.5",
|
||||||
"execa": "^6.1.0",
|
"colorette": "2.0.20",
|
||||||
"find-up": "6.3.0",
|
"commander": "11.0.0",
|
||||||
"ora": "^6.1.0",
|
"dotenv": "^16.3.1",
|
||||||
"prompts": "2.4.2",
|
"execa": "7.1.1",
|
||||||
"undici": "^5.6.1"
|
"find-up": "6.3.0",
|
||||||
},
|
"ora": "6.3.1",
|
||||||
"devDependencies": {
|
"prompts": "2.4.2",
|
||||||
"@favware/npm-deprecate": "1.0.7",
|
"undici": "5.22.1"
|
||||||
"@types/prompts": "2.4.3",
|
},
|
||||||
"esbuild-plugin-version-injector": "^1.0.3",
|
"devDependencies": {
|
||||||
"prettier": "2.8.4",
|
"@babel/parser": "^7.22.5",
|
||||||
"tsup": "^6.6.3",
|
"@favware/npm-deprecate": "1.0.7",
|
||||||
"typescript": "4.9.5"
|
"@types/prompts": "2.4.4",
|
||||||
},
|
"esbuild-plugin-version-injector": "1.1.0",
|
||||||
"engines": {
|
"prettier": "2.8.8",
|
||||||
"node": ">= 16.10.x"
|
"tsup": "6.7.0",
|
||||||
},
|
"typescript": "5.1.3"
|
||||||
"publishConfig": {
|
},
|
||||||
"registry": "https://registry.npmjs.org/",
|
"engines": {
|
||||||
"access": "public"
|
"node": ">= 18.16.x"
|
||||||
}
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": ["config:base"],
|
"extends": ["config:base", "group:allNonMajor"],
|
||||||
"major": {
|
"major": {
|
||||||
"dependencyDashboardApproval": true
|
"dependencyDashboardApproval": true
|
||||||
},
|
},
|
||||||
"schedule": ["every weekend"],
|
"schedule": ["every weekend"],
|
||||||
"lockFileMaintenance": {
|
"lockFileMaintenance": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
"matchUpdateTypes": ["minor", "patch"],
|
||||||
"matchCurrentVersion": "!/^0/"
|
"matchCurrentVersion": "!/^0/"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { extraPrompt } from '../prompts/extra.js';
|
|||||||
import { create } from '../utilities/create.js';
|
import { create } from '../utilities/create.js';
|
||||||
|
|
||||||
export async function extra() {
|
export async function extra() {
|
||||||
const extra = await prompt([extraPrompt]);
|
const extra = await prompt([extraPrompt]);
|
||||||
|
|
||||||
if (Object.keys(extra).length < 1) process.exit(1);
|
if (Object.keys(extra).length < 1) process.exit(1);
|
||||||
const lang = extra.extra.includes('typescript') ? 'TS' : 'JS';
|
const lang = extra.extra.includes('typescript') ? 'TS' : 'JS';
|
||||||
await create(extra.extra.split('-')[0], lang, process.cwd(), true);
|
await create(extra.extra.split('-')[0], lang, process.cwd(), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
import { cyanBright, green, magentaBright } from 'colorette';
|
import { cyanBright, green, magentaBright } from 'colorette';
|
||||||
|
|
||||||
export function help() {
|
export const help = `
|
||||||
return `
|
|
||||||
___ ___ _ __ _ __
|
___ ___ _ __ _ __
|
||||||
/ __|/ _ \\ '__| '_ \\
|
/ __|/ _ \\ '__| '_ \\
|
||||||
\\__ \\ __/ | | | | |
|
\\__ \\ __/ | | | | |
|
||||||
|___/\\___|_| |_| |_|
|
|___/\\___|_| |_| |_|
|
||||||
|
|
||||||
Welcome!
|
Welcome!
|
||||||
If you're new to ${cyanBright('sern')}, run ${magentaBright(
|
If you're new to ${cyanBright('sern')}, run ${magentaBright('npm create @sern/bot')} for an interactive setup to your new bot project!
|
||||||
'sern init'
|
|
||||||
)} for an interactive setup to your new bot project!
|
|
||||||
|
|
||||||
${green(
|
${green(`If you have any ideas, suggestions, bug reports, kindly join our support server: https://sern.dev/discord`)}`;
|
||||||
`If you have any ideas, suggestions, bug reports, kindly join our support server: https://sern.dev/discord`
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
import { greenBright, redBright, underline } from 'colorette';
|
import { greenBright, redBright, underline, 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 ora from 'ora';
|
||||||
import prompt from 'prompts';
|
import prompt from 'prompts';
|
||||||
import {
|
import { cmds_dir, gitInit, lang, main_dir, name, skip_install_dep, which_manager } from '../prompts/init.js';
|
||||||
cmds_dir,
|
|
||||||
gitInit,
|
|
||||||
lang,
|
|
||||||
main_dir,
|
|
||||||
name,
|
|
||||||
skip_install_dep,
|
|
||||||
which_manager,
|
|
||||||
} from '../prompts/init.js';
|
|
||||||
|
|
||||||
import { writeFile } from 'fs/promises';
|
import { writeFile } from 'fs/promises';
|
||||||
import { editDirs, editMain } from '../utilities/edits.js';
|
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 { npm } from '../utilities/npm.js';
|
||||||
import type { PackageManagerChoice } from '../utilities/types.js';
|
import type { PackageManagerChoice } from '../utilities/types.js';
|
||||||
|
|
||||||
|
/** @deprecated Use npm create instead */
|
||||||
export async function init(flags: Flags) {
|
export async function init(flags: Flags) {
|
||||||
let data: PromptData;
|
console.log(`${yellowBright('[WARN]:')} This command is deprecated, use ${greenBright('npm create @sern/bot')} instead`);
|
||||||
let git_init = true; // the default;
|
|
||||||
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
|
||||||
|
|
||||||
if (flags.y) {
|
let data: PromptData;
|
||||||
const projectName = await prompt([name]);
|
let git_init = true; // the default;
|
||||||
git_init = true;
|
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
||||||
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 language = data.lang === 'javascript-esm' ? 'javascript' : data.lang;
|
if (flags.y) {
|
||||||
const config = {
|
const projectName = await prompt([name]);
|
||||||
language,
|
git_init = true;
|
||||||
paths: {
|
data = {
|
||||||
base: data.main_dir,
|
name: projectName.name,
|
||||||
commands: data.cmds_dir,
|
lang: 'typescript',
|
||||||
},
|
main_dir: 'src',
|
||||||
};
|
cmds_dir: 'commands',
|
||||||
const file = JSON.stringify(config, null, 2);
|
};
|
||||||
|
} 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 language = data.lang === 'javascript-esm' ? 'javascript' : data.lang;
|
||||||
const receivedData = Object.keys(data).length;
|
const config = {
|
||||||
const incompleteDataCondition = receivedData < requiredData;
|
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', {
|
if (!flags.sync) await cloneRepo(data.lang, data.name);
|
||||||
cwd: process.cwd() + '/' + 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) {
|
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
||||||
console.log('Project was successfully synced!');
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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') {
|
let choice: PackageManagerChoice;
|
||||||
choice = (await prompt([which_manager])).manager;
|
|
||||||
} else {
|
|
||||||
choice = (
|
|
||||||
(await prompt([skip_install_dep])).skip_install_dep ? pm : 'skip'
|
|
||||||
) as PackageManagerChoice;
|
|
||||||
}
|
|
||||||
|
|
||||||
await installDeps(choice, data.name);
|
if (pm === 'both') {
|
||||||
await editMain(data.name);
|
choice = (await prompt([which_manager])).manager;
|
||||||
await editDirs(data.main_dir, data.cmds_dir, data.name, data.lang);
|
} else {
|
||||||
|
choice = ((await prompt([skip_install_dep])).skip_install_dep ? pm : 'skip') as PackageManagerChoice;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`${greenBright('Success, project was initialised!')}`);
|
await installDeps(choice, data.name);
|
||||||
process.exit(0);
|
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 */
|
/** It initializes git */
|
||||||
async function git(data: Data) {
|
async function git(data: Data) {
|
||||||
const spin = ora({
|
const spin = ora({
|
||||||
text: 'Initializing git...',
|
text: 'Initializing git...',
|
||||||
spinner: 'aesthetic',
|
spinner: 'aesthetic',
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await execa('git', ['init', data.name]);
|
await execa('git', ['init', data.name]);
|
||||||
await wait(300);
|
await wait(300);
|
||||||
spin.succeed('Git initialized!');
|
spin.succeed('Git initialized!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
spin.fail(
|
spin.fail(`${redBright('Failed')} to initialize git!\nTry to install it at ${underline('https://git-scm.com')}\nSkipping for now.`);
|
||||||
`${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. */
|
/** Wait for a specified number of milliseconds, then return a promise that resolves to undefined. */
|
||||||
async function wait(ms: number) {
|
async function wait(ms: number) {
|
||||||
const wait = (await import('util')).promisify(setTimeout);
|
const wait = (await import('util')).promisify(setTimeout);
|
||||||
return wait(ms);
|
return wait(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Data {
|
interface Data {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Flags {
|
interface Flags {
|
||||||
y: boolean;
|
y: boolean;
|
||||||
sync: boolean;
|
sync: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PromptData {
|
interface PromptData {
|
||||||
name: string;
|
name: string;
|
||||||
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
||||||
main_dir: string;
|
main_dir: string;
|
||||||
cmds_dir: string;
|
cmds_dir: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,32 +9,28 @@ import { fromCwd } from '../utilities/fromCwd.js';
|
|||||||
* Installs plugins to project
|
* Installs plugins to project
|
||||||
*/
|
*/
|
||||||
export async function plugins() {
|
export async function plugins() {
|
||||||
const e: string[] = (await prompt([await pluginsQ()])).list;
|
const e: string[] = (await prompt([await pluginsQ()])).list;
|
||||||
if (!e) process.exit(1);
|
if (!e) process.exit(1);
|
||||||
|
|
||||||
for await (const url of e) {
|
for await (const url of e) {
|
||||||
await download(url);
|
await download(url);
|
||||||
}
|
}
|
||||||
const pluginNames = e.map((e) => e.split('/').pop());
|
const pluginNames = e.map((e) => e.split('/').pop());
|
||||||
console.log(
|
console.log(`Successfully downloaded plugin(s):\n${greenBright(pluginNames.join('\n'))}`);
|
||||||
`Successfully downloaded plugin(s):\n${greenBright(
|
|
||||||
pluginNames.join('\n')
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function download(url: string) {
|
async function download(url: string) {
|
||||||
const data = await fetch(url, { method: 'GET' })
|
const data = await fetch(url, { method: 'GET' })
|
||||||
.then((res) => res.text())
|
.then((res) => res.text())
|
||||||
.catch(() => null);
|
.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 dir = `${fromCwd('/src/plugins')}`;
|
||||||
const filedir = `${process.cwd()}/src/plugins/${url.split('/').pop()}`;
|
const filedir = `${process.cwd()}/src/plugins/${url.split('/').pop()}`;
|
||||||
|
|
||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
fs.writeFileSync(filedir, data);
|
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);
|
||||||
58
src/index.ts
58
src/index.ts
@@ -3,36 +3,50 @@
|
|||||||
import { extra } from './commands/extra.js';
|
import { extra } from './commands/extra.js';
|
||||||
import { help } from './commands/help.js';
|
import { help } from './commands/help.js';
|
||||||
import { init } from './commands/init.js';
|
import { init } from './commands/init.js';
|
||||||
|
import { publish } from './commands/publish.js';
|
||||||
|
|
||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import { plugins } from './commands/plugins.js';
|
import { plugins } from './commands/plugins.js';
|
||||||
|
import { yellowBright } from 'colorette';
|
||||||
export const program = new Command();
|
export const program = new Command();
|
||||||
|
|
||||||
const version: string = '[VI]{{inject}}[/VI]';
|
const version: string = '[VI]{{inject}}[/VI]';
|
||||||
program
|
|
||||||
.name('sern')
|
|
||||||
.description(help())
|
|
||||||
.version(`sern CLI v${version}`)
|
|
||||||
.exitOverride(() => process.exit(0));
|
|
||||||
|
|
||||||
program
|
program //
|
||||||
.command(init.name)
|
.name('sern')
|
||||||
.description('Quickest way to scaffold a new project')
|
.description(help)
|
||||||
.option('-y', 'Finishes setup as default')
|
.version(`sern CLI v${version}`, '-v, --version')
|
||||||
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
.exitOverride(() => process.exit(0));
|
||||||
.action(init);
|
|
||||||
|
|
||||||
program
|
program //
|
||||||
.command(plugins.name)
|
.command(init.name)
|
||||||
.description(
|
.description(`Quickest way to scaffold a new project ${yellowBright('[DEPRECATED]')}`)
|
||||||
'Install plugins from https://github.com/sern-handler/awesome-plugins'
|
.option('-y', 'Finishes setup as default')
|
||||||
)
|
.option('-s, --sync', 'Syncs the project and generates sern.config.json')
|
||||||
.option('-n --name', 'Name of plugin')
|
.action(init);
|
||||||
.action(plugins);
|
|
||||||
|
|
||||||
program
|
program //
|
||||||
.command(extra.name)
|
.command(plugins.name)
|
||||||
.description('Easy way to add extra things in your sern project')
|
.description('Install plugins from https://github.com/sern-handler/awesome-plugins')
|
||||||
.action(extra);
|
.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();
|
program.parse();
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import type { PromptObject } from 'prompts';
|
import type { PromptObject } from 'prompts';
|
||||||
|
|
||||||
export const extraPrompt: PromptObject = {
|
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',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
title: 'Dockerfile (TypeScript)',
|
title: 'Dockerfile (TypeScript)',
|
||||||
description: 'Dockerfile for TypeScript',
|
description: 'Dockerfile for TypeScript',
|
||||||
value: 'Dockerfile-typescript',
|
value: 'Dockerfile-typescript',
|
||||||
selected: true,
|
selected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Dockerfile (JavaScript)',
|
title: 'Dockerfile (JavaScript)',
|
||||||
description: 'Dockerfile for JavaScript',
|
description: 'Dockerfile for JavaScript',
|
||||||
value: 'Dockerfile-javascript',
|
value: 'Dockerfile-javascript',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,95 +2,91 @@ import { blueBright } from 'colorette';
|
|||||||
import type { PromptObject } from 'prompts';
|
import type { PromptObject } from 'prompts';
|
||||||
|
|
||||||
export const lang: PromptObject = {
|
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',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
title: 'JavaScript',
|
title: 'JavaScript',
|
||||||
description: 'JS',
|
description: 'JS',
|
||||||
value: 'javascript',
|
value: 'javascript',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'JavaScript (ESM)',
|
title: 'JavaScript (ESM)',
|
||||||
description: 'JS',
|
description: 'JS',
|
||||||
value: 'javascript-esm',
|
value: 'javascript-esm',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'TypeScript',
|
title: 'TypeScript',
|
||||||
description: 'TS - (Recommended)',
|
description: 'TS - (Recommended)',
|
||||||
value: 'typescript',
|
value: 'typescript',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const main_dir: PromptObject = {
|
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: PromptObject = {
|
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: (dir: string) =>
|
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 = {
|
export const npmInit: PromptObject = {
|
||||||
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: PromptObject = {
|
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: PromptObject = {
|
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',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
title: 'NPM',
|
title: 'NPM',
|
||||||
description: 'Default Package Manager',
|
description: 'Default Package Manager',
|
||||||
selected: true,
|
selected: true,
|
||||||
value: 'npm',
|
value: 'npm',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Yarn',
|
title: 'Yarn',
|
||||||
description: 'Yarn Package Manager',
|
description: 'Yarn Package Manager',
|
||||||
value: 'yarn',
|
value: 'yarn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Skip',
|
title: 'Skip',
|
||||||
description: 'Skip selection',
|
description: 'Skip selection',
|
||||||
value: 'skip',
|
value: 'skip',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const skip_install_dep: PromptObject = {
|
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 = {
|
export const name: PromptObject = {
|
||||||
message: 'What is your project name?',
|
message: 'What is your project name?',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
validate: (name: string) =>
|
validate: (name: string) => (name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$') ? true : 'Invalid name'),
|
||||||
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';
|
import { getLang } from '../utilities/getLang.js';
|
||||||
|
|
||||||
function upperCase(string: string | null) {
|
function upperCase(string: string | null) {
|
||||||
if (string === null) {
|
if (string === null) {
|
||||||
console.error('Lang property not found!');
|
console.error('Lang property not found!');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
return string === 'typescript' ? 'TypeScript' : 'JavaScript';
|
return string === 'typescript' ? 'TypeScript' : 'JavaScript';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gimmechoices(): Promise<Choice[]> {
|
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);
|
const resp = await fetch(link).catch(() => null);
|
||||||
if (!resp)
|
if (!resp) return [{ title: 'No plugins found!', value: '', disabled: true }];
|
||||||
return [{ title: 'No plugins found!', value: '', disabled: true }];
|
|
||||||
|
|
||||||
const data = (await resp.json()) as Data[];
|
const data = (await resp.json()) as Data[];
|
||||||
const choices = data.map((e) => ({
|
const choices = data.map((e) => ({
|
||||||
title: e.name,
|
title: e.name,
|
||||||
value: e.download_url,
|
value: e.download_url,
|
||||||
}));
|
}));
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pluginsQ(): Promise<PromptObject> {
|
export async function pluginsQ(): Promise<PromptObject> {
|
||||||
return {
|
return {
|
||||||
name: 'list',
|
name: 'list',
|
||||||
type: 'autocompleteMultiselect',
|
type: 'autocompleteMultiselect',
|
||||||
message: 'What plugins do you want to install?',
|
message: 'What plugins do you want to install?',
|
||||||
choices: await gimmechoices(),
|
choices: await gimmechoices(),
|
||||||
min: 1,
|
min: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Data {
|
interface Data {
|
||||||
name: string;
|
name: string;
|
||||||
download_url: 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 { dirname, resolve } from 'node:path';
|
||||||
import { fileURLToPath, URL } from 'url';
|
import { fileURLToPath, URL } from 'url';
|
||||||
const root = new URL('../../', import.meta.url);
|
const root = new URL('../../', import.meta.url);
|
||||||
|
const sern = new URL('./@sern/', root);
|
||||||
const templates = new URL('./templates/', root);
|
const cli = new URL('./cli/', sern);
|
||||||
|
const templates = new URL('./templates/', cli);
|
||||||
const extraURL = new URL('./extra/', templates);
|
const extraURL = new URL('./extra/', templates);
|
||||||
const extraFolder = fileURLToPath(extraURL);
|
const extraFolder = fileURLToPath(extraURL);
|
||||||
|
|
||||||
@@ -14,19 +15,12 @@ const extraFolder = fileURLToPath(extraURL);
|
|||||||
* @param location - The location of the file to be created.
|
* @param location - The location of the file to be created.
|
||||||
* @param 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.
|
||||||
*/
|
*/
|
||||||
export async function create(
|
export async function create(name: string, lang: string, location: string, no_ext: boolean) {
|
||||||
name: string,
|
const file = `${name}.${lang}.sern`;
|
||||||
lang: string,
|
|
||||||
location: string,
|
|
||||||
no_ext: boolean
|
|
||||||
) {
|
|
||||||
const file = `${name}.${lang}.sern`;
|
|
||||||
|
|
||||||
const target = no_ext
|
const target = no_ext ? `${location}/${name}` : `${location}/${name}.${lang}`;
|
||||||
? `${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.
|
* @param target - The location of the file to be created.
|
||||||
*/
|
*/
|
||||||
async function createFile(template: string, target: string) {
|
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.
|
* @returns A promise that resolves to the result of the writeFile function.
|
||||||
*/
|
*/
|
||||||
async function writeFileRecursive(target: string, data: string) {
|
async function writeFileRecursive(target: string, data: string) {
|
||||||
const resolvedTarget = resolve(target);
|
const resolvedTarget = resolve(target);
|
||||||
const dir = dirname(resolvedTarget);
|
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.
|
* @param name - The name of the project.
|
||||||
*/
|
*/
|
||||||
export async function editMain(name: string) {
|
export async function editMain(name: string) {
|
||||||
const pjLocation = (await findUp('package.json', {
|
const pjLocation = (await findUp('package.json', {
|
||||||
cwd: fromCwd('/' + name),
|
cwd: fromCwd('/' + name),
|
||||||
})) as string;
|
})) 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.");
|
||||||
|
|
||||||
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.
|
* @param lang - The language you want to use.
|
||||||
*/
|
*/
|
||||||
export async function editDirs(
|
export async function editDirs(
|
||||||
srcName: string,
|
srcName: string,
|
||||||
cmds_dirName: string,
|
cmds_dirName: string,
|
||||||
name: string,
|
name: string,
|
||||||
lang: 'javascript' | 'typescript' | 'javascript-esm' = 'typescript'
|
lang: 'javascript' | 'typescript' | 'javascript-esm' = 'typescript'
|
||||||
) {
|
) {
|
||||||
const path = (await findUp('src', {
|
const path = (await findUp('src', {
|
||||||
cwd: fromCwd(name),
|
cwd: fromCwd(name),
|
||||||
type: 'directory',
|
type: 'directory',
|
||||||
})) as string;
|
})) 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: fromCwd(name, srcName),
|
cwd: fromCwd(name, srcName),
|
||||||
type: 'directory',
|
type: 'directory',
|
||||||
})) as string;
|
})) as string;
|
||||||
|
|
||||||
const index = (await findUp(`index.${ext}`, {
|
const index = (await findUp(`index.${ext}`, {
|
||||||
cwd: fromCwd(name, srcName),
|
cwd: fromCwd(name, srcName),
|
||||||
})) as string;
|
})) as string;
|
||||||
|
|
||||||
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
const newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
||||||
await rename(cmdsPath, newCmdsPath);
|
await rename(cmdsPath, newCmdsPath);
|
||||||
|
|
||||||
const tsconfig = await findUp('tsconfig.json', {
|
const tsconfig = await findUp('tsconfig.json', {
|
||||||
cwd: process.cwd() + '/' + name,
|
cwd: process.cwd() + '/' + name,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tsconfig) {
|
if (tsconfig) {
|
||||||
const output = JSON.parse(await readFile(tsconfig, 'utf8'));
|
const output = JSON.parse(await readFile(tsconfig, 'utf8'));
|
||||||
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;
|
||||||
|
|
||||||
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 oldfold = ext === 'ts' ? 'dist' : 'src';
|
||||||
const newfold = ext === 'ts' ? 'dist' : srcName;
|
const newfold = ext === 'ts' ? 'dist' : srcName;
|
||||||
|
|
||||||
const regex = new RegExp(`commands: '${oldfold}/commands'`);
|
const regex = new RegExp(`commands: '${oldfold}/commands'`);
|
||||||
const edit = output.replace(
|
const edit = output.replace(regex, `commands: '${newfold}/${cmds_dirName}'`);
|
||||||
regex,
|
|
||||||
`commands: '${newfold}/${cmds_dirName}'`
|
|
||||||
);
|
|
||||||
|
|
||||||
return writeFile(index, edit);
|
return writeFile(index, edit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
export function fromCwd(...dir: string[]) {
|
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.
|
* @returns The language of the project.
|
||||||
*/
|
*/
|
||||||
export async function getLang(): Promise<'typescript' | 'javascript'> {
|
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,34 +13,34 @@ import type { PackageManagerChoice } from './types';
|
|||||||
* @param name - The name of the project
|
* @param name - The name of the project
|
||||||
*/
|
*/
|
||||||
export async function installDeps(choice: PackageManagerChoice, name: string) {
|
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,
|
||||||
});
|
});
|
||||||
if (!pkg) throw new Error('No package.json found!');
|
if (!pkg) throw new Error('No package.json found!');
|
||||||
|
|
||||||
const output = JSON.parse(await readFile(pkg, 'utf8'));
|
const output = JSON.parse(await readFile(pkg, 'utf8'));
|
||||||
if (!output) throw new Error("Can't read file.");
|
if (!output) throw new Error("Can't read file.");
|
||||||
|
|
||||||
const deps = output.dependencies;
|
const deps = output.dependencies;
|
||||||
if (!deps) throw new Error("Can't find dependencies.");
|
if (!deps) throw new Error("Can't find dependencies.");
|
||||||
|
|
||||||
if (choice === 'skip') {
|
if (choice === 'skip') {
|
||||||
return console.log('Dependency installation skipped...');
|
return console.log('Dependency installation skipped...');
|
||||||
}
|
}
|
||||||
|
|
||||||
const spin = ora({
|
const spin = ora({
|
||||||
text: `Installing dependencies...`,
|
text: `Installing dependencies...`,
|
||||||
spinner: 'aesthetic',
|
spinner: 'aesthetic',
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
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);
|
||||||
} else spin.succeed(`Dependencies installed!`);
|
} else spin.succeed(`Dependencies installed!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,21 +49,14 @@ export async function installDeps(choice: PackageManagerChoice, name: string) {
|
|||||||
* @param name - The name of the project
|
* @param name - The name of the project
|
||||||
*/
|
*/
|
||||||
export async function cloneRepo(lang: string, name: string) {
|
export async function cloneRepo(lang: string, name: string) {
|
||||||
try {
|
try {
|
||||||
await execa('git', [
|
await execa('git', ['clone', `https://github.com/sern-handler/templates.git`]);
|
||||||
'clone',
|
copyRecursiveSync(`templates/templates/${lang}`, name);
|
||||||
`https://github.com/sern-handler/templates.git`,
|
fs.rmSync(`templates/`, { recursive: true, force: true });
|
||||||
]);
|
} catch (error) {
|
||||||
copyRecursiveSync(`templates/templates/${lang}`, name);
|
console.log(`${redBright('✖ Failed')} to clone github templates repo. Install git and try again!`);
|
||||||
fs.rmSync(`templates/`, { recursive: true, force: true });
|
process.exit(1);
|
||||||
} catch (error) {
|
}
|
||||||
console.log(
|
|
||||||
`${redBright(
|
|
||||||
'✖ Failed'
|
|
||||||
)} to clone github templates repo. Install git and try again!`
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,21 +67,18 @@ export async function cloneRepo(lang: string, name: string) {
|
|||||||
* @param 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: string, dest: string) {
|
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();
|
const isDirectory = exists && stats.isDirectory();
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
fs.mkdirSync(dest);
|
fs.mkdirSync(dest);
|
||||||
|
|
||||||
fs.readdirSync(src).forEach(function (childItemName) {
|
fs.readdirSync(src).forEach(function (childItemName) {
|
||||||
copyRecursiveSync(
|
copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
|
||||||
path.join(src, childItemName),
|
});
|
||||||
path.join(dest, childItemName)
|
} else {
|
||||||
);
|
fs.copyFileSync(src, dest);
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
fs.copyFileSync(src, dest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,21 +5,21 @@ import { execa } from 'execa';
|
|||||||
* @returns A promise that resolves to a string.
|
* @returns A promise that resolves to a string.
|
||||||
*/
|
*/
|
||||||
export async function npm() {
|
export async function npm() {
|
||||||
const npm = await execa('npm', ['-v']).catch(() => null);
|
const npm = await execa('npm', ['-v']).catch(() => null);
|
||||||
const npm_version = npm?.stdout;
|
const npm_version = npm?.stdout;
|
||||||
|
|
||||||
const yarn = await execa('yarn', ['-v']).catch(() => null);
|
const yarn = await execa('yarn', ['-v']).catch(() => null);
|
||||||
const yarn_version = yarn?.stdout;
|
const yarn_version = yarn?.stdout;
|
||||||
|
|
||||||
if (npm_version && !yarn_version) {
|
if (npm_version && !yarn_version) {
|
||||||
return 'npm';
|
return 'npm';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!npm_version && yarn_version) {
|
if (!npm_version && yarn_version) {
|
||||||
return 'yarn';
|
return 'yarn';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npm_version && yarn_version) {
|
if (npm_version && yarn_version) {
|
||||||
return 'both';
|
return 'both';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"rootDir": ".",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"importsNotUsedAsValues": "error",
|
"verbatimModuleSyntax": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"forceConsistentCasingInFileNames": true
|
"forceConsistentCasingInFileNames": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import { defineConfig } from 'tsup'
|
import { defineConfig } from 'tsup';
|
||||||
import { esbuildPluginVersionInjector } from 'esbuild-plugin-version-injector';
|
import { esbuildPluginVersionInjector } from 'esbuild-plugin-version-injector';
|
||||||
const shared = {
|
const shared = {
|
||||||
entry: ['src/index.ts'],
|
entry: ['src/index.ts', 'src/create-publish.mts'],
|
||||||
platform: 'node',
|
|
||||||
clean: true,
|
clean: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
};
|
};
|
||||||
export default defineConfig(
|
export default defineConfig({
|
||||||
{
|
format: 'esm',
|
||||||
format: 'esm',
|
target: 'node18',
|
||||||
target: 'node16',
|
tsconfig: './tsconfig.json',
|
||||||
tsconfig: './tsconfig.json',
|
outDir: './dist',
|
||||||
outDir: './dist',
|
treeshake: true,
|
||||||
treeshake: true,
|
esbuildPlugins: [esbuildPluginVersionInjector()],
|
||||||
esbuildPlugins: [esbuildPluginVersionInjector()],
|
platform: 'node',
|
||||||
...shared,
|
splitting: false,
|
||||||
}
|
...shared,
|
||||||
)
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user