mirror of
https://github.com/sern-handler/cli
synced 2026-06-06 17:36:53 +00:00
Compare commits
150 Commits
v0.1.1
...
feat/watch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c06df12de | ||
|
|
667d0c1b89 | ||
|
|
5dbf2a87dc | ||
| a309c085e9 | |||
| f1d7d6c911 | |||
|
|
4ec96dbe17 | ||
|
|
3970cc6911 | ||
|
|
9045e1a03f | ||
|
|
d9ca5ff3ff | ||
|
|
5a68916479 | ||
|
|
e8c4764a9e | ||
|
|
c785d49fa5 | ||
| 40829267c4 | |||
|
|
1fc69b0a6e | ||
|
|
d01e4cb2f1 | ||
|
|
5fd2a7b4c4 | ||
|
|
42bd528756 | ||
|
|
c218065a04 | ||
|
|
2ece63cb8b | ||
|
|
88e2bbf6c8 | ||
|
|
913ff4dc15 | ||
|
|
30179d1ea9 | ||
|
|
3f74658b16 | ||
|
|
0a3fedd1d8 | ||
|
|
f12d541dfe | ||
|
|
642bf11608 | ||
|
|
827ffb7ad9 | ||
|
|
2348e3e9ab | ||
|
|
14df4a9b65 | ||
|
|
4bc7d1b081 | ||
|
|
acbec3e733 | ||
|
|
dbc3154101 | ||
|
|
7252c533bc | ||
|
|
dce78c0945 | ||
|
|
58fa3253f6 | ||
|
|
1421136181 | ||
|
|
f29c7881fe | ||
|
|
0d37da5689 | ||
|
|
504d36729e | ||
|
|
e391fddf20 | ||
|
|
e5d6de4841 | ||
|
|
fc47847eeb | ||
|
|
386b30aedd | ||
|
|
f2531a6f9b | ||
| 69287ab1bd | |||
|
|
aa398a871c | ||
|
|
0855abfea3 | ||
|
|
6212fb3588 | ||
|
|
2018c4381e | ||
|
|
5b0214a073 | ||
|
|
6e6ed3136d | ||
|
|
c302e1e4be | ||
|
|
e60fb42e3e | ||
|
|
5e48f27584 | ||
|
|
276b9656b8 | ||
|
|
75dff367f5 | ||
|
|
90429523c3 | ||
|
|
bed31c1f49 | ||
|
|
9271da3076 | ||
|
|
2009d1fdca | ||
|
|
f9aa2c3d20 | ||
|
|
3fa93bd903 | ||
|
|
e7c50c4d32 | ||
|
|
b1190efee3 | ||
|
|
55b1fff28e | ||
|
|
7bcbf55fb5 | ||
|
|
ebc688022e | ||
|
|
810763837c | ||
|
|
fa331ae0c0 | ||
|
|
6c034a568f | ||
|
|
9158e66bb4 | ||
|
|
af593bf84a | ||
|
|
f84e7ac8f5 | ||
|
|
08b8a13d16 | ||
|
|
c4f8e45bdc | ||
|
|
83e841a341 | ||
|
|
ab2f8016b6 | ||
|
|
93ef62bc9d | ||
|
|
e454ddaaab | ||
|
|
e3ee6d5428 | ||
|
|
02eec5f926 | ||
|
|
aa1e11b24a | ||
|
|
39817e6b4f | ||
|
|
a0d5890ea7 | ||
|
|
2fa5a360ef | ||
|
|
1e07b5f1c8 | ||
|
|
c312ca794c | ||
|
|
eee3bb8db6 | ||
|
|
d9ea304fa6 | ||
|
|
52725ea7f6 | ||
|
|
b24a053d1c | ||
|
|
419b7bce22 | ||
|
|
5a24ae4819 | ||
|
|
8f6b1c690f | ||
|
|
46ec745b88 | ||
|
|
6472683c19 | ||
|
|
2b260eb1bc | ||
|
|
428b87ee1f | ||
|
|
493189772f | ||
|
|
dff1481e19 | ||
|
|
9264dde532 | ||
|
|
ffc1e6f3eb | ||
|
|
95c20a3edf | ||
|
|
c351bd5c0b | ||
|
|
f218e6524b | ||
|
|
afd0b46ffc | ||
|
|
c730986264 | ||
|
|
03dddd4384 | ||
|
|
177766e357 | ||
|
|
7cbde33af2 | ||
|
|
58922bf69e | ||
|
|
92b713e476 | ||
|
|
94757d67cb | ||
|
|
6253571095 | ||
|
|
c4c9b11bc2 | ||
|
|
e06ae29fa1 | ||
|
|
d455a9ef30 | ||
|
|
9bd2b0f38b | ||
|
|
330b2ee92d | ||
|
|
8c45327094 | ||
|
|
361e6451a7 | ||
|
|
81eabff53e | ||
|
|
d78c20a491 | ||
|
|
a97bfdf9ee | ||
|
|
7276c2cb21 | ||
|
|
0ba16b494c | ||
|
|
d35cb828fb | ||
|
|
ae3725587d | ||
|
|
885045a041 | ||
|
|
54a3e6e42c | ||
|
|
eb85a7a8f2 | ||
|
|
e86e3a7e67 | ||
|
|
e3a7d1a28c | ||
|
|
82dd9e7141 | ||
|
|
055da6c24d | ||
|
|
3bd262739f | ||
|
|
805543e1a3 | ||
|
|
7e65f3e5c3 | ||
|
|
93e17be8c7 | ||
|
|
514a56fde4 | ||
|
|
895a48910e | ||
|
|
7cf62c0308 | ||
|
|
3eb63835d9 | ||
|
|
e78cb552da | ||
|
|
f650171030 | ||
|
|
b2e6236dde | ||
|
|
09a9b68b65 | ||
|
|
67a0efd1c2 | ||
|
|
310c82f24e | ||
|
|
b1a8683373 |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -1,2 +1 @@
|
||||
* @Allyedge
|
||||
* @EvolutionX-10
|
||||
32
.github/workflows/auto-deprecate.yml
vendored
Normal file
32
.github/workflows/auto-deprecate.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: NPM Auto Deprecate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
auto-deprecate:
|
||||
name: NPM Auto Deprecate
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org/'
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm i
|
||||
- name: Deprecate dev versions
|
||||
run: npx npm-deprecate --name "*dev*" --package "@sern/cli" --message "This is a deprecated version of @sern/cli@dev. Please use the latest dev version."
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Deprecate pr versions
|
||||
run: npx npm-deprecate --name "*pr*" --package "@sern/cli" --message "This is a deprecated version of @sern/cli. Please use the latest version."
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
35
.github/workflows/codeql-analysis-go.yml
vendored
35
.github/workflows/codeql-analysis-go.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: "CodeQL Go"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: "40 13 * * 2"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["go"]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
65
.github/workflows/codeql-analysis.yml
vendored
Normal file
65
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '40 13 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
40
.github/workflows/continuous-delivery.yml
vendored
Normal file
40
.github/workflows/continuous-delivery.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Continuous Delivery
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'package.json'
|
||||
|
||||
jobs:
|
||||
Publish:
|
||||
name: Publishing Dev
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm i && npm run build
|
||||
|
||||
- name: Link Project
|
||||
run: npm link
|
||||
|
||||
- name: Test Sern
|
||||
run: sern
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
npm version premajor --preid "dev.$(git rev-parse --verify --short HEAD)" --git-tag-version=false
|
||||
npm publish --tag dev
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
54
.github/workflows/continuous-integration.yml
vendored
Normal file
54
.github/workflows/continuous-integration.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
# Trigger the workflow on push or pull request,
|
||||
# but only for the main branch
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request_target:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# Lint:
|
||||
# name: Linting
|
||||
# runs-on: ubuntu-latest
|
||||
|
||||
# steps:
|
||||
# - name: Check out Git repository
|
||||
# uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
# - name: Set up Node.js
|
||||
# uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
# with:
|
||||
# node-version: 17
|
||||
|
||||
# Prettier must be in `package.json`
|
||||
# - name: Install Node.js dependencies
|
||||
# run: npm i
|
||||
|
||||
# - name: Run Prettier
|
||||
# run: npm run format
|
||||
|
||||
Test:
|
||||
name: Testing
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm i && npm run build
|
||||
|
||||
- name: Link Project
|
||||
run: npm link
|
||||
|
||||
- name: Test sern
|
||||
run: sern
|
||||
40
.github/workflows/publish.yml
vendored
Normal file
40
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
prNumber:
|
||||
description: The number of the PR that is being deployed
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
Publish:
|
||||
name: Publishing
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
|
||||
with:
|
||||
node-version: 17
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: npm i && npm run build
|
||||
|
||||
- name: Link Project
|
||||
run: npm link
|
||||
|
||||
- name: Test sern
|
||||
run: sern
|
||||
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
TAG=$(echo 'pr-${{ github.event.inputs.prNumber }}')
|
||||
npm version premajor --preid "${TAG}.$(git rev-parse --verify --short HEAD)" --git-tag-version=false
|
||||
npm publish --tag ${TAG}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
32
.github/workflows/release-please.yml
vendored
Normal file
32
.github/workflows/release-please.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
Release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: google-github-actions/release-please-action@v3
|
||||
id: release
|
||||
with:
|
||||
release-type: node
|
||||
bump-patch-for-minor-pre-major: true
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- 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 && npm run build
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- run: npm link
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- run: sern
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
35
.github/workflows/release.yml
vendored
35
.github/workflows/release.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: goreleaser
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all tags
|
||||
run: git fetch --force --tags
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
id: go
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
118
.gitignore
vendored
118
.gitignore
vendored
@@ -1 +1,117 @@
|
||||
node_modules
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Editor Files
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
.env.development.local
|
||||
.env.development
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Extras
|
||||
.vscode/
|
||||
|
||||
# Yarn files
|
||||
.yarn/install-state.gz
|
||||
.yarn/build-state.yml
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
builds:
|
||||
- binary: sern
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
main: ./cmd
|
||||
6
.npmignore
Normal file
6
.npmignore
Normal file
@@ -0,0 +1,6 @@
|
||||
renovate.json
|
||||
tsconfig.json
|
||||
.prettierignore
|
||||
.prettierrc
|
||||
.gitattributes
|
||||
.github/
|
||||
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
||||
.github/
|
||||
CHANGELOG.md
|
||||
dist/
|
||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 140
|
||||
}
|
||||
203
CHANGELOG.md
203
CHANGELOG.md
@@ -1,23 +1,204 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 0.1.1 (2022-06-02)
|
||||
## [1.0.2](https://github.com/sern-handler/cli/compare/v1.0.1...v1.0.2) (2023-11-04)
|
||||
|
||||
The `go-npm` package was replaced by one of its forks, `@gzuidhof/go-npm`.
|
||||
|
||||
`@gzuidhof/go-npm` has updated dependencies, and it uses `esbuild`, which is great.
|
||||
### Bug Fixes
|
||||
|
||||
### Changes
|
||||
* better error handling ([5dbf2a8](https://github.com/sern-handler/cli/commit/5dbf2a87dcb0001993fe126d9002bc82c8108e24))
|
||||
* build mkdir errors ([#122](https://github.com/sern-handler/cli/issues/122)) ([f1d7d6c](https://github.com/sern-handler/cli/commit/f1d7d6c911bc54ed3ca3e39eefbc7de6ee33b10d))
|
||||
|
||||
- Replace `go-npm` with `@gzuidhof/go-npm`.
|
||||
## [1.0.1](https://github.com/sern-handler/cli/compare/v1.0.0...v1.0.1) (2023-10-05)
|
||||
|
||||
## 0.1.0 (2022-06-02)
|
||||
|
||||
This is the CLI's initial release.
|
||||
### Bug Fixes
|
||||
|
||||
* multiple bugs ([#119](https://github.com/sern-handler/cli/issues/119)) ([d9ca5ff](https://github.com/sern-handler/cli/commit/d9ca5ff3ff2f304a6d75f2b7a296bd900431d41f))
|
||||
|
||||
## [1.0.0](https://github.com/sern-handler/cli/compare/v0.6.0...v1.0.0) (2023-09-05)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **plugins:** older versions of cli does not have plugins command functional
|
||||
|
||||
### Features
|
||||
|
||||
- `init` command
|
||||
- `help` command
|
||||
- `version` command
|
||||
* build app ([#112](https://github.com/sern-handler/cli/issues/112)) ([88e2bbf](https://github.com/sern-handler/cli/commit/88e2bbf6c84e3841370a4288181e8ec721ef1925))
|
||||
* list subcommand ([#113](https://github.com/sern-handler/cli/issues/113)) ([5fd2a7b](https://github.com/sern-handler/cli/commit/5fd2a7b4c4bc92467fbaa26005d261d4ed8b2a13))
|
||||
* **plugins:** new method to obtain plugins ([#114](https://github.com/sern-handler/cli/issues/114)) ([c785d49](https://github.com/sern-handler/cli/commit/c785d49fa5c0d98261de7d7b0c39f85c21316156))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* credentials precedence ([#111](https://github.com/sern-handler/cli/issues/111)) ([3f74658](https://github.com/sern-handler/cli/commit/3f74658b16b2697df11c7e33172c09c30b7543a8))
|
||||
* **extra:** dockerfile errors and tsc fallback ([#101](https://github.com/sern-handler/cli/issues/101)) ([4082926](https://github.com/sern-handler/cli/commit/40829267c4e77b316a60604c63bad79124713b89))
|
||||
|
||||
## [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)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* re-write to TypeScript
|
||||
|
||||
### Features
|
||||
|
||||
* add engine for node version & remove manual version check ([#72](https://github.com/sern-handler/cli/issues/72)) ([2009d1f](https://github.com/sern-handler/cli/commit/2009d1fdca9a383d219304fd3cb48a622355b7dc))
|
||||
* adds the esm template option + refactors ([#73](https://github.com/sern-handler/cli/issues/73)) ([9271da3](https://github.com/sern-handler/cli/commit/9271da30764f86225385e8ae6448b99d66687294))
|
||||
* re-write to TypeScript ([bed31c1](https://github.com/sern-handler/cli/commit/bed31c1f4995bbf7d8d0a483f562788172e29919))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* release 0.5.0 ([2018c43](https://github.com/sern-handler/cli/commit/2018c4381e665b9b0c5e70a203aa0dfd9fdd3cef))
|
||||
|
||||
## [0.4.2](https://github.com/sern-handler/cli/compare/v0.4.1...v0.4.2) (2022-07-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* switch to undici ([#58](https://github.com/sern-handler/cli/issues/58)) ([c4f8e45](https://github.com/sern-handler/cli/commit/c4f8e45bdc0af5a3bbd394d2b9f852f4a946114c))
|
||||
|
||||
## [0.4.1](https://github.com/sern-handler/cli/compare/v0.4.0...v0.4.1) (2022-07-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `sern.config.json` ([#38](https://github.com/sern-handler/cli/issues/38)) ([3eb6383](https://github.com/sern-handler/cli/commit/3eb63835d9f6ff3f3426e017ea87344c00bb13a4))
|
||||
* add basic type checking ([eb85a7a](https://github.com/sern-handler/cli/commit/eb85a7a8f2f6252f719fd396d42cded2d9eb0918))
|
||||
* add commander and start plugins installer ([#36](https://github.com/sern-handler/cli/issues/36)) ([b2e6236](https://github.com/sern-handler/cli/commit/b2e6236dde6f4848dde6fc23a6222415824bb294))
|
||||
* add default settings for the -y flag ([#19](https://github.com/sern-handler/cli/issues/19)) ([e5f607e](https://github.com/sern-handler/cli/commit/e5f607e99875e105cbb148cab3ed1bbc3771ae35))
|
||||
* added actions and formatting stuff ([b302a8b](https://github.com/sern-handler/cli/commit/b302a8b362257fb2cea72b7e1fc66bea351c511f))
|
||||
* added help command ([ca23d17](https://github.com/sern-handler/cli/commit/ca23d17670663b62e23849e2350deef208bfc100))
|
||||
* Added version command & created readme ([#25](https://github.com/sern-handler/cli/issues/25)) ([7535a5e](https://github.com/sern-handler/cli/commit/7535a5e0267c9e682b7bc8470206c0597f5ba9a1))
|
||||
* bump all files to GitHub 🎉 ([01b39ad](https://github.com/sern-handler/cli/commit/01b39ad9b78f0a67e23ba66c10262082675eeed5))
|
||||
* cli is now functional ([65f38f3](https://github.com/sern-handler/cli/commit/65f38f3eb2b4e8e2bd136b9bd8f37f1966be1661))
|
||||
* cli is now functional ([5021d28](https://github.com/sern-handler/cli/commit/5021d28bca6ebe1cb4a548f5e595b1220f222c98))
|
||||
* create typescript dockerfile and the extra command ([#28](https://github.com/sern-handler/cli/issues/28)) ([b1a8683](https://github.com/sern-handler/cli/commit/b1a86833734258e0a22da18c2c780133c199d5cd))
|
||||
* enable extra command & jsdockerfile ([#43](https://github.com/sern-handler/cli/issues/43)) ([7cf62c0](https://github.com/sern-handler/cli/commit/7cf62c03083b8ebbb8a6a63fd8efe592344d5230))
|
||||
* **init:** add --sync flag ([#53](https://github.com/sern-handler/cli/issues/53)) ([b24a053](https://github.com/sern-handler/cli/commit/b24a053d1cb8c00d49a96b6d536dd17205b9fa0e))
|
||||
* making sern help message look better, adding ascii art ([#50](https://github.com/sern-handler/cli/issues/50)) ([9bd2b0f](https://github.com/sern-handler/cli/commit/9bd2b0f38be835a31fceeabdf60487a1424cdf7e))
|
||||
* more questions, better handling, better ui ([f931802](https://github.com/sern-handler/cli/commit/f9318024bb4c62cee1a7ddfc6af4117c22ca6020))
|
||||
* now edits the directories as per user's choice ([fec1c8e](https://github.com/sern-handler/cli/commit/fec1c8e24c5ca7752f9e74b0fc3a32716bb42299))
|
||||
* plugin command!!! ([#45](https://github.com/sern-handler/cli/issues/45)) ([895a489](https://github.com/sern-handler/cli/commit/895a48910e32813f8aa25f57302a4123fc631c2c))
|
||||
* rebase changes ([cae3c59](https://github.com/sern-handler/cli/commit/cae3c597c3da6aa836fb9c70b8555814e8fc5db0))
|
||||
* refactored code and added custom handling of commands ([0e97b7d](https://github.com/sern-handler/cli/commit/0e97b7db8afed7f625eeb0a43aa992441ab49b39))
|
||||
* **skip:** option to skip package manager selection ([#20](https://github.com/sern-handler/cli/issues/20)) ([7b1d535](https://github.com/sern-handler/cli/commit/7b1d53520f0aa35e48b72d61d2f1a85ffdfdfec8))
|
||||
* using degit to clone the templates ([ddb0285](https://github.com/sern-handler/cli/commit/ddb02850f2096d8c9ec36e766ea74e10d2efce3f))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* avoid crashing of cli when no plugin found ([#47](https://github.com/sern-handler/cli/issues/47)) ([8c45327](https://github.com/sern-handler/cli/commit/8c45327094b2560f7b5c813a1c1925920bd46038))
|
||||
* fix degit erroring when there's no cache ([fc01554](https://github.com/sern-handler/cli/commit/fc01554fae2726f4ebd39a66ef1cb634a421dd9f))
|
||||
* **install.js:** fix mistyped. cached -> cache ([fa68936](https://github.com/sern-handler/cli/commit/fa689360ce054c63dab77e8b8f0b794b3b8736e4))
|
||||
* no more crashing cli if yarn isnt present ([#24](https://github.com/sern-handler/cli/issues/24)) ([88893a3](https://github.com/sern-handler/cli/commit/88893a35cd1144867713de32c5bf52c2dc702450))
|
||||
* no more error when selecting js ([cc410bd](https://github.com/sern-handler/cli/commit/cc410bd370a751833dbc5fc04030bfa53a6c1fd2))
|
||||
* prettier things ([1265224](https://github.com/sern-handler/cli/commit/1265224bb9f93cb104915be50c1c2ea1e3924955))
|
||||
* removed useless line ([f268b1c](https://github.com/sern-handler/cli/commit/f268b1c62fd4d5823d483a33cfef2e2d7f7b127c))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **init.js:** string.match -> regex.test for node version ([f760dbc](https://github.com/sern-handler/cli/commit/f760dbc6e39e098496f25a5c4ee90855a2bb3bd5))
|
||||
|
||||
### [0.2.2](https://github.com/sern-handler/cli/compare/v0.2.1...v0.2.2) (2022-07-05)
|
||||
|
||||
### [0.2.1](https://github.com/sern-handler/cli/compare/v0.2.0...v0.2.1) (2022-07-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* making sern help message look better, adding ascii art ([#50](https://github.com/sern-handler/cli/issues/50)) ([9bd2b0f](https://github.com/sern-handler/cli/commit/9bd2b0f38be835a31fceeabdf60487a1424cdf7e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* avoid crashing of cli when no plugin found ([#47](https://github.com/sern-handler/cli/issues/47)) ([8c45327](https://github.com/sern-handler/cli/commit/8c45327094b2560f7b5c813a1c1925920bd46038))
|
||||
|
||||
## [0.2.0](https://github.com/sern-handler/cli/compare/v0.1.3...v0.2.0) (2022-06-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `sern.config.json` ([#38](https://github.com/sern-handler/cli/issues/38)) ([3eb6383](https://github.com/sern-handler/cli/commit/3eb63835d9f6ff3f3426e017ea87344c00bb13a4))
|
||||
* add basic type checking ([eb85a7a](https://github.com/sern-handler/cli/commit/eb85a7a8f2f6252f719fd396d42cded2d9eb0918))
|
||||
* add commander and start plugins installer ([#36](https://github.com/sern-handler/cli/issues/36)) ([b2e6236](https://github.com/sern-handler/cli/commit/b2e6236dde6f4848dde6fc23a6222415824bb294))
|
||||
* enable extra command & jsdockerfile ([#43](https://github.com/sern-handler/cli/issues/43)) ([7cf62c0](https://github.com/sern-handler/cli/commit/7cf62c03083b8ebbb8a6a63fd8efe592344d5230))
|
||||
* plugin command!!! ([#45](https://github.com/sern-handler/cli/issues/45)) ([895a489](https://github.com/sern-handler/cli/commit/895a48910e32813f8aa25f57302a4123fc631c2c))
|
||||
|
||||
### [0.1.3](https://github.com/sern-handler/cli/compare/v0.1.2...v0.1.3) (2022-06-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add default settings for the -y flag ([#19](https://github.com/sern-handler/cli/issues/19)) ([e5f607e](https://github.com/sern-handler/cli/commit/e5f607e99875e105cbb148cab3ed1bbc3771ae35))
|
||||
* Added version command & created readme ([#25](https://github.com/sern-handler/cli/issues/25)) ([7535a5e](https://github.com/sern-handler/cli/commit/7535a5e0267c9e682b7bc8470206c0597f5ba9a1))
|
||||
* create typescript dockerfile and the extra command ([#28](https://github.com/sern-handler/cli/issues/28)) ([b1a8683](https://github.com/sern-handler/cli/commit/b1a86833734258e0a22da18c2c780133c199d5cd))
|
||||
* now edits the directories as per user's choice ([fec1c8e](https://github.com/sern-handler/cli/commit/fec1c8e24c5ca7752f9e74b0fc3a32716bb42299))
|
||||
* **skip:** option to skip package manager selection ([#20](https://github.com/sern-handler/cli/issues/20)) ([7b1d535](https://github.com/sern-handler/cli/commit/7b1d53520f0aa35e48b72d61d2f1a85ffdfdfec8))
|
||||
* using degit to clone the templates ([ddb0285](https://github.com/sern-handler/cli/commit/ddb02850f2096d8c9ec36e766ea74e10d2efce3f))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix degit erroring when there's no cache ([fc01554](https://github.com/sern-handler/cli/commit/fc01554fae2726f4ebd39a66ef1cb634a421dd9f))
|
||||
* **install.js:** fix mistyped. cached -> cache ([fa68936](https://github.com/sern-handler/cli/commit/fa689360ce054c63dab77e8b8f0b794b3b8736e4))
|
||||
* no more crashing cli if yarn isnt present ([#24](https://github.com/sern-handler/cli/issues/24)) ([88893a3](https://github.com/sern-handler/cli/commit/88893a35cd1144867713de32c5bf52c2dc702450))
|
||||
* no more error when selecting js ([cc410bd](https://github.com/sern-handler/cli/commit/cc410bd370a751833dbc5fc04030bfa53a6c1fd2))
|
||||
|
||||
### [0.1.1](https://github.com/sern-handler/cli/compare/v0.1.0...v0.1.1) (2022-05-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added help command ([ca23d17](https://github.com/sern-handler/cli/commit/ca23d17670663b62e23849e2350deef208bfc100))
|
||||
* cli is now functional ([5021d28](https://github.com/sern-handler/cli/commit/5021d28bca6ebe1cb4a548f5e595b1220f222c98))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* prettier things ([1265224](https://github.com/sern-handler/cli/commit/1265224bb9f93cb104915be50c1c2ea1e3924955))
|
||||
* removed useless line ([f268b1c](https://github.com/sern-handler/cli/commit/f268b1c62fd4d5823d483a33cfef2e2d7f7b127c))
|
||||
|
||||
## 0.1.0 (2022-04-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added actions and formatting stuff ([b302a8b](https://github.com/sern-handler/cli/commit/b302a8b362257fb2cea72b7e1fc66bea351c511f))
|
||||
* bump all files to GitHub 🎉 ([01b39ad](https://github.com/sern-handler/cli/commit/01b39ad9b78f0a67e23ba66c10262082675eeed5))
|
||||
* more questions, better handling, better ui ([f931802](https://github.com/sern-handler/cli/commit/f9318024bb4c62cee1a7ddfc6af4117c22ca6020))
|
||||
* refactored code and added custom handling of commands ([0e97b7d](https://github.com/sern-handler/cli/commit/0e97b7db8afed7f625eeb0a43aa992441ab49b39))
|
||||
|
||||
62
README.md
62
README.md
@@ -1,19 +1,14 @@
|
||||
# Sern CLI
|
||||
<div align="center">
|
||||
<img src="https://raw.githubusercontent.com/sern-handler/.github/main/cli.png" width="900px">
|
||||
</div>
|
||||
|
||||
[](https://github.com/sern-handler/cli)
|
||||
[](https://github.com/sern-handler/cli)
|
||||
|
||||
Our CLI allows you to setup and manage Discord bot projects without writing a single line of code!
|
||||
# Features
|
||||
|
||||
😁 **User Friendly** <br>
|
||||
💦 **Simple** <br>
|
||||
🌱 **Efficient** <br>
|
||||
💪 **Powerful** <br>
|
||||
|
||||
## License
|
||||
|
||||
[](https://github.com/sern-handler/cli)
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
@@ -21,7 +16,7 @@ npm install -g @sern/cli@latest
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn add -g @sern/cli@latest
|
||||
yarn global add @sern/cli@latest
|
||||
```
|
||||
|
||||
```sh
|
||||
@@ -32,26 +27,37 @@ pnpm add -g @sern/cli@latest
|
||||
|
||||
When you install the CLI, you can use our commands with **sern** prefix.
|
||||
|
||||
`sern <command> (opt)<flag>`
|
||||
```
|
||||
Usage: sern [options] [command]
|
||||
|
||||
|
||||
___ ___ _ __ _ __
|
||||
/ __|/ _ \ '__| '_ \
|
||||
\__ \ __/ | | | | |
|
||||
|___/\___|_| |_| |_|
|
||||
|
||||
Welcome!
|
||||
If you're new to sern, run npm create @sern/bot for an interactive setup to your new bot project!
|
||||
|
||||
If you have any ideas, suggestions, bug reports, kindly join our support server: https://sern.dev/discord
|
||||
|
||||
Options:
|
||||
-v, --version output the version number
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
init [options] Quickest way to scaffold a new project [DEPRECATED]
|
||||
plugins [options] Install plugins from https://github.com/sern-handler/awesome-plugins
|
||||
extra Easy way to add extra things in your sern project
|
||||
commands Defacto way to manage your slash commands
|
||||
help [command] display help for command
|
||||
```
|
||||
|
||||
## Setting Up Your Project
|
||||
|
||||
To create a new project, you can simply run the following command:
|
||||
Run `npm create @sern/bot` for an interactive setup on a brand new project using our framework.
|
||||
|
||||
```sh
|
||||
sern init
|
||||
```
|
||||
## Installing Plugins
|
||||
|
||||
The `init` command will ask you some questions and at the end it will generate a new project.
|
||||
|
||||
## Help
|
||||
|
||||
If you need help, you can always run the following command:
|
||||
|
||||
```sh
|
||||
sern help
|
||||
```
|
||||
|
||||
## Stats
|
||||
|
||||

|
||||
sern runs on your plugins. Contribute to our [repository](https://github.com/sern-handler/awesome-plugins) and then install the plugins via our cli! <br>
|
||||
Run `sern plugins` to see all installable plugins.
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/sern-handler/cli/pkg/initialize"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize a new Sern project.",
|
||||
Long: `Initialize a new Sern project, either with a JavaScript or a TypeScript template.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
initialize.Initialize()
|
||||
},
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "sern",
|
||||
Short: "A powerful CLI tool for Sern.",
|
||||
Version: "0.1.0",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Sern CLI")
|
||||
},
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
rootCmd.Flags().BoolP("help", "h", false, "Help for the Sern CLI.")
|
||||
rootCmd.Flags().BoolP("version", "v", false, "The version of the Sern CLI.")
|
||||
rootCmd.SetVersionTemplate("Sern CLI - Version {{.Version}}\n")
|
||||
rootCmd.AddCommand(initCmd)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package main
|
||||
|
||||
import "github.com/sern-handler/cli/cmd/cli"
|
||||
|
||||
func main() {
|
||||
cli.Execute()
|
||||
}
|
||||
38
go.mod
38
go.mod
@@ -1,38 +0,0 @@
|
||||
module github.com/sern-handler/cli
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/gookit/color v1.5.0
|
||||
github.com/spf13/cobra v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 // indirect
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
136
go.sum
136
go.sum
@@ -1,136 +0,0 @@
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4 h1:pchTU9rsLUSvWEl2Aq9Pv3k0IE2fkqtGxazskAMd9Ng=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4/go.mod h1:hrV6Y/kQCLhIZXGcriDCUBtB3wnN7156gMXJ3+b23xM=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
|
||||
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
4130
package-lock.json
generated
4130
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
96
package.json
96
package.json
@@ -1,37 +1,63 @@
|
||||
{
|
||||
"name": "@sern/cli",
|
||||
"version": "0.1.1",
|
||||
"description": "Our CLI allows you to setup and manage Discord bot projects without writing a single line of code!",
|
||||
"scripts": {
|
||||
"postinstall": "go-npm install",
|
||||
"preuninstall": "go-npm uninstall"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sern-handler/cli.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gzuidhof/go-npm": "^0.1.13"
|
||||
},
|
||||
"keywords": [
|
||||
"sern",
|
||||
"cli",
|
||||
"discord",
|
||||
"bot",
|
||||
"discord.js"
|
||||
],
|
||||
"contributors": [
|
||||
"Allyedge",
|
||||
"EvolutionX-10"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sern-handler/cli/issues"
|
||||
},
|
||||
"homepage": "https://github.com/sern-handler/cli#readme",
|
||||
"goBinary": {
|
||||
"name": "sern",
|
||||
"path": "./bin",
|
||||
"url": "https://github.com/sern-handler/cli/releases/download/v{{version}}/cli_{{version}}_{{platform}}_{{arch}}.tar.gz"
|
||||
}
|
||||
"name": "@sern/cli",
|
||||
"version": "1.0.2",
|
||||
"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",
|
||||
"esbuild": "^0.19.1",
|
||||
"execa": "7.2.0",
|
||||
"find-up": "6.3.0",
|
||||
"glob": "^10.3.3",
|
||||
"ora": "6.3.1",
|
||||
"prompts": "2.4.2",
|
||||
"undici": "5.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@favware/npm-deprecate": "1.0.7",
|
||||
"@types/prompts": "2.4.4",
|
||||
"prettier": "2.8.8",
|
||||
"tsup": "^6.7.0",
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.16.x"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/sern-handler/cli/pkg/util"
|
||||
)
|
||||
|
||||
func installDependencies(name string, packageManager string) error {
|
||||
err := os.Chdir(name)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't change to the project's directory.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
packageManagers := util.CheckPackageManagers()
|
||||
|
||||
if packageManager == "npm" && packageManagers.NPM {
|
||||
err := exec.Command("npm", "install").Run()
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't install the dependencies.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
color.Info.Prompt("Successfully installed the dependencies.")
|
||||
}
|
||||
|
||||
if packageManager == "yarn" && packageManagers.Yarn {
|
||||
err := exec.Command("yarn", "install").Run()
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't install the dependencies.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
color.Info.Prompt("Successfully installed the dependencies.")
|
||||
}
|
||||
|
||||
if packageManager == "skip" {
|
||||
color.Warn.Prompt("Skipping the installation of the dependencies.")
|
||||
}
|
||||
|
||||
if !packageManagers.NPM && !packageManagers.Yarn {
|
||||
color.Error.Prompt("Couldn't find any package managers.")
|
||||
|
||||
return errors.New("couldn't find any package managers")
|
||||
}
|
||||
|
||||
err = os.Chdir("..")
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't change to the starting directory.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
func Initialize() {
|
||||
answers := struct {
|
||||
Name string
|
||||
Language string
|
||||
Main string
|
||||
Commands string
|
||||
Package string
|
||||
}{}
|
||||
|
||||
err := survey.Ask(questions, &answers)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Project initialization failed, exiting.")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
color.Info.Prompt("Initializing the project...")
|
||||
|
||||
err = cloneRepository(answers.Name, answers.Language)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't generate the project from the templates, exiting.")
|
||||
|
||||
err = os.RemoveAll("templates")
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't remove the templates folder.")
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = os.RemoveAll("templates")
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't remove the templates folder.")
|
||||
}
|
||||
|
||||
color.Info.Prompt("Successfully generated the project from the templates.")
|
||||
|
||||
color.Info.Prompt("Renaming the project's folders...")
|
||||
|
||||
err = renameFolders(answers.Name, answers.Main, answers.Commands)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't rename the folders, exiting.")
|
||||
color.Warn.Prompt("The project was generated, but the folders weren't renamed.\n\nYou can still use the project, but you will have to rename the folders manually.")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
color.Info.Prompt("Successfully renamed the project's folders.")
|
||||
|
||||
color.Info.Prompt("Installing the dependencies...")
|
||||
|
||||
err = installDependencies(answers.Name, answers.Package)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't install the dependencies, exiting.")
|
||||
color.Warn.Prompt("The project was generated, but the dependencies weren't installed.\n\nYou can still use the project, but you will have to install the dependencies manually.")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = renamePackageJson(answers.Name)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't rename the package.json file, exiting.")
|
||||
color.Warn.Prompt("The project was generated, but the package.json file wasn't updated.\n\nYou can still use the project, but you will have to update the package.json file manually.")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
color.Success.Prompt("Project successfully initialized.")
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package initialize
|
||||
|
||||
type PackageJSON struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
Main string `json:"main"`
|
||||
Scripts map[string]string `json:"scripts"`
|
||||
Keywords []string `json:"keywords"`
|
||||
Author string `json:"author"`
|
||||
License string `json:"license"`
|
||||
Dependencies map[string]string `json:"dependencies"`
|
||||
DevDependencies map[string]string `json:"devDependencies"`
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import "github.com/AlecAivazis/survey/v2"
|
||||
|
||||
var questions = []*survey.Question{
|
||||
{
|
||||
Name: "name",
|
||||
Prompt: &survey.Input{
|
||||
Message: "What is your project's name?",
|
||||
},
|
||||
Validate: survey.Required,
|
||||
},
|
||||
{
|
||||
Name: "language",
|
||||
Prompt: &survey.Select{
|
||||
Message: "What language do you want to use?",
|
||||
Options: []string{"JavaScript", "TypeScript"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "main",
|
||||
Prompt: &survey.Input{
|
||||
Message: "What is your project's main directory?",
|
||||
Default: "src",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "commands",
|
||||
Prompt: &survey.Input{
|
||||
Message: "What is your project's command directory?",
|
||||
Default: "commands",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "package",
|
||||
Prompt: &survey.Select{
|
||||
Message: "What package manager do you want to use?",
|
||||
Options: []string{"npm", "yarn", "skip"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
func renameFolders(name string, main string, commands string) error {
|
||||
if main != "src" {
|
||||
err := os.Rename(name+"/src", name+"/"+main)
|
||||
|
||||
if err != nil {
|
||||
color.Warn.Prompt("Couldn't rename the main folder.")
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if commands != "commands" {
|
||||
err := os.Rename(name+"/"+main+"/commands", name+"/"+main+"/"+commands)
|
||||
|
||||
if err != nil {
|
||||
color.Warn.Prompt("Couldn't rename the commands folder.")
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func renamePackageJson(name string) error {
|
||||
file, err := ioutil.ReadFile(name + "/package.json")
|
||||
|
||||
if err != nil {
|
||||
color.Warn.Prompt("Couldn't read the package.json file.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var packageJSON PackageJSON
|
||||
|
||||
err = json.Unmarshal(file, &packageJSON)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
||||
color.Warn.Prompt("Couldn't unmarshal the package.json file.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
packageJSON.Name = name
|
||||
|
||||
file, err = json.MarshalIndent(packageJSON, "", " ")
|
||||
|
||||
if err != nil {
|
||||
color.Warn.Prompt("Couldn't marshal the package.json file.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(name+"/package.json", file, 0644)
|
||||
|
||||
if err != nil {
|
||||
color.Warn.Prompt("Couldn't write the package.json file.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
func cloneRepository(name string, language string) error {
|
||||
_, err := git.PlainClone("templates", false, &git.CloneOptions{
|
||||
URL: "https://github.com/sern-handler/templates",
|
||||
Progress: os.Stdout,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't install the template.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Rename("templates/templates/"+strings.ToLower(language), name)
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't rename the template to the project's name.")
|
||||
color.Warn.Prompt("The project was generated, but it wasn't renamed.\n\nYou can still use the project, but you will have to rename it manually.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.RemoveAll("templates")
|
||||
|
||||
if err != nil {
|
||||
color.Error.Prompt("Couldn't remove the templates folder.")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package util
|
||||
|
||||
import "os/exec"
|
||||
|
||||
type PackageManagers struct {
|
||||
NPM bool
|
||||
Yarn bool
|
||||
}
|
||||
|
||||
func CheckPackageManagers() PackageManagers {
|
||||
packageManagers := PackageManagers{
|
||||
NPM: false,
|
||||
Yarn: false,
|
||||
}
|
||||
|
||||
_, err := exec.LookPath("npm")
|
||||
|
||||
if err == nil {
|
||||
packageManagers.NPM = true
|
||||
}
|
||||
|
||||
_, err = exec.LookPath("yarn")
|
||||
|
||||
if err == nil {
|
||||
packageManagers.Yarn = true
|
||||
}
|
||||
|
||||
return packageManagers
|
||||
}
|
||||
17
renovate.json
Normal file
17
renovate.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$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/"
|
||||
}
|
||||
]
|
||||
}
|
||||
177
src/commands/build.ts
Normal file
177
src/commands/build.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
import esbuild from 'esbuild';
|
||||
import { getConfig, type sernConfig } from '../utilities/getConfig';
|
||||
import { resolve } from 'node:path';
|
||||
import { glob } from 'glob';
|
||||
import { configDotenv } from 'dotenv';
|
||||
import assert from 'node:assert';
|
||||
import { imageLoader, validExtensions } from '../plugins/imageLoader';
|
||||
import defaultEsbuild from '../utilities/defaultEsbuildConfig';
|
||||
import { require } from '../utilities/require';
|
||||
import { pathExists, pathExistsSync } from 'find-up';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import * as Preprocessor from '../utilities/preprocessor';
|
||||
import { bold, magentaBright } from 'colorette';
|
||||
|
||||
type BuildOptions = {
|
||||
/**
|
||||
* Define __VERSION__
|
||||
* This option is a quick switch to defining the __VERSION__ constant which will be a string of the version provided in
|
||||
* cwd's package.json
|
||||
*/
|
||||
defineVersion?: boolean;
|
||||
/**
|
||||
* default = esm
|
||||
*/
|
||||
format?: 'cjs' | 'esm';
|
||||
/**
|
||||
* extra esbuild plugins to build with sern.
|
||||
*/
|
||||
esbuildPlugins?: esbuild.Plugin[];
|
||||
/**
|
||||
* https://esbuild.github.io/api/#drop-labels
|
||||
**/
|
||||
dropLabels?: string[];
|
||||
/**
|
||||
* https://esbuild.github.io/api/#define
|
||||
**/
|
||||
define?: Record<string, string>;
|
||||
|
||||
tsconfig?: string;
|
||||
/**
|
||||
* default = 'development'
|
||||
*/
|
||||
mode: 'production' | 'development';
|
||||
/**
|
||||
* will search for env file. If none exists,
|
||||
* default to .env.
|
||||
*/
|
||||
env?: string;
|
||||
};
|
||||
|
||||
/*
|
||||
* locates jsconfig or tsconfig depending on language.
|
||||
* If path is not given, default to the current working directory's `(js|ts)config.json`
|
||||
*/
|
||||
function resolveConfigPath (path: string|undefined, language: string) {
|
||||
if(language === 'javascript') {
|
||||
return path ?? resolve('jsconfig.json')
|
||||
}
|
||||
return path ?? resolve('tsconfig.json')
|
||||
}
|
||||
|
||||
async function createBuildConfig(options: Record<string,any>, sernConfig: sernConfig) {
|
||||
const buildConfigPath = resolve(options.project ?? 'sern.build.js');
|
||||
const defaultBuildConfig = {
|
||||
defineVersion: true,
|
||||
format: options.format ?? 'esm',
|
||||
mode: options.mode ?? 'development',
|
||||
dropLabels: [],
|
||||
esbuildPlugins: [],
|
||||
tsconfig: resolveConfigPath(options.tsconfig, sernConfig.language),
|
||||
env: options.env ?? resolve('.env'),
|
||||
} satisfies BuildOptions;
|
||||
|
||||
if(pathExistsSync(buildConfigPath)) {
|
||||
return {
|
||||
...defaultBuildConfig,
|
||||
...(await import('file:///' + buildConfigPath)).default,
|
||||
}
|
||||
} else {
|
||||
return defaultBuildConfig;
|
||||
}
|
||||
}
|
||||
|
||||
function fillEnv(options: Record<string, any>) {
|
||||
let env = {} as Record<string, string>;
|
||||
configDotenv({ path: options.env, processEnv: env });
|
||||
return env;
|
||||
}
|
||||
|
||||
export async function build(options: Record<string, any>) {
|
||||
if (!options.supressWarnings) {
|
||||
console.info(`${magentaBright('EXPERIMENTAL')}: This API has not been stabilized. add -W or --suppress-warnings flag to suppress`);
|
||||
}
|
||||
const sernConfig = await getConfig();
|
||||
const entryPoints = await glob(`./src/**/*{${validExtensions.join(',')}}`, {
|
||||
ignore: {
|
||||
ignored: (p) => p.name.endsWith('.d.ts'),
|
||||
},
|
||||
});
|
||||
|
||||
const buildConfig = await createBuildConfig(options, sernConfig);
|
||||
let env = fillEnv(options);
|
||||
|
||||
if (env.MODE && !env.NODE_ENV) {
|
||||
console.warn('Use NODE_ENV instead of MODE');
|
||||
console.warn('MODE has no effect.');
|
||||
console.warn(`https://nodejs.dev/en/learn/nodejs-the-difference-between-development-and-production/`);
|
||||
}
|
||||
|
||||
if (env.NODE_ENV) {
|
||||
buildConfig.mode = env.NODE_ENV as 'production' | 'development';
|
||||
console.log(magentaBright('NODE_ENV:'), 'Found NODE_ENV variable, setting `mode` to this.');
|
||||
}
|
||||
|
||||
assert(buildConfig.mode === 'development'
|
||||
|| buildConfig.mode === 'production', 'Mode is not `production` or `development`');
|
||||
|
||||
|
||||
try {
|
||||
let config = require(buildConfig.tsconfig!);
|
||||
config.extends && console.warn("Please ensure to extend the generated tsconfig")
|
||||
} catch(e) {
|
||||
console.warn("no tsconfig / jsconfig found");
|
||||
console.warn(`Please create a ${sernConfig.language === 'javascript' ? 'jsconfig.json' : 'tsconfig.json' }`);
|
||||
console.warn("It should have at least extend the generated one sern makes.")
|
||||
console.warn(`
|
||||
{
|
||||
"extends": "./.sern/tsconfig.json",
|
||||
}`.trim())
|
||||
throw e;
|
||||
}
|
||||
|
||||
console.log(bold('Building with:'));
|
||||
console.log(' ', magentaBright('defineVersion'), buildConfig.defineVersion);
|
||||
console.log(' ', magentaBright('format'), buildConfig.format);
|
||||
console.log(' ', magentaBright('mode'), buildConfig.mode);
|
||||
console.log(' ', magentaBright('tsconfig'), buildConfig.tsconfig);
|
||||
console.log(' ', magentaBright('env'), buildConfig.env);
|
||||
|
||||
const sernDir = resolve('.sern'),
|
||||
genDir = resolve(sernDir, 'generated'),
|
||||
ambientFilePath = resolve(sernDir, 'ambient.d.ts'),
|
||||
packageJsonPath = resolve('package.json'),
|
||||
sernTsConfigPath = resolve(sernDir, 'tsconfig.json'),
|
||||
packageJson = () => require(packageJsonPath);
|
||||
|
||||
if (!(await pathExists(genDir))) {
|
||||
console.log('Making .sern/generated dir, does not exist');
|
||||
await mkdir(genDir, { recursive: true });
|
||||
}
|
||||
|
||||
try {
|
||||
const defVersion = () => JSON.stringify(packageJson().version);
|
||||
const define = {
|
||||
...(buildConfig.define ?? {}),
|
||||
__DEV__: `${buildConfig.mode === 'development'}`,
|
||||
__PROD__: `${buildConfig.mode === 'production'}`,
|
||||
} satisfies Record<string, string>;
|
||||
|
||||
buildConfig.defineVersion && Object.assign(define, { __VERSION__: defVersion() });
|
||||
|
||||
await Preprocessor.writeTsConfig(buildConfig.format!, sernTsConfigPath, writeFile);
|
||||
await Preprocessor.writeAmbientFile(ambientFilePath, define, writeFile);
|
||||
|
||||
//https://esbuild.github.io/content-types/#tsconfig-json
|
||||
await esbuild.build({
|
||||
entryPoints,
|
||||
plugins: [imageLoader, ...(buildConfig.esbuildPlugins ?? [])],
|
||||
...defaultEsbuild(buildConfig.format!, buildConfig.tsconfig),
|
||||
define,
|
||||
dropLabels: [buildConfig.mode === 'production' ? '__DEV__' : '__PROD__', ...buildConfig.dropLabels!],
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
12
src/commands/extra.ts
Normal file
12
src/commands/extra.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import prompt from 'prompts';
|
||||
import { extraPrompt } from '../prompts/extra.js';
|
||||
import { create } from '../utilities/create.js';
|
||||
|
||||
export async function extra() {
|
||||
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);
|
||||
}
|
||||
13
src/commands/help.ts
Normal file
13
src/commands/help.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { cyanBright, green, magentaBright } from 'colorette';
|
||||
|
||||
export const help = `
|
||||
___ ___ _ __ _ __
|
||||
/ __|/ _ \\ '__| '_ \\
|
||||
\\__ \\ __/ | | | | |
|
||||
|___/\\___|_| |_| |_|
|
||||
|
||||
Welcome!
|
||||
|
||||
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://sern.dev/discord`)}`;
|
||||
123
src/commands/init.ts
Normal file
123
src/commands/init.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
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 { writeFile } from 'fs/promises';
|
||||
import { editDirs, editMain } from '../utilities/edits.js';
|
||||
import { cloneRepo, installDeps } from '../utilities/install.js';
|
||||
import { npm } from '../utilities/npm.js';
|
||||
import type { PackageManagerChoice } from '../utilities/types.js';
|
||||
|
||||
/** @deprecated Use npm create instead */
|
||||
export async function init(flags: Flags) {
|
||||
console.log(`${yellowBright('[WARN]:')} This command is deprecated, use ${greenBright('npm create @sern/bot')} instead`);
|
||||
|
||||
let data: PromptData;
|
||||
let git_init = true; // the default;
|
||||
let pm = flags.sync ? undefined : flags.y ? 'npm' : await npm();
|
||||
|
||||
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 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);
|
||||
|
||||
const requiredData = flags.sync !== undefined ? 3 : 4;
|
||||
const receivedData = Object.keys(data).length;
|
||||
const incompleteDataCondition = receivedData < requiredData;
|
||||
|
||||
if (incompleteDataCondition) process.exit(1);
|
||||
|
||||
if (!flags.sync) await cloneRepo(data.lang, data.name);
|
||||
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + data.name,
|
||||
});
|
||||
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
|
||||
await writeFile(pkg.replace('package.json', 'sern.config.json'), file);
|
||||
|
||||
if (flags.sync) {
|
||||
console.log('Project was successfully synced!');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
git_init ? await git(data) : console.log(`Skipping git init...\n`);
|
||||
|
||||
let choice: PackageManagerChoice;
|
||||
|
||||
if (pm === 'both') {
|
||||
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);
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
interface Data {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
y: boolean;
|
||||
sync: boolean;
|
||||
}
|
||||
|
||||
interface PromptData {
|
||||
name: string;
|
||||
lang: 'typescript' | 'javascript' | 'javascript-esm';
|
||||
main_dir: string;
|
||||
cmds_dir: string;
|
||||
}
|
||||
67
src/commands/list.ts
Normal file
67
src/commands/list.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { blueBright, bold, cyanBright, greenBright, italic, magentaBright, underline } from 'colorette';
|
||||
import { getSern } from '../utilities/getSern';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import type { CommandData, GuildId } from '../utilities/types';
|
||||
|
||||
export function list() {
|
||||
const files = getSern();
|
||||
if (!files.includes('command-data-remote.json')) {
|
||||
console.error(`No commands found\nPlease run ${cyanBright('sern commands publish')} to publish your commands`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const commands: Record<GuildId, CommandData[]> = JSON.parse(readFileSync('.sern/command-data-remote.json', 'utf-8'));
|
||||
const globalCommands = commands.global;
|
||||
|
||||
delete commands.global;
|
||||
console.log(bold('Global Commands'));
|
||||
for (const command of globalCommands) log(command);
|
||||
|
||||
console.log('\t');
|
||||
|
||||
for (const guildId in commands) {
|
||||
const guildCommands = commands[guildId];
|
||||
console.log(`${bold('Guild Commands')} [${underline(cyanBright(guildId))}]`);
|
||||
for (const command of guildCommands) log(command);
|
||||
}
|
||||
}
|
||||
|
||||
const AppCommandsType: Record<number, string> = {
|
||||
1: magentaBright('Slash'),
|
||||
2: magentaBright('User'),
|
||||
3: magentaBright('Message'),
|
||||
};
|
||||
|
||||
const AppCommandOptionType: Record<number, string> = {
|
||||
1: magentaBright('SubCommand'),
|
||||
2: magentaBright('SubCommand Group'),
|
||||
3: magentaBright('String'),
|
||||
4: magentaBright('Integer'),
|
||||
5: magentaBright('Boolean'),
|
||||
6: magentaBright('User'),
|
||||
7: magentaBright('Channel'),
|
||||
8: magentaBright('Role'),
|
||||
9: magentaBright('Mentionable'),
|
||||
10: magentaBright('Number'),
|
||||
11: magentaBright('Attachment'),
|
||||
};
|
||||
|
||||
function log(command: CommandData) {
|
||||
console.log(clean(`\t${cyanBright(command.name)} ${italic(command.description)} (${greenBright(command.id)})`));
|
||||
console.log(`\t Type: ${AppCommandsType[command.type]}`);
|
||||
|
||||
if (command.options) {
|
||||
console.log(`\t Options:`);
|
||||
for (const option of command.options) {
|
||||
console.log(`\t ${blueBright(option.name)}: ${AppCommandOptionType[option.type]}`);
|
||||
if (option.options) {
|
||||
console.log(`\t Options:`);
|
||||
for (const subOption of option.options) {
|
||||
console.log(`\t ${cyanBright(subOption.name)}: ${AppCommandOptionType[subOption.type]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clean = (str: string) => str.split(' ').filter(Boolean).join(' ');
|
||||
71
src/commands/plugins.ts
Normal file
71
src/commands/plugins.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { greenBright } from 'colorette';
|
||||
import fs from 'fs';
|
||||
import prompt from 'prompts';
|
||||
import { fetch } from 'undici';
|
||||
import { pluginsQ } from '../prompts/plugin.js';
|
||||
import { fromCwd } from '../utilities/fromCwd.js';
|
||||
import esbuild from 'esbuild';
|
||||
import { getLang } from '../utilities/getLang.js';
|
||||
import { resolve } from 'path';
|
||||
import { require } from '../utilities/require.js';
|
||||
interface PluginData {
|
||||
description: string;
|
||||
hash: string;
|
||||
name: string;
|
||||
author: string[];
|
||||
link: string;
|
||||
example: string;
|
||||
version: '1.0.0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs plugins to project
|
||||
*/
|
||||
export async function plugins() {
|
||||
const e: PluginData[] = (await prompt([await pluginsQ()])).list;
|
||||
if (!e) process.exit(1);
|
||||
|
||||
const lang = await getLang();
|
||||
for await (const plgData of e) {
|
||||
const pluginText = await download(plgData.link);
|
||||
const dir = fromCwd('/src/plugins');
|
||||
const linkNoExtension = `${process.cwd()}/src/plugins/${plgData.name}`;
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
if (lang === 'typescript') {
|
||||
fs.writeFileSync(linkNoExtension + '.ts', pluginText);
|
||||
} else {
|
||||
const { type = undefined } = require(resolve('package.json'));
|
||||
const format = type === undefined || type === 'cjs' ? 'cjs' : 'esm';
|
||||
const transformResult = await esbuild.transform(pluginText, {
|
||||
target: 'node18',
|
||||
format,
|
||||
loader: 'ts',
|
||||
banner: `/**\n Partial information: ${plgData.description}\n @author ${plgData.author}\n @example${plgData.example}*/`,
|
||||
});
|
||||
if (transformResult.warnings.length > 0) {
|
||||
console.log(transformResult.warnings.map((msg) => msg.text).join('\n'));
|
||||
}
|
||||
console.warn('transforming plugins with js strips comments');
|
||||
console.warn('We provided some minimal information at top of file, or view the documentation for this plugin here:');
|
||||
console.warn(plgData.link);
|
||||
fs.writeFileSync(linkNoExtension + '.js', transformResult.code);
|
||||
}
|
||||
}
|
||||
|
||||
const pluginNames = e.map((data) => {
|
||||
return 'Installed ' + data.name + ' ' + 'from ' + data.author.join(',');
|
||||
});
|
||||
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);
|
||||
|
||||
if (!data) throw new Error('Download failed! Kindly contact developers');
|
||||
|
||||
return data;
|
||||
}
|
||||
42
src/commands/publish.ts
Normal file
42
src/commands/publish.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { magentaBright } from 'colorette';
|
||||
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>) {
|
||||
if (!args.suppressWarnings) {
|
||||
console.info(`${magentaBright('EXPERIMENTAL')}: This API has not been stabilized. add -W or --suppress-warnings flag to suppress`);
|
||||
}
|
||||
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 {
|
||||
suppressWarnings: boolean;
|
||||
import: string[];
|
||||
token: string;
|
||||
applicationId: string;
|
||||
}
|
||||
5
src/commands/watch.ts
Normal file
5
src/commands/watch.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import esbuild from 'esbuild'
|
||||
|
||||
export async function watch(argv: unknown) {
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
270
src/create-publish.mts
Normal file
270
src/create-publish.mts
Normal file
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
console.log("preloading: ", preload);
|
||||
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 serialize = (permissions: unknown) => {
|
||||
if(typeof permissions === 'bigint' || typeof permissions === 'number') {
|
||||
return permissions.toString();
|
||||
}
|
||||
|
||||
if(Array.isArray(permissions)) {
|
||||
return permissions
|
||||
.reduce((acc, cur) => acc | cur, BigInt(0))
|
||||
.toString()
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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: serialize(config?.defaultMemberPermissions),
|
||||
},
|
||||
config,
|
||||
};
|
||||
};
|
||||
|
||||
// We can use these objects to publish to DAPI
|
||||
const publishableData = modules.map(makePublishData),
|
||||
token = process.env.token || process.env.DISCORD_TOKEN,
|
||||
appid = process.env.applicationId || process.env.APPLICATION_ID;
|
||||
|
||||
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) {
|
||||
globalCommands.length && spin.succeed(`All ${cyanBright('Global')} commands published`);
|
||||
globalCommandsResponse = await res.json();
|
||||
} else {
|
||||
spin.fail(`Failed to publish global commands [Code: ${redBright(res.status)}]`);
|
||||
switch(res.status) {
|
||||
case 400 :
|
||||
throw Error("400: Ensure your commands have proper fields and data with nothing left out");
|
||||
case 404 :
|
||||
throw Error("Forbidden 404. Is you application id and/or token correct?")
|
||||
case 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);
|
||||
})
|
||||
.catch(() => "No errors found (Unparsable json for a request with bad status code). Read the status code.")
|
||||
);
|
||||
console.error("Status Text ", 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}`);
|
||||
switch(response.status) {
|
||||
case 400 :
|
||||
throw Error("400: Ensure your commands have proper fields and data and nothing left out");
|
||||
case 404 :
|
||||
throw Error("Forbidden 404. Is you application id and/or token correct?")
|
||||
case 429:
|
||||
throw Error('Chill out homie, too many requests')
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
67
src/index.ts
Normal file
67
src/index.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Command } from 'commander';
|
||||
import { yellowBright } from 'colorette';
|
||||
export const program = new Command();
|
||||
|
||||
const importDynamic = async <T extends string>(filename: T) => import(`./commands/${filename}` as const);
|
||||
declare const __VERSION__: string;
|
||||
|
||||
program
|
||||
.name('sern')
|
||||
.description(await importDynamic('help.js').then((m) => m.help))
|
||||
.version(`sern CLI v${__VERSION__}`, '-v, --version')
|
||||
.exitOverride(() => process.exit(0));
|
||||
|
||||
program
|
||||
.command('init')
|
||||
.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(async (...args) => importDynamic('init.js').then((m) => m.init(...args)));
|
||||
|
||||
program
|
||||
.command('plugins')
|
||||
.description('Install plugins from https://github.com/sern-handler/awesome-plugins')
|
||||
.option('-n --name', 'Name of plugin')
|
||||
.action((...args) => importDynamic('plugins.js').then((m) => m.plugins(...args)));
|
||||
|
||||
program
|
||||
.command('extra')
|
||||
.description('Easy way to add extra things in your sern project')
|
||||
.action((...args) => importDynamic('extra.js').then((m) => m.extra(...args)));
|
||||
|
||||
program //
|
||||
.command('commands')
|
||||
.description('Defacto way to manage your slash commands')
|
||||
.addCommand(
|
||||
new Command('publish')
|
||||
.description('New way to manage your slash commands')
|
||||
.option('-W --suppress-warnings', 'suppress experimental warning')
|
||||
.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(async (...args) => importDynamic('publish.js').then((m) => m.publish(...args)))
|
||||
)
|
||||
.addCommand(
|
||||
new Command('list') //
|
||||
.description('List all slash commands')
|
||||
.action(async (...args) => importDynamic('list.js').then((m) => m.list(...args)))
|
||||
);
|
||||
|
||||
program
|
||||
.command('build')
|
||||
.description('Build your bot')
|
||||
.option('-f --format [fmt]', 'The module system of your application. `cjs` or `esm`', 'esm')
|
||||
.option('-m --mode [mode]', 'the mode for sern to build in. `production` or `development`', 'development')
|
||||
.option('-W --suppress-warnings', 'suppress experimental warning')
|
||||
.option('-p --project [filePath]', 'build with the provided sern.build file')
|
||||
.option('-e --env', 'path to .env file')
|
||||
.option('--tsconfig [filePath]', 'Use this tsconfig')
|
||||
.action(async (...args) => importDynamic('build.js').then((m) => m.build(...args)));
|
||||
program
|
||||
.command('watch')
|
||||
.description('start a hmr session')
|
||||
.action(async (...args) => importDynamic('watch.js').then((m) => m.watch(...args)))
|
||||
program.parse();
|
||||
39
src/plugins/imageLoader.ts
Normal file
39
src/plugins/imageLoader.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'node:path';
|
||||
import { require } from '../utilities/require.js';
|
||||
import { type Plugin } from 'esbuild';
|
||||
import { basename } from 'node:path';
|
||||
|
||||
export const validExtensions = ['.ts', '.js', '.json', '.png', '.jpg', '.jpeg', '.webp'];
|
||||
|
||||
//https://github.com/evanw/esbuild/issues/1051
|
||||
export const imageLoader = {
|
||||
name: 'attachment-loader',
|
||||
setup: (b) => {
|
||||
const filter = new RegExp(`\.${validExtensions.slice(3).join('|')}$`);
|
||||
b.onResolve({ filter }, (args) => {
|
||||
//if the module is being imported, resolve the path and transform to the js stub
|
||||
if (args.importer) {
|
||||
const newPath = path
|
||||
.format({ ...path.parse(args.path), base: '', ext: '.js' })
|
||||
.split(path.sep)
|
||||
.join(path.posix.sep);
|
||||
return { path: newPath, namespace: 'attachment-loader', external: true };
|
||||
}
|
||||
// if the file is actually the attachment, resolve the full dir
|
||||
return { path: require.resolve(args.path, { paths: [args.resolveDir] }), namespace: 'attachment-loader' };
|
||||
});
|
||||
|
||||
b.onLoad({ filter: /.*/, namespace: 'attachment-loader' }, async (args) => {
|
||||
const base64 = await fs.readFile(args.path).then((s) => s.toString('base64'));
|
||||
return {
|
||||
contents: `
|
||||
var __toBuffer = (base64) => Buffer.from(base64, "base64");
|
||||
module.exports = {
|
||||
name: '${basename(args.path)}',
|
||||
attachment: __toBuffer("${base64}")
|
||||
}`,
|
||||
};
|
||||
});
|
||||
},
|
||||
} satisfies Plugin;
|
||||
20
src/prompts/extra.ts
Normal file
20
src/prompts/extra.ts
Normal file
@@ -0,0 +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',
|
||||
},
|
||||
],
|
||||
};
|
||||
92
src/prompts/init.ts
Normal file
92
src/prompts/init.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
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',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const main_dir: PromptObject = {
|
||||
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),
|
||||
};
|
||||
|
||||
export const npmInit: PromptObject = {
|
||||
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,
|
||||
};
|
||||
|
||||
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',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const skip_install_dep: PromptObject = {
|
||||
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'),
|
||||
};
|
||||
31
src/prompts/plugin.ts
Normal file
31
src/prompts/plugin.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { Choice, PromptObject } from 'prompts';
|
||||
import { fetch } from 'undici';
|
||||
|
||||
async function gimmechoices(): Promise<Choice[]> {
|
||||
const link = `https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/pluginlist.json`;
|
||||
|
||||
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,
|
||||
}));
|
||||
|
||||
return choices;
|
||||
}
|
||||
|
||||
export async function pluginsQ(): Promise<PromptObject> {
|
||||
return {
|
||||
name: 'list',
|
||||
type: 'autocompleteMultiselect',
|
||||
message: 'What plugins do you want to install?',
|
||||
choices: await gimmechoices(),
|
||||
min: 1,
|
||||
};
|
||||
}
|
||||
|
||||
interface Data {
|
||||
name: string;
|
||||
link: 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: unknown) => {
|
||||
const guildCommandURL = new URL(`${appid}/guilds/${guildId}/commands`, baseURL);
|
||||
return fetch(guildCommandURL, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(guildCommand),
|
||||
headers,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
19
src/types/config.d.ts
vendored
Normal file
19
src/types/config.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface sernConfig {
|
||||
language: 'typescript' | 'javascript';
|
||||
paths: {
|
||||
base: string;
|
||||
commands: string;
|
||||
};
|
||||
scripts?: {
|
||||
prepublish?: string;
|
||||
};
|
||||
buildPath: string;
|
||||
rest?: Record<string, Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface TheoreticalEnv {
|
||||
DISCORD_TOKEN: string;
|
||||
APPLICATION_ID: string;
|
||||
MODE: 'PROD' | 'DEV';
|
||||
[name: string]: string;
|
||||
}
|
||||
51
src/utilities/create.ts
Normal file
51
src/utilities/create.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
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 extraURL = new URL('./extra/', templates);
|
||||
const extraFolder = fileURLToPath(extraURL);
|
||||
|
||||
/**
|
||||
* It creates a file with the name `name.lang.sern` in the `location` directory
|
||||
* @param name - The name of the file.
|
||||
* @param lang - The language you want to use.
|
||||
* @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`;
|
||||
|
||||
const target = no_ext ? `${location}/${name}` : `${location}/${name}.${lang}`;
|
||||
|
||||
return createFile(file, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* It reads a file from a template folder, and writes it to a target folder
|
||||
* @param template - The name of the file to be created.
|
||||
* @param target - The location of the file to be created.
|
||||
*/
|
||||
async function createFile(template: string, target: string) {
|
||||
const location = `${extraFolder}${template}`;
|
||||
|
||||
const file = await readFile(location, 'utf8');
|
||||
|
||||
await writeFileRecursive(target, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* It creates a directory recursively, then writes a file to it
|
||||
* @param target - The path to the file you want to write to.
|
||||
* @param data - The data to write to the file.
|
||||
* @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);
|
||||
|
||||
await mkdir(dir, { recursive: true });
|
||||
|
||||
return writeFile(resolvedTarget, data);
|
||||
}
|
||||
12
src/utilities/defaultEsbuildConfig.ts
Normal file
12
src/utilities/defaultEsbuildConfig.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type esbuild from 'esbuild';
|
||||
import { resolve } from 'path';
|
||||
|
||||
export default (format: 'cjs' | 'esm', tsconfig: string|undefined) =>
|
||||
({
|
||||
platform: 'node',
|
||||
format,
|
||||
tsconfig: tsconfig,
|
||||
logLevel: 'info',
|
||||
minify: false,
|
||||
outdir: resolve('dist'),
|
||||
} satisfies esbuild.BuildOptions);
|
||||
80
src/utilities/edits.ts
Normal file
80
src/utilities/edits.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { findUp } from 'find-up';
|
||||
import { readFile, rename, writeFile } from 'node:fs/promises';
|
||||
import { fromCwd } from './fromCwd.js';
|
||||
|
||||
/**
|
||||
* It takes a string, finds the package.json file in the directory of the string, and changes the name
|
||||
* of the package.json file to the string.
|
||||
* @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 output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
||||
if (!output) throw new Error("Can't read your package.json.");
|
||||
|
||||
output.name = name;
|
||||
|
||||
return writeFile(pjLocation, JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* It renames the `src` and `commands` directories, and edits the `index.ts` file to reflect the
|
||||
* changes
|
||||
* @param srcName - The name of the folder that will contain your main files.
|
||||
* @param cmds_dirName - The name of the directory where your commands will be stored.
|
||||
* @param name - The name of the folder you want to edit.
|
||||
* @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'
|
||||
) {
|
||||
const path = (await findUp('src', {
|
||||
cwd: fromCwd(name),
|
||||
type: 'directory',
|
||||
})) as string;
|
||||
|
||||
const ext = lang === 'typescript' ? 'ts' : 'js';
|
||||
|
||||
const newMainDir = path?.replace('src', srcName);
|
||||
await rename(path, newMainDir);
|
||||
|
||||
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 newCmdsPath = cmdsPath?.replace('commands', cmds_dirName);
|
||||
await rename(cmdsPath, newCmdsPath);
|
||||
|
||||
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;
|
||||
|
||||
await writeFile(tsconfig, JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
const output = await readFile(index, 'utf8');
|
||||
|
||||
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}'`);
|
||||
|
||||
return writeFile(index, edit);
|
||||
}
|
||||
5
src/utilities/fromCwd.ts
Normal file
5
src/utilities/fromCwd.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import path from 'path';
|
||||
|
||||
export function fromCwd(...dir: string[]) {
|
||||
return path.join(...[process.cwd(), ...dir]);
|
||||
}
|
||||
24
src/utilities/getConfig.ts
Normal file
24
src/utilities/getConfig.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
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;
|
||||
};
|
||||
buildPath: string;
|
||||
}
|
||||
18
src/utilities/getLang.ts
Normal file
18
src/utilities/getLang.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { findUp } from 'find-up';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
/**
|
||||
* It finds the sern.config.json file, reads it, and returns the language property
|
||||
* @returns The language of the project.
|
||||
*/
|
||||
export async function getLang(): Promise<'typescript' | 'javascript'> {
|
||||
const sernLocation = await findUp('sern.config.json');
|
||||
|
||||
if (!sernLocation) throw new Error("Can't find sern.config.json");
|
||||
|
||||
const output = JSON.parse(await readFile(sernLocation, 'utf8'));
|
||||
|
||||
if (!output) throw new Error("Can't read your sern.config.json.");
|
||||
|
||||
return output.language;
|
||||
}
|
||||
17
src/utilities/getSern.ts
Normal file
17
src/utilities/getSern.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { readdirSync } from 'node:fs';
|
||||
import { fromCwd } from './fromCwd';
|
||||
import { redBright, cyanBright } from 'colorette';
|
||||
|
||||
export function getSern() {
|
||||
let files: string[] = [];
|
||||
|
||||
try {
|
||||
const sern = fromCwd('.sern');
|
||||
files = readdirSync(sern);
|
||||
} catch (error) {
|
||||
console.error(`${redBright('Error:')} Could not locate ${cyanBright('.sern')} directory`);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
return files;
|
||||
}
|
||||
}
|
||||
84
src/utilities/install.ts
Normal file
84
src/utilities/install.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { redBright } from 'colorette';
|
||||
import { execa } from 'execa';
|
||||
import { findUp } from 'find-up';
|
||||
import fs from 'fs';
|
||||
import { readFile } from 'fs/promises';
|
||||
import ora from 'ora';
|
||||
import path from 'path';
|
||||
import type { PackageManagerChoice } from './types';
|
||||
|
||||
/**
|
||||
* It installs dependencies from a package.json file
|
||||
* @param choice - The package manager to use.
|
||||
* @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 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.");
|
||||
|
||||
if (choice === 'skip') {
|
||||
return console.log('Dependency installation skipped...');
|
||||
}
|
||||
|
||||
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!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the repo, copy the files from the repo to the new project directory, and delete the repo
|
||||
* @param lang - The language of the template
|
||||
* @param name - The name of the project
|
||||
*/
|
||||
export async function cloneRepo(lang: string, name: string) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the source is a directory, create the destination directory and then recursively copy the
|
||||
* contents of the source directory to the destination directory. If the source is not a directory,
|
||||
* copy the source file to the destination file
|
||||
* @param src - The source path.
|
||||
* @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 stats = (exists && fs.statSync(src)) as fs.Stats;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
25
src/utilities/npm.ts
Normal file
25
src/utilities/npm.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { execa } from 'execa';
|
||||
|
||||
/**
|
||||
* It checks if you have npm or yarn installed, and returns a string based on the result
|
||||
* @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 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 'yarn';
|
||||
}
|
||||
|
||||
if (npm_version && yarn_version) {
|
||||
return 'both';
|
||||
}
|
||||
}
|
||||
90
src/utilities/preprocessor.ts
Normal file
90
src/utilities/preprocessor.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
const declareConstType = (name: string, type: string) => String.raw`declare var ${name}: ${type}`;
|
||||
|
||||
const processEnvType = (env: NodeJS.ProcessEnv) => {
|
||||
const entries = Object.keys(env);
|
||||
|
||||
const envBuilder = new StringWriter();
|
||||
|
||||
for (const key of entries) {
|
||||
envBuilder.tab();
|
||||
envBuilder.tab();
|
||||
envBuilder.envField(key);
|
||||
}
|
||||
return envBuilder.build();
|
||||
};
|
||||
|
||||
const determineJSONType = (s: string) => {
|
||||
return typeof JSON.parse(s);
|
||||
};
|
||||
|
||||
type FileWriter = (path: string, content: string, format: BufferEncoding) => Promise<void>;
|
||||
const writeAmbientFile = async (path: string, define: Record<string, string>, writeFile: FileWriter) => {
|
||||
const fileContent = new StringWriter();
|
||||
for (const [k, v] of Object.entries(define)) {
|
||||
fileContent.varDecl(k, v);
|
||||
}
|
||||
fileContent
|
||||
.println('declare namespace NodeJS {')
|
||||
.tab()
|
||||
.println('interface ProcessEnv {')
|
||||
.envFields(process.env)
|
||||
.tab()
|
||||
.println('}')
|
||||
.println('}');
|
||||
|
||||
await writeFile(path, fileContent.build(), 'utf8');
|
||||
};
|
||||
|
||||
const writeTsConfig = async (format: 'cjs' | 'esm', configPath: string, fw: FileWriter) => {
|
||||
//maybe better way to do this
|
||||
const target = format === 'esm' ? { target: 'esnext' } : {};
|
||||
const sernTsConfig = {
|
||||
compilerOptions: {
|
||||
moduleResolution: 'node',
|
||||
strict: true,
|
||||
skipLibCheck: true,
|
||||
...target,
|
||||
rootDirs: ['./generated', '../src'],
|
||||
},
|
||||
include: ['./ambient.d.ts', '../src'],
|
||||
};
|
||||
|
||||
await fw(configPath, JSON.stringify(sernTsConfig, null, 3), 'utf8');
|
||||
};
|
||||
class StringWriter {
|
||||
private fileString = '';
|
||||
|
||||
tab() {
|
||||
this.fileString += ' ';
|
||||
return this;
|
||||
}
|
||||
|
||||
varDecl(name: string, type: string) {
|
||||
this.fileString += declareConstType(name, determineJSONType(type)) + '\n';
|
||||
return this;
|
||||
}
|
||||
|
||||
println(data: string) {
|
||||
this.fileString += data + '\n';
|
||||
return this;
|
||||
}
|
||||
envField(key: string) {
|
||||
if (/\s|\(|\)/g.test(key)) {
|
||||
this.fileString += `"${key}": string`;
|
||||
} else {
|
||||
this.fileString += key + ':' + 'string';
|
||||
}
|
||||
this.fileString += '\n';
|
||||
return this;
|
||||
}
|
||||
|
||||
envFields(env: NodeJS.ProcessEnv) {
|
||||
this.fileString += processEnvType(env);
|
||||
return this;
|
||||
}
|
||||
build() {
|
||||
return this.fileString;
|
||||
}
|
||||
}
|
||||
|
||||
export { writeAmbientFile, writeTsConfig };
|
||||
41
src/utilities/readPaths.ts
Normal file
41
src/utilities/readPaths.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { readdir, stat } from 'fs/promises';
|
||||
import { basename, join, extname } from 'path';
|
||||
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 deriveFileInfo(dir: string, file: string) {
|
||||
const fullPath = join(dir, file);
|
||||
return {
|
||||
fullPath,
|
||||
fileStats: await stat(fullPath),
|
||||
base: basename(file),
|
||||
};
|
||||
}
|
||||
|
||||
export 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;
|
||||
}
|
||||
}
|
||||
3
src/utilities/require.ts
Normal file
3
src/utilities/require.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
export const require = createRequire(import.meta.url);
|
||||
35
src/utilities/types.ts
Normal file
35
src/utilities/types.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export type PackageManagerChoice = 'skip' | 'npm' | 'yarn';
|
||||
|
||||
export type GuildId = string;
|
||||
|
||||
export interface CommandData {
|
||||
id: string;
|
||||
application_id: string;
|
||||
version: string;
|
||||
default_member_permissions?: string;
|
||||
type: number;
|
||||
name: string;
|
||||
name_localizations?: Record<string, string>;
|
||||
description: string;
|
||||
description_localizations?: Record<string, string>;
|
||||
dm_permission: boolean;
|
||||
guild_id: string;
|
||||
nsfw: boolean;
|
||||
options?: OptionData[];
|
||||
}
|
||||
|
||||
interface OptionData {
|
||||
type: number;
|
||||
name: string;
|
||||
name_localizations?: Record<string, string>;
|
||||
description: string;
|
||||
description_localizations?: Record<string, string>;
|
||||
required?: boolean;
|
||||
choices?: ChoiceData[];
|
||||
options?: OptionData[];
|
||||
}
|
||||
|
||||
interface ChoiceData {
|
||||
name: string;
|
||||
value: string | number;
|
||||
}
|
||||
11
templates/extra/Dockerfile.JS.sern
Normal file
11
templates/extra/Dockerfile.JS.sern
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM node:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD node src/index.js
|
||||
15
templates/extra/Dockerfile.TS.sern
Normal file
15
templates/extra/Dockerfile.TS.sern
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM node:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN npm install -D typescript
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN tsc --build || npx -p typescript tsc --build
|
||||
|
||||
CMD node dist/index.js
|
||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
26
tsup.config.ts
Normal file
26
tsup.config.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
import { createRequire } from 'node:module';
|
||||
const shared = {
|
||||
entry: [
|
||||
'src/index.ts',
|
||||
'src/create-publish.mts',
|
||||
'src/commands/**',
|
||||
],
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
};
|
||||
export default defineConfig({
|
||||
format: 'esm',
|
||||
target: 'node18',
|
||||
tsconfig: './tsconfig.json',
|
||||
outDir: './dist',
|
||||
treeshake: true,
|
||||
bundle: true,
|
||||
esbuildPlugins: [],
|
||||
platform: 'node',
|
||||
splitting: true,
|
||||
define: {
|
||||
__VERSION__: `"${createRequire(import.meta.url)('./package.json').version}"`,
|
||||
},
|
||||
...shared,
|
||||
});
|
||||
Reference in New Issue
Block a user