mirror of
https://github.com/ReVanced/revanced-bots.git
synced 2026-01-10 13:26:16 +00:00
chore: use alternative ways to bundle
This commit is contained in:
@@ -1,5 +1,2 @@
|
||||
# Safety measures, do not remove
|
||||
IS_USING_DOT_ENV=1
|
||||
|
||||
# Your Wit.ai token
|
||||
WIT_AI_TOKEN="YOUR_TOKEN_HERE"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"$schema": "./config.schema.json",
|
||||
|
||||
"address": "127.0.0.1",
|
||||
"port": 3000,
|
||||
"ocrConcurrentQueues": 3,
|
||||
"logLevel": "log"
|
||||
}
|
||||
@@ -42,4 +42,4 @@ The possible levels (sorted by their importance descendingly) are:
|
||||
|
||||
The next page will tell you how to run and bundle the server.
|
||||
|
||||
Continue: [🏃🏻♂️ Running the server](./2_running.md)
|
||||
Continue: [🏃🏻♂️ Running the server](./2_running_and_deploying.md)
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# 🏃🏻♂️ Running the server
|
||||
|
||||
There are many methods to run the server. Choose one that suits best for the situation.
|
||||
|
||||
## 👷🏻 Development mode (recommended)
|
||||
|
||||
There will be no compilation step, and Bun will automatically watch changes and restart the server for you.
|
||||
|
||||
You can quickly start the server by running:
|
||||
|
||||
```sh
|
||||
bun dev
|
||||
```
|
||||
|
||||
## 🌐 Production mode
|
||||
|
||||
Production mode runs no different from the development server, it simply has less debugging information printed to console by default. However, more production-specific features may come.
|
||||
|
||||
To start the server in production mode, you'll have to:
|
||||
|
||||
1. Set the `NODE_ENV` environment variable to `production`
|
||||
|
||||
> It is very possible to set the value in the `.env` file and let Bun load it, **but it is recommended to set the variable before Bun even starts**.
|
||||
|
||||
2. Start the server
|
||||
```sh
|
||||
bun dev
|
||||
```
|
||||
|
||||
## 📦 Building
|
||||
|
||||
If you're looking to build and host the server somewhere else, you can run:
|
||||
|
||||
```sh
|
||||
bun bundle
|
||||
```
|
||||
|
||||
The files will be placed in the `dist` directory. **Configurations and `.env` files will NOT be copied automatically.**
|
||||
|
||||
To start up the server, you'll need to install `tesseract.js` first.
|
||||
```sh
|
||||
bun install tesseract.js
|
||||
# or
|
||||
bun install tesseract.js -g
|
||||
|
||||
# Run the server
|
||||
bun run index.js
|
||||
```
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
The next page will tell you about packets.
|
||||
|
||||
Continue: [📨 Packets](./3_packets.md)
|
||||
59
apis/websocket/docs/2_running_and_deploying.md
Normal file
59
apis/websocket/docs/2_running_and_deploying.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# 🏃🏻♂️ Running and deploying the server
|
||||
|
||||
There are many methods to run the server. Choose one that suits best for the situation.
|
||||
|
||||
## 👷🏻 Development mode
|
||||
|
||||
There will be no compilation step, and Bun will automatically watch changes and restart the server for you.
|
||||
|
||||
You can quickly start the server by running:
|
||||
|
||||
```sh
|
||||
bun dev
|
||||
```
|
||||
|
||||
## 📦 Building
|
||||
|
||||
If you're looking to build and host the server somewhere else, you can run:
|
||||
|
||||
```sh
|
||||
bun run build
|
||||
```
|
||||
|
||||
The distribution files will be placed inside the `dist` directory. Inside will include:
|
||||
|
||||
- The default configuration for the API
|
||||
- Compiled source files of the API
|
||||
|
||||
You'll need to also copy the `node_modules` directory dereferenced if you want to run the distribution files somewhere else.
|
||||
|
||||
## ✈️ Deploying
|
||||
|
||||
To deploy the API, you'll need to:
|
||||
|
||||
1. [Build the API as seen in the previous step](#-building)
|
||||
|
||||
2. Copy contents of the `dist` directory
|
||||
|
||||
```sh
|
||||
# For instance, we'll copy them both to /usr/src/api
|
||||
cp -R ./dist/* /usr/src/api
|
||||
```
|
||||
|
||||
3. Replace the default configuration *(optional)*
|
||||
|
||||
4. Configure environment variables
|
||||
As seen in [`.env.example`](../.env.example). You can also optionally use a `.env` file which **Bun will automatically load**.
|
||||
|
||||
5. Finally, you can run the API using these commands
|
||||
|
||||
```sh
|
||||
cd /usr/src/api
|
||||
bun run index.js
|
||||
```
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
The next page will tell you about packets.
|
||||
|
||||
Continue: [📨 Packets](./3_packets.md)
|
||||
@@ -6,7 +6,7 @@
|
||||
"description": "🧦 WebSocket API server for bots assisting ReVanced",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"bundle": "bun build src/index.ts --outdir=dist --target=bun -e tesseract.js",
|
||||
"bundle": "bun run scripts/build.ts",
|
||||
"dev": "bun run src/index.ts --watch",
|
||||
"build": "bun bundle",
|
||||
"watch": "bun dev"
|
||||
@@ -30,9 +30,11 @@
|
||||
"@revanced/bot-shared": "workspace:*",
|
||||
"@sapphire/async-queue": "^1.5.2",
|
||||
"chalk": "^5.3.0",
|
||||
"tesseract.js": "^5.1.0"
|
||||
"tesseract.js": "^5.1.0",
|
||||
"ws": "^8.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.10",
|
||||
"typed-emitter": "^2.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
23
apis/websocket/scripts/build.ts
Normal file
23
apis/websocket/scripts/build.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createLogger } from '@revanced/bot-shared'
|
||||
import { cp } from 'fs/promises'
|
||||
|
||||
async function build(): Promise<void> {
|
||||
const logger = createLogger()
|
||||
|
||||
logger.info('Building Tesseract.js worker...')
|
||||
await Bun.build({
|
||||
entrypoints: ['../../node_modules/tesseract.js/src/worker-script/node/index.js'],
|
||||
target: 'bun',
|
||||
outdir: './dist/worker',
|
||||
})
|
||||
|
||||
logger.info('Building WebSocket API...')
|
||||
await Bun.build({
|
||||
entrypoints: ['./src/index.ts'],
|
||||
outdir: './dist',
|
||||
target: 'bun',
|
||||
})
|
||||
}
|
||||
|
||||
await build()
|
||||
await cp('config.json', 'dist/config.json')
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createWorker as createTesseractWorker } from 'tesseract.js'
|
||||
import { OEM, createWorker as createTesseractWorker } from 'tesseract.js'
|
||||
|
||||
import { join as joinPath } from 'path'
|
||||
import { inspect as inspectObject } from 'util'
|
||||
import { exists as pathExists } from 'fs/promises'
|
||||
|
||||
import Client from './classes/Client'
|
||||
|
||||
@@ -36,10 +38,6 @@ if (!['development', 'production'].includes(environment)) {
|
||||
|
||||
logger.info(`Running in ${environment} mode...`)
|
||||
|
||||
if (environment === 'production' && process.env['IS_USING_DOT_ENV']) {
|
||||
logger.warn('You seem to be using .env files, this is generally not a good idea in production...')
|
||||
}
|
||||
|
||||
if (!process.env['WIT_AI_TOKEN']) {
|
||||
logger.error('WIT_AI_TOKEN is not defined in the environment variables')
|
||||
process.exit(1)
|
||||
@@ -47,7 +45,14 @@ if (!process.env['WIT_AI_TOKEN']) {
|
||||
|
||||
// Workers and API clients
|
||||
|
||||
const tesseract = await createTesseractWorker('eng')
|
||||
const TesseractWorkerPath = joinPath(import.meta.dir, 'worker', 'index.js')
|
||||
const TesseractCompiledWorkerExists = await pathExists(TesseractWorkerPath)
|
||||
const tesseract = await createTesseractWorker(
|
||||
'eng',
|
||||
OEM.DEFAULT,
|
||||
TesseractCompiledWorkerExists ? { workerPath: TesseractWorkerPath } : undefined,
|
||||
)
|
||||
|
||||
const wit = {
|
||||
token: process.env['WIT_AI_TOKEN']!,
|
||||
async fetch(route: string, options?: RequestInit) {
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
"target": "ESNext",
|
||||
"lib": ["ESNext"],
|
||||
"composite": false,
|
||||
"skipLibCheck": true
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"include": ["./*.json", "src/**/*.ts"]
|
||||
"include": ["./*.json", "src/**/*.ts", "scripts/**/*.ts"]
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { PermissionFlagsBits } from 'discord.js'
|
||||
import type { Config } from './config.schema'
|
||||
|
||||
export default {
|
||||
owners: ['629368283354628116', '737323631117598811', '282584705218510848'],
|
||||
guilds: ['952946952348270622'],
|
||||
messageScan: {
|
||||
filter: {
|
||||
// Team, Mod, Immunity
|
||||
roles: ['952987191401926697', '955220417969262612', '1027874293192863765'],
|
||||
users: [],
|
||||
// Team, Development
|
||||
channels: ['952987428786941952', '953965039105232906'],
|
||||
whitelist: false,
|
||||
},
|
||||
humanCorrections: {
|
||||
falsePositiveLabel: 'false_positive',
|
||||
allow: {
|
||||
members: {
|
||||
// Team, Supporter
|
||||
roles: ['952987191401926697', '1019903194941362198'],
|
||||
permissions: PermissionFlagsBits.ManageMessages,
|
||||
},
|
||||
},
|
||||
},
|
||||
allowedAttachmentMimeTypes: ['image/jpeg', 'image/png', 'image/webp'],
|
||||
responses: [
|
||||
{
|
||||
triggers: {
|
||||
text: [{ label: 'false_positive', threshold: 0 }],
|
||||
},
|
||||
response: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
logLevel: 'debug',
|
||||
api: {
|
||||
url: 'ws://127.0.0.1:3000',
|
||||
disconnectLimit: 3,
|
||||
},
|
||||
} satisfies Config as Config
|
||||
@@ -1,18 +1,22 @@
|
||||
# ⚙️ Configuration
|
||||
|
||||
This page tells you how to configure the bot.
|
||||
|
||||
## 📄 JSON config
|
||||
|
||||
See [`config.ts`](../config.ts).
|
||||
|
||||
---
|
||||
|
||||
### `config.owners`
|
||||
#### `config.owners`
|
||||
|
||||
User IDs of the owners of the bot. Only add owners when needed.
|
||||
|
||||
### `config.guilds`
|
||||
#### `config.guilds`
|
||||
|
||||
Servers the bot is allowed to be and register commands in.
|
||||
|
||||
### `config.logLevel`
|
||||
#### `config.logLevel`
|
||||
|
||||
The level of logs to print to console. If the level is more important or equally important to set level, it will be forwarded to the console.
|
||||
|
||||
@@ -26,14 +30,42 @@ The possible levels (sorted by their importance descendingly) are:
|
||||
- `log`
|
||||
- `debug`
|
||||
|
||||
### `config.api.websocketUrl`
|
||||
#### `config.api.url`
|
||||
|
||||
The WebSocket URL to connect to (including port). Soon auto-discovery will be implemented.
|
||||
WebSocket URL to connect to (including port). Soon auto-discovery will be implemented.
|
||||
|
||||
### `config.messageScan`
|
||||
#### `config.api.disconnectLimit`
|
||||
|
||||
Amount of times to allow disconnecting before exiting with code `1`.
|
||||
|
||||
#### `config.messageScan`
|
||||
|
||||
[Please see the next page.](./2_adding_autoresponses.md)
|
||||
|
||||
#### `config.moderation`
|
||||
|
||||
TBD.
|
||||
|
||||
#### `config.rolePresets`
|
||||
|
||||
TBD.
|
||||
|
||||
## 🟰 Environment variables
|
||||
|
||||
See [`.env.example`](../.env.example).
|
||||
You can set environment variables in your shell or use a `.env` file which **Bun will automatically load**.
|
||||
|
||||
---
|
||||
|
||||
#### `DISCORD_TOKEN`
|
||||
|
||||
The Discord bot token.
|
||||
|
||||
#### `DATABASE_URL`
|
||||
|
||||
The database URL, since we're using SQLite, we'll be using the `file` protocol.
|
||||
Example values are: `file:./revanced.db`, `file:./db.sqlite`, `file:./discord_bot.sqlite`
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
The next page will tell you how to configure auto-responses.
|
||||
|
||||
@@ -86,4 +86,4 @@ filterOverride: {
|
||||
|
||||
The next page will tell you how to run and bundle the bot.
|
||||
|
||||
Continue: [🏃🏻♂️ Running the bot](./3_running.md)
|
||||
Continue: [🏃🏻♂️ Running the bot](./3_running_and_deploying.md)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# 🏃🏻♂️ Running the bot
|
||||
|
||||
There are two methods to run the bot. Choose one that suits best for the situation.
|
||||
|
||||
## 👷🏻 Development mode (recommended)
|
||||
|
||||
There will be no compilation step, and Bun will automatically watch changes and restart the bot for you.
|
||||
|
||||
You can quickly start the bot by running:
|
||||
|
||||
```sh
|
||||
bun dev
|
||||
```
|
||||
|
||||
## 📦 Building
|
||||
|
||||
There's unfortunately no way to build/bundle the bot yet due to how dynamic imports currently work, though we have a few ideas that may work.
|
||||
As a workaround, you can zip up the whole project, unzip, and run it in development mode using Bun.
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
The next page will tell you how to add commands and listen to events to the bot.
|
||||
|
||||
Continue: [✨ Adding commands and listening to events](./4_commands_and_events.md)
|
||||
68
bots/discord/docs/3_running_and_deploying.md
Normal file
68
bots/discord/docs/3_running_and_deploying.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 🏃🏻♂️ Running and deploying
|
||||
|
||||
There are two methods to run the bot. Choose one that suits best for the situation.
|
||||
|
||||
## 👷🏻 Development mode (recommended)
|
||||
|
||||
There will be no compilation step, and Bun will automatically watch changes and restart the bot for you.
|
||||
|
||||
You can quickly start the bot by running:
|
||||
|
||||
```sh
|
||||
bun dev
|
||||
```
|
||||
|
||||
## 📦 Building
|
||||
|
||||
To build the bot, you can run:
|
||||
|
||||
```sh
|
||||
bun run build
|
||||
```
|
||||
|
||||
The distribution files will be placed inside the `dist` directory. Inside will include:
|
||||
|
||||
- The default configuration for the bot
|
||||
- An empty database for the bot with schemas configured
|
||||
- Compiled source files of the bot
|
||||
|
||||
## ✈️ Deploying
|
||||
|
||||
To deploy the bot, you'll need to:
|
||||
|
||||
1. Replace the `config.ts` file with your own configuration _(optional)_
|
||||
2. [Build the bot as seen in the previous step](#-building)
|
||||
3. Run the `reload-slash-commands` script
|
||||
This is to ensure all commands are registered, so they can be used.
|
||||
**It may take up to 2 hours until **global** commands are updated. This is a Discord limitation.**
|
||||
|
||||
```sh
|
||||
# Assuming you're in the workspace's root (NOT REPOSITORY ROOT)
|
||||
bun run scripts/reload-slash-commands.ts
|
||||
```
|
||||
|
||||
4. Copy contents of the `dist` directory
|
||||
|
||||
```sh
|
||||
# For instance, we'll copy them both to /usr/src/discord-bot
|
||||
# Assuming you're in the workspace's root (NOT REPOSITORY ROOT)
|
||||
cp -R ./dist/* /usr/src/discord-bot
|
||||
```
|
||||
|
||||
5. Replace the default empty database with your own _(optional)_
|
||||
|
||||
6. Configure environment variables
|
||||
As seen in [`.env.example`](../.env.example). You can also optionally use a `.env` file which **Bun will automatically load**.
|
||||
|
||||
7. Finally, run the bot
|
||||
|
||||
```sh
|
||||
cd /usr/src/discord-bot
|
||||
bun run src/index.js
|
||||
```
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
The next page will tell you how to add commands and listen to events to the bot.
|
||||
|
||||
Continue: [✨ Adding commands and listening to events](./4_commands_and_events.md)
|
||||
@@ -74,34 +74,49 @@ export default {
|
||||
|
||||
Events are a bit different. We have 2 different event systems for both Discord API and our own bot API. This means the [`src/events`](../src/events) directory will have 2 separate directories inside. They are specific to the respective API, but the utility functions make the experience with both of them very similar.
|
||||
|
||||
To start adding events, you can use this template:
|
||||
To start adding events, you can use these templates:
|
||||
|
||||
##### Discord event template
|
||||
|
||||
```ts
|
||||
// For Discord events (remove functions you do not use)
|
||||
import { on, once } from '$utils/discord/events'
|
||||
import { on, once, withContext } from '$utils/discord/events'
|
||||
|
||||
// You will have auto-complete and types for all of them, don't worry!
|
||||
// WARNING: The first argument is the `context` object for Discord events
|
||||
// This is intended by design because Discord events usually always use it.
|
||||
on('eventName', async (context, arg1, arg2, ...) => {
|
||||
// Do something in here when the event is triggered
|
||||
on('eventName', async (arg1, arg2, ...) => {
|
||||
// Do something when the event is triggered
|
||||
})
|
||||
|
||||
once('eventName', async (arg1, arg2, ...) => {
|
||||
// Do something for only a single time after it's triggered, never again
|
||||
})
|
||||
|
||||
withContext(on, 'eventName', async (context, arg1, arg2, ...) => {
|
||||
// Do some other thing that requires the context object
|
||||
})
|
||||
```
|
||||
|
||||
##### API events template
|
||||
|
||||
```ts
|
||||
// For "Helper" events (remove functions you do not use)
|
||||
import { on, once } from '$utils/api/events'
|
||||
|
||||
// You will have auto-complete and types for all of them, don't worry!
|
||||
on('eventName', async (arg1, arg2, ...) => {
|
||||
// Do something in here when the event is triggered
|
||||
// Do something when the event is triggered
|
||||
})
|
||||
|
||||
once('eventName', async (arg1, arg2, ...) => {
|
||||
// Do something for only a single time after it's triggered, never again
|
||||
})
|
||||
```
|
||||
|
||||
API events are stored in [`src/events/api`](../src/events/api), and Discord events are in [`src/events/discord`](../src/events/discord).
|
||||
|
||||
### 📛 Event file naming conventions
|
||||
|
||||
Since a single event file can have multiple listeners, you should name exactly what the file handles.
|
||||
For example, when a nickname change happens, a member joins, or a member sends a message, the bot is required to cure their nickname. Therefore we would name the event file `curedRequired.ts`.
|
||||
|
||||
> [!NOTE]
|
||||
> If you need multiple event listeners for the same exact event, you can put them in a directory with the event name and rename the listeners to what they handle specifically. You can see how we do it in [`src/events/discord/interactionCreate`](../src/events/discord/interactionCreate).
|
||||
> If you need multiple event listeners for the same exact event **but also need more abstraction**, you can put them in a directory with the event name and rename the listeners to what they handle specifically. You can see how we do it in [`src/events/discord/interactionCreate`](../src/events/discord/interactionCreate).
|
||||
|
||||
## ⏭️ What's next
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
# 🫙 Storing data
|
||||
|
||||
We use SQLite to store every piece of persistent data. By using Bun, we get access to the `bun:sqlite` module which allows us to easily do SQLite operations.
|
||||
|
||||
## 🪄 Creating a database
|
||||
|
||||
You can easily create a database by initializing the `BasicDatabase` class:
|
||||
|
||||
```ts
|
||||
interface MyDatabase {
|
||||
field: string
|
||||
key: string
|
||||
}
|
||||
|
||||
const db = new BasicDatabase<MyDatabase>(
|
||||
// File path
|
||||
'database_file.db',
|
||||
// Database schema, in SQL
|
||||
`field TEXT NOT NULL, key TEXT PRIMARY KEY NOT NULL`,
|
||||
// Custom table name (optional, defaults to 'data'),
|
||||
'data'
|
||||
)
|
||||
```
|
||||
|
||||
## 📝 Writing data
|
||||
|
||||
Initializing `MyDatabase` will immediately create/open the `database_file.db` file. To write data, you can use the `insert` or `update` method:
|
||||
|
||||
```ts
|
||||
const key = 'my key'
|
||||
const field = 'some data'
|
||||
|
||||
// Order is according to the schema
|
||||
// db.insert(...columns)
|
||||
db.insert(field, key)
|
||||
|
||||
const field2 = 'some other data'
|
||||
|
||||
// db.update(data, filter)
|
||||
db.update({
|
||||
field: field2
|
||||
}, `key = ${key}`)
|
||||
```
|
||||
|
||||
You can also delete a row:
|
||||
|
||||
```ts
|
||||
db.delete(`key = ${key}`)
|
||||
|
||||
console.log(db.select(`key = ${key}`)) // null
|
||||
```
|
||||
|
||||
## 👀 Reading data
|
||||
|
||||
To get data using a filter, you can use the `select` method:
|
||||
|
||||
```ts
|
||||
// We insert it back
|
||||
db.insert(field, key)
|
||||
|
||||
const data = db.select('*', `key = ${key}`)
|
||||
console.log(data) // { key: 'my key', field: 'some other data' }
|
||||
|
||||
const { key: someKey } = db.select('key', `field = '${field2}'`)
|
||||
console.log(someKey) // 'my key'
|
||||
```
|
||||
|
||||
|
||||
If the existing abstractions aren't enough, you can also use the `run`, `prepare`, or `query` method:
|
||||
|
||||
```ts
|
||||
// Enable WAL
|
||||
db.run('PRAGMA journal_mode=WAL')
|
||||
|
||||
const selectFromKey = db.prepare('SELECT * FROM data WHERE key = $key')
|
||||
|
||||
console.log(
|
||||
selectFromKey.get({
|
||||
$key: key
|
||||
})
|
||||
) // { key: 'my key', field: 'some other data' }
|
||||
|
||||
console.log(
|
||||
selectFromKey.get({
|
||||
$key: 'non existent key'
|
||||
})
|
||||
) // null
|
||||
```
|
||||
@@ -4,13 +4,15 @@
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "🤖 Discord bot assisting ReVanced",
|
||||
"main": "dist/index.js",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"register": "bun run scripts/reload-slash-commands.ts",
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"prepare": "drizzle-kit push",
|
||||
"build": "tsc",
|
||||
"watch": "bun dev"
|
||||
"start": "bun run scripts/generate-indexes.ts && bun run src/index.ts",
|
||||
"dev": "bun run scripts/generate-indexes.ts && bun --watch src/index.ts",
|
||||
"build:config": "bun build config.ts --outdir=dist",
|
||||
"build": "bun prepare && bun build:config && bun build src/index.ts -e ./config.js --target=bun --outdir=dist/src && DATABASE_URL=dist/db.sqlite3 drizzle-kit push",
|
||||
"watch": "bun dev",
|
||||
"prepare": "bun run scripts/generate-indexes.ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -28,15 +30,18 @@
|
||||
},
|
||||
"homepage": "https://github.com/revanced/revanced-helper#readme",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.8.2",
|
||||
"@discordjs/rest": "^2.3.0",
|
||||
"@libsql/client": "^0.6.2",
|
||||
"@revanced/bot-api": "workspace:*",
|
||||
"@revanced/bot-shared": "workspace:*",
|
||||
"chalk": "^5.3.0",
|
||||
"decancer": "^3.2.2",
|
||||
"discord.js": "^14.15.3",
|
||||
"drizzle-kit": "^0.22.7",
|
||||
"drizzle-orm": "^0.31.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@libsql/client": "^0.6.2",
|
||||
"drizzle-kit": "^0.22.7"
|
||||
"discord-api-types": "^0.37.91"
|
||||
}
|
||||
}
|
||||
|
||||
6
bots/discord/scripts/generate-indexes.ts
Normal file
6
bots/discord/scripts/generate-indexes.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { join } from 'path'
|
||||
import { generateCommandsIndex, generateEventsIndex } from '../src/utils/fs'
|
||||
|
||||
await generateCommandsIndex(join(import.meta.dir, '../src/commands'))
|
||||
await generateEventsIndex(join(import.meta.dir, '../src/events/discord'))
|
||||
await generateEventsIndex(join(import.meta.dir, '../src/events/api'))
|
||||
@@ -2,12 +2,12 @@ import { inspect } from 'util'
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('eval')
|
||||
.setDescription('Evaluates something')
|
||||
.setDescription('Make the bot less sentient by evaluating code')
|
||||
.addStringOption(option => option.setName('code').setDescription('The code to evaluate').setRequired(true))
|
||||
.setDMPermission(true)
|
||||
.toJSON(),
|
||||
@@ -15,8 +15,7 @@ export default {
|
||||
ownerOnly: true,
|
||||
global: true,
|
||||
|
||||
// @ts-expect-error: Needed for science
|
||||
async execute(context, interaction) {
|
||||
async execute(_, interaction) {
|
||||
const code = interaction.options.getString('code', true)
|
||||
|
||||
await interaction.reply({
|
||||
|
||||
@@ -1,41 +1,26 @@
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('exception-test')
|
||||
.setDescription('throw up pls')
|
||||
.setDescription('Makes the bot intentionally hate you by throwing an exception')
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName('type')
|
||||
.setDescription('The type of exception to throw')
|
||||
.addChoices({
|
||||
name: 'process exception',
|
||||
value: 'Process',
|
||||
})
|
||||
.addChoices({
|
||||
name: 'generic error',
|
||||
value: 'Generic',
|
||||
})
|
||||
.addChoices({
|
||||
name: 'invalid argument',
|
||||
value: 'InvalidArgument',
|
||||
})
|
||||
.addChoices({
|
||||
name: 'invalid channel',
|
||||
value: 'InvalidChannel',
|
||||
})
|
||||
.addChoices({
|
||||
name: 'invalid user',
|
||||
value: 'InvalidUser',
|
||||
})
|
||||
.addChoices({
|
||||
name: 'invalid duration',
|
||||
value: 'InvalidDuration',
|
||||
})
|
||||
.setRequired(true),
|
||||
.setRequired(true)
|
||||
.addChoices(
|
||||
Object.keys(CommandErrorType).map(
|
||||
k =>
|
||||
({
|
||||
name: k,
|
||||
value: k,
|
||||
}) as const,
|
||||
),
|
||||
),
|
||||
)
|
||||
.setDMPermission(true)
|
||||
.toJSON(),
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder().setName('stop').setDescription('Stops the bot').setDMPermission(true).toJSON(),
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('stop')
|
||||
.setDescription(
|
||||
"You don't want to run this unless the bot starts to go insane, and like, you really need to stop it.",
|
||||
)
|
||||
.setDMPermission(true)
|
||||
.toJSON(),
|
||||
|
||||
ownerOnly: true,
|
||||
global: true,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
|
||||
|
||||
import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder().setName('coinflip').setDescription('Do a coinflip!').setDMPermission(true).toJSON(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SlashCommandBuilder, type TextBasedChannel } from 'discord.js'
|
||||
|
||||
import { config } from '$/context'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
||||
@@ -1,56 +1,16 @@
|
||||
import type { SlashCommandBuilder } from '@discordjs/builders'
|
||||
import type { ChatInputCommandInteraction } from 'discord.js'
|
||||
// AUTO-GENERATED BY A SCRIPT, DON'T TOUCH
|
||||
|
||||
// Temporary system
|
||||
export type Command = {
|
||||
data: ReturnType<SlashCommandBuilder['toJSON']>
|
||||
// The function has to return void or Promise<void>
|
||||
// because TS may complain about some code paths not returning a value
|
||||
/**
|
||||
* The function to execute when this command is triggered
|
||||
* @param interaction The interaction that triggered this command
|
||||
*/
|
||||
execute: (
|
||||
context: typeof import('../context'),
|
||||
interaction: ChatInputCommandInteraction,
|
||||
info: Info,
|
||||
) => Promise<void> | void
|
||||
memberRequirements?: {
|
||||
/**
|
||||
* The mode to use when checking for requirements.
|
||||
* - `all` means that the user needs meet all requirements specified.
|
||||
* - `any` means that the user needs to meet any of the requirements specified.
|
||||
*
|
||||
* @default "all"
|
||||
*/
|
||||
mode?: 'all' | 'any'
|
||||
/**
|
||||
* The permissions required to use this command (in BitFields).
|
||||
*
|
||||
* - **0n** means that everyone can use this command.
|
||||
* - **-1n** means that only bot owners can use this command.
|
||||
* @default -1n
|
||||
*/
|
||||
permissions?: bigint
|
||||
/**
|
||||
* The roles required to use this command.
|
||||
* By default, this is set to `[]`.
|
||||
*/
|
||||
roles?: string[]
|
||||
}
|
||||
/**
|
||||
* Whether this command can only be used by bot owners.
|
||||
* @default false
|
||||
*/
|
||||
ownerOnly?: boolean
|
||||
/**
|
||||
* Whether to register this command as a global slash command.
|
||||
* This is set to `false` and commands will be registered in allowed guilds only by default.
|
||||
* @default false
|
||||
*/
|
||||
global?: boolean
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
userIsOwner: boolean
|
||||
}
|
||||
import './index'
|
||||
import './fun/reply'
|
||||
import './fun/coinflip'
|
||||
import './development/eval'
|
||||
import './development/stop'
|
||||
import './development/exception-test'
|
||||
import './moderation/purge'
|
||||
import './moderation/cure'
|
||||
import './moderation/role-preset'
|
||||
import './moderation/mute'
|
||||
import './moderation/unmute'
|
||||
import './moderation/unban'
|
||||
import './moderation/slowmode'
|
||||
import './moderation/ban'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { config } from '$/context'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
import { config } from '$/context'
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { applyRolePreset } from '$/utils/discord/rolePresets'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
import { config } from '$/context'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
|
||||
@@ -4,7 +4,7 @@ import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { config } from '$/context'
|
||||
import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
||||
@@ -4,7 +4,7 @@ import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { sendPresetReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { applyRolePreset, removeRolePreset } from '$/utils/discord/rolePresets'
|
||||
import { parseDuration } from '$/utils/duration'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { config } from '$/context'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
import { config } from '$/context'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { removeRolePreset } from '$/utils/discord/rolePresets'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import type { Command } from '..'
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
||||
56
bots/discord/src/commands/types.ts
Normal file
56
bots/discord/src/commands/types.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { SlashCommandBuilder } from '@discordjs/builders'
|
||||
import type { ChatInputCommandInteraction } from 'discord.js'
|
||||
|
||||
// Temporary system
|
||||
export type Command = {
|
||||
data: ReturnType<SlashCommandBuilder['toJSON']>
|
||||
// The function has to return void or Promise<void>
|
||||
// because TS may complain about some code paths not returning a value
|
||||
/**
|
||||
* The function to execute when this command is triggered
|
||||
* @param interaction The interaction that triggered this command
|
||||
*/
|
||||
execute: (
|
||||
context: typeof import('../context'),
|
||||
interaction: ChatInputCommandInteraction,
|
||||
info: Info,
|
||||
) => Promise<void> | void
|
||||
memberRequirements?: {
|
||||
/**
|
||||
* The mode to use when checking for requirements.
|
||||
* - `all` means that the user needs meet all requirements specified.
|
||||
* - `any` means that the user needs to meet any of the requirements specified.
|
||||
*
|
||||
* @default "all"
|
||||
*/
|
||||
mode?: 'all' | 'any'
|
||||
/**
|
||||
* The permissions required to use this command (in BitFields).
|
||||
*
|
||||
* - **0n** means that everyone can use this command.
|
||||
* - **-1n** means that only bot owners can use this command.
|
||||
* @default -1n
|
||||
*/
|
||||
permissions?: bigint
|
||||
/**
|
||||
* The roles required to use this command.
|
||||
* By default, this is set to `[]`.
|
||||
*/
|
||||
roles?: string[]
|
||||
}
|
||||
/**
|
||||
* Whether this command can only be used by bot owners.
|
||||
* @default false
|
||||
*/
|
||||
ownerOnly?: boolean
|
||||
/**
|
||||
* Whether to register this command as a global slash command.
|
||||
* This is set to `false` and commands will be registered in allowed guilds only by default.
|
||||
* @default false
|
||||
*/
|
||||
global?: boolean
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
userIsOwner: boolean
|
||||
}
|
||||
@@ -4,13 +4,15 @@ import { createLogger } from '@revanced/bot-shared'
|
||||
import { ActivityType, Client as DiscordClient, Partials } from 'discord.js'
|
||||
import { drizzle } from 'drizzle-orm/bun-sqlite'
|
||||
|
||||
import config from '../config'
|
||||
// Export config first, as commands require them
|
||||
import config from '../config.js'
|
||||
export { config }
|
||||
|
||||
import * as commands from './commands'
|
||||
import * as schemas from './database/schemas'
|
||||
|
||||
import { loadCommands } from '$utils/discord/commands'
|
||||
import { pathJoinCurrentDir } from '$utils/fs'
|
||||
import type { Command } from './commands/types'
|
||||
|
||||
export { config }
|
||||
export const logger = createLogger({
|
||||
level: config.logLevel === 'none' ? Number.MAX_SAFE_INTEGER : config.logLevel,
|
||||
})
|
||||
@@ -59,5 +61,5 @@ export const discord = {
|
||||
],
|
||||
},
|
||||
}),
|
||||
commands: await loadCommands(pathJoinCurrentDir(import.meta.url, 'commands')),
|
||||
commands: Object.fromEntries(Object.values<Command>(commands).map((cmd) => [cmd.data.name, cmd])) as Record<string, Command>,
|
||||
} as const
|
||||
|
||||
5
bots/discord/src/events/api/index.ts
Normal file
5
bots/discord/src/events/api/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// AUTO-GENERATED BY A SCRIPT, DON'T TOUCH
|
||||
|
||||
import './ready'
|
||||
import './disconnect'
|
||||
import './index'
|
||||
10
bots/discord/src/events/discord/index.ts
Normal file
10
bots/discord/src/events/discord/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// AUTO-GENERATED BY A SCRIPT, DON'T TOUCH
|
||||
|
||||
import './ready'
|
||||
import './cureRequired'
|
||||
import './index'
|
||||
import './messageCreate/messageScanRequired'
|
||||
import './messageReactionAdd/correctResponse'
|
||||
import './interactionCreate/chatCommand'
|
||||
import './interactionCreate/correctResponse'
|
||||
import './guildMemberAdd/applyRolePresets'
|
||||
2
bots/discord/src/events/register.ts
Normal file
2
bots/discord/src/events/register.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import './discord'
|
||||
import './api'
|
||||
@@ -1,7 +1,8 @@
|
||||
import { api, discord, logger } from '$/context'
|
||||
import { listAllFilesRecursive, pathJoinCurrentDir } from '$utils/fs'
|
||||
import { getMissingEnvironmentVariables } from '@revanced/bot-shared'
|
||||
|
||||
import './events/register'
|
||||
|
||||
// Check if token exists
|
||||
const missingEnvs = getMissingEnvironmentVariables(['DISCORD_TOKEN', 'DATABASE_URL'])
|
||||
if (missingEnvs.length) {
|
||||
@@ -9,14 +10,5 @@ if (missingEnvs.length) {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
for (const event of listAllFilesRecursive(pathJoinCurrentDir(import.meta.url, 'events', 'api'))) {
|
||||
await import(event)
|
||||
}
|
||||
|
||||
api.client.connect()
|
||||
|
||||
for (const event of listAllFilesRecursive(pathJoinCurrentDir(import.meta.url, 'events', 'discord'))) {
|
||||
await import(event)
|
||||
}
|
||||
|
||||
discord.client.login()
|
||||
|
||||
5
bots/discord/src/types.d.ts
vendored
5
bots/discord/src/types.d.ts
vendored
@@ -1,5 +0,0 @@
|
||||
type IfExtends<T, U, True, False> = T extends U ? True : False
|
||||
type IfTrue<Condition, True, False> = IfExtends<Condition, true, True, False>
|
||||
type EmptyObject<K = PropertyKey> = Record<K, never>
|
||||
type ValuesOf<T> = T[keyof T]
|
||||
type MaybeArray<T> = T | T[]
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Command } from '$commands'
|
||||
import type { Command } from '$commands/types'
|
||||
import { listAllFilesRecursive } from '$utils/fs'
|
||||
|
||||
export const loadCommands = async (dir: string) => {
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import { readdirSync } from 'fs'
|
||||
import { dirname, join } from 'path'
|
||||
import { fileURLToPath } from 'bun'
|
||||
import { readdirSync, writeFileSync } from 'fs'
|
||||
import { join, relative } from 'path'
|
||||
|
||||
export const listAllFilesRecursive = (dir: string): string[] =>
|
||||
readdirSync(dir, { recursive: true, withFileTypes: true })
|
||||
.filter(x => x.isFile())
|
||||
.map(x => join(x.parentPath, x.name))
|
||||
|
||||
export const pathJoinCurrentDir = (importMetaUrl: string, ...objects: [string, ...string[]]) =>
|
||||
join(dirname(fileURLToPath(importMetaUrl)), ...objects)
|
||||
export const generateCommandsIndex = (dirPath: string) => generateIndexes(dirPath, x => !x.endsWith('types.ts'))
|
||||
|
||||
export const generateEventsIndex = (dirPath: string) => generateIndexes(dirPath)
|
||||
|
||||
const generateIndexes = async (dirPath: string, pathFilter?: (path: string) => boolean) => {
|
||||
const files = listAllFilesRecursive(dirPath)
|
||||
.filter(x => (x.endsWith('.ts') && !x.endsWith('index.ts') && pathFilter ? pathFilter(x) : true))
|
||||
.map(x => relative(dirPath, x))
|
||||
|
||||
writeFileSync(
|
||||
join(dirPath, 'index.ts'),
|
||||
`// AUTO-GENERATED BY A SCRIPT, DON'T TOUCH\n\n${files.map(c => `import './${c.split('.').at(-2)}'`).join('\n')}`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,8 +18,18 @@
|
||||
"$commands": ["./src/commands/index.ts"],
|
||||
"$commands/*": ["./src/commands/*"]
|
||||
},
|
||||
"skipLibCheck": true
|
||||
"skipLibCheck": true,
|
||||
"plugins": [
|
||||
{
|
||||
"transform": "typescript-transform-path-rewrite"
|
||||
}
|
||||
]
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"include": ["./**/*.ts", "./*.ts"]
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"./config.schema.ts",
|
||||
"./drizzle.config.ts"
|
||||
],
|
||||
"include": ["./src/**/*.ts", "./scripts/**/*.ts"]
|
||||
}
|
||||
|
||||
@@ -17,17 +17,24 @@ To start developing, you'll need to set up the development environment first.
|
||||
|
||||
3. Install dependencies
|
||||
|
||||
```sh
|
||||
bun install
|
||||
```
|
||||
```sh
|
||||
bun install
|
||||
```
|
||||
|
||||
4. Build packages/libraries
|
||||
4. Install Git hooks for linting (optional, but recommended)
|
||||
|
||||
```sh
|
||||
bun run build
|
||||
bunx lefthook install
|
||||
```
|
||||
|
||||
5. Change your directory to a project's root
|
||||
5. Build packages/libraries
|
||||
|
||||
```sh
|
||||
bun run build:packages
|
||||
```
|
||||
|
||||
6. Change your directory to a project's root
|
||||
|
||||
```sh
|
||||
# WebSocket API
|
||||
cd apis/websocket
|
||||
|
||||
11
package.json
11
package.json
@@ -6,14 +6,14 @@
|
||||
"license": "GPL-3.0-or-later",
|
||||
"type": "module",
|
||||
"author": "Palm <contact@palmdevs.me> (https://palmdevs.me)",
|
||||
"workspaces": ["apis/*", "bots/*", "packages/*"],
|
||||
"workspaces": ["packages/*", "apis/*", "bots/*"],
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
"build:packages": "turbo run build --filter=\"./packages/*\"",
|
||||
"watch": "turbo run watch",
|
||||
"flint": "biome check --apply .",
|
||||
"flint": "biome check --write .",
|
||||
"flint:check": "biome check .",
|
||||
"clint": "commitlint --edit",
|
||||
"prepare": "lefthook install"
|
||||
"clint": "commitlint --edit"
|
||||
},
|
||||
"homepage": "https://github.com/revanced/revanced-helper#readme",
|
||||
"repository": {
|
||||
@@ -27,6 +27,7 @@
|
||||
"Palm <contact@palmdevs.me> (https://palmdevs.me)",
|
||||
"ReVanced <nosupport@revanced.app> (https://revanced.app)"
|
||||
],
|
||||
"packageManager": "pnpm@9.4.0",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.8.2",
|
||||
"@commitlint/cli": "^19.3.0",
|
||||
@@ -38,7 +39,7 @@
|
||||
"concurrently": "^8.2.2",
|
||||
"conventional-changelog-conventionalcommits": "^7.0.2",
|
||||
"lefthook": "^1.6.18",
|
||||
"turbo": "^1.13.4",
|
||||
"turbo": "2",
|
||||
"typescript": "^5.5.2"
|
||||
},
|
||||
"trustedDependencies": ["@biomejs/biome", "esbuild", "lefthook"]
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"ws": "^8.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.10",
|
||||
"typed-emitter": "^2.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
"module": "ESNext",
|
||||
"composite": true,
|
||||
"noEmit": false
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
"module": "ESNext",
|
||||
"composite": true,
|
||||
"noEmit": false
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
||||
@@ -21,5 +21,7 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"isolatedModules": true,
|
||||
"allowImportingTsExtensions": false
|
||||
}
|
||||
},
|
||||
"include": ["./**/*"],
|
||||
"exclude": ["./packages/**/*"]
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"$schema": "https://turbo.build/schema.json",
|
||||
"pipeline": {
|
||||
"tasks": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**"],
|
||||
"outputMode": "errors-only"
|
||||
"outputLogs": "errors-only"
|
||||
},
|
||||
"watch": {
|
||||
"dependsOn": ["^watch"],
|
||||
"outputMode": "errors-only"
|
||||
"outputLogs": "errors-only"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user