Skip to content

Commit bbb9c89

Browse files
committed
chore: Update build scripts and dependencies for production environment
- Set NODE_ENV to production in build and start scripts - Update TypeScript version in pnpm-lock.yaml - Modify tsup configuration to enable bundling and treeshaking - Refactor asset path resolution for markdown loading in commands and events - Change deployment workflow to create a local .env file for production
1 parent def8f69 commit bbb9c89

File tree

9 files changed

+52
-22
lines changed

9 files changed

+52
-22
lines changed

.github/workflows/deploy.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ jobs:
5959
username: ${{ secrets.VPS_USER }}
6060
key: ${{ secrets.VPS_SSH_KEY }}
6161
script: |
62-
echo "DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }}" > /home/${{ secrets.VPS_USER }}/discord-bot/.env
63-
echo "CLIENT_ID=${{ secrets.CLIENT_ID }}" >> /home/${{ secrets.VPS_USER }}/discord-bot/.env
62+
echo "DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }}" > /home/${{ secrets.VPS_USER }}/discord-bot/.env.local
63+
echo "CLIENT_ID=${{ secrets.CLIENT_ID }}" >> /home/${{ secrets.VPS_USER }}/discord-bot/.env.local
64+
echo "NODE_ENV=production" >> /home/${{ secrets.VPS_USER }}/discord-bot/.env.local
6465
6566
- name: Extract and restart bot on VPS
6667
uses: appleboy/[email protected]
@@ -71,4 +72,4 @@ jobs:
7172
script: |
7273
cd /home/${{ secrets.VPS_USER }}/discord-bot/
7374
tar xzf bot-build.tar.gz
74-
pm2 restart bot || pm2 start ./dist/index.js --name bot
75+
pm2 restart bot || pm2 start ./dist/index.js --name bot --node-args="--env-file=.env.local"

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
"description": "Web Dev & Web Design discord bot",
55
"type": "module",
66
"scripts": {
7-
"build:ci": "npm run build:ts && npm run build:copy",
8-
"build:dev": "pnpm run build:ts && pnpm run build:copy",
7+
"build:ci": "NODE_ENV=production npm run build:ts && npm run build:copy",
8+
"build:dev": "NODE_ENV=production pnpm run build:ts && pnpm run build:copy",
99
"build:ts": "tsup",
1010
"build:copy": "node scripts/copy-assets.js",
11-
"start": "node dist/index.js",
11+
"start": "NODE_ENV=production node dist/index.js",
1212
"dev": "tsx watch src/index.ts",
1313
"deploy": "tsx src/util/deploy.ts",
1414
"lint": "biome lint .",
@@ -29,6 +29,7 @@
2929
"dependencies": {
3030
"@discordjs/core": "^2.2.2",
3131
"discord.js": "^14.22.1",
32+
"typescript": "^5.9.2",
3233
"web-features": "^3.3.0"
3334
},
3435
"devDependencies": {
@@ -37,8 +38,7 @@
3738
"husky": "^9.1.7",
3839
"lint-staged": "^16.2.1",
3940
"tsup": "^8.5.0",
40-
"tsx": "^4.20.6",
41-
"typescript": "^5.9.2"
41+
"tsx": "^4.20.6"
4242
},
4343
"lint-staged": {
4444
"*.{ts,js}": [

pnpm-lock.yaml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/guides/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { ApplicationCommandOptionType, ApplicationCommandType, MessageFlags } from 'discord.js';
22
import { logToChannel } from '../../util/channel-logging.js';
33
import { createCommand } from '../../util/commands.js';
4-
import { loadMarkdownOptions } from '../../util/markdown.js';
5-
6-
const subjectsDir = new URL('./subjects/', import.meta.url);
4+
import { loadMarkdownOptions, resolveAssetPath } from '../../util/markdown.js';
75

86
const subjectChoices = new Map<string, string>();
97

108
const loadChoices = async (): Promise<void> => {
9+
const subjectsDir = resolveAssetPath(
10+
'./subjects/',
11+
'./commands/guides/subjects/',
12+
import.meta.url
13+
);
1114
const choices = await loadMarkdownOptions<{ name: string }>(subjectsDir);
1215

1316
for (const { frontmatter, content } of choices) {

src/commands/tips/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { ApplicationCommandOptionType, ApplicationCommandType, MessageFlags } from 'discord.js';
22
import { logToChannel } from '../../util/channel-logging.js';
33
import { createCommand } from '../../util/commands.js';
4-
import { loadMarkdownOptions } from '../../util/markdown.js';
5-
6-
const subjectsDir = new URL('./subjects/', import.meta.url);
4+
import { loadMarkdownOptions, resolveAssetPath } from '../../util/markdown.js';
75

86
const subjectChoices = new Map<string, string>();
97

108
const loadChoices = async (): Promise<void> => {
9+
const subjectsDir = resolveAssetPath('./subjects/', './commands/tips/subjects/', import.meta.url);
1110
const choices = await loadMarkdownOptions<{ name: string }>(subjectsDir);
1211

1312
for (const { frontmatter, content } of choices) {

src/env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const config = {
1616
token: requireEnv('DISCORD_TOKEN'),
1717
clientId: requireEnv('CLIENT_ID'),
1818
},
19+
ENV: process.env.NODE_ENV,
1920
// Add more config sections as needed:
2021
// database: {
2122
// url: requireEnv('DATABASE_URL'),

src/events/just-ask.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Events } from 'discord.js';
22
import { MINUTE } from '../constants/time.js';
33
import { createEvent } from '../util/events.js';
4-
import { loadMarkdownOptions } from '../util/markdown.js';
4+
import { loadMarkdownOptions, resolveAssetPath } from '../util/markdown.js';
55
import { rateLimit } from '../util/rate-limit.js';
66

77
// Subject patterns (who)
@@ -26,10 +26,12 @@ const askToAskPattern = new RegExp(
2626

2727
const isAskingToAsk = (text: string) => askToAskPattern.test(text);
2828

29-
const [response] = await loadMarkdownOptions<{ name: string }>(
30-
new URL('../commands/tips/subjects/', import.meta.url),
31-
'justask.md'
29+
const justAskDir = resolveAssetPath(
30+
'../commands/tips/subjects/',
31+
'./commands/tips/subjects/',
32+
import.meta.url
3233
);
34+
const [response] = await loadMarkdownOptions<{ name: string }>(justAskDir, 'justask.md');
3335

3436
const { canRun, reset } = rateLimit(10 * MINUTE);
3537

src/util/markdown.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
import type { PathLike } from 'node:fs';
22
import { readdir, readFile } from 'node:fs/promises';
3+
import { config } from '../env.js';
4+
5+
/**
6+
* Resolves a path that works in both dev (src/) and prod (dist/) environments
7+
*
8+
* @param devPath - Path relative to the calling file in dev (e.g., './subjects/')
9+
* @param prodPath - Path relative to dist/index.js in prod (e.g., './commands/tips/subjects/')
10+
* @param baseUrl - import.meta.url from the calling file
11+
* @returns URL that works in both environments
12+
*/
13+
export const resolveAssetPath = (devPath: string, prodPath: string, baseUrl: string): URL => {
14+
const isProduction = config.ENV === 'production';
15+
const path = isProduction ? prodPath : devPath;
16+
return new URL(path, baseUrl);
17+
};
318

419
/**
520
* A simple markdown parser that extracts frontmatter and content

tsup.config.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
import { defineConfig } from 'tsup';
22

33
export default defineConfig({
4-
bundle: false,
4+
bundle: true,
55
clean: true,
66
dts: false,
77
outDir: 'dist',
88
format: ['esm'],
99
target: 'esnext',
10-
entry: ['src/**/*.ts', 'src/*.ts'],
11-
minify: true,
10+
entry: ['src/index.ts'],
11+
minify: false,
12+
external: [
13+
// Don't bundle discord.js - it has dynamic requires that don't work in ESM bundles
14+
'discord.js',
15+
'@discordjs/core',
16+
// Don't bundle typescript - it has dynamic requires that don't work in ESM bundles
17+
'typescript',
18+
],
19+
treeshake: true,
20+
shims: true,
1221
});

0 commit comments

Comments
 (0)