Skip to content

Commit 00c839a

Browse files
committed
feat: improvements
1 parent 6ffd80b commit 00c839a

File tree

74 files changed

+854
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+854
-134
lines changed

.github/workflows/dev-redis.yaml

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: (CommandKit Redis) Publish Dev Build
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'packages/redis/**'
9+
10+
jobs:
11+
release:
12+
name: 🚀 Publish Dev Build
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: pnpm/action-setup@v2
16+
with:
17+
version: '9.15.0'
18+
19+
- name: 📚 Checkout
20+
uses: actions/checkout@v3
21+
22+
- name: 🟢 Node
23+
uses: actions/setup-node@v2
24+
with:
25+
node-version: 22
26+
registry-url: https://registry.npmjs.org
27+
28+
- name: 🍳 Prepare
29+
run: pnpm install
30+
31+
- name: 🔢 Update Version
32+
run: |
33+
cd packages/redis
34+
node -e "const pkg = require('./package.json'); \
35+
const newVersion = pkg.version + '-dev.' + new Date().toISOString().replace(/[:\-T]/g, '').substr(0,14); \
36+
pkg.version = newVersion; \
37+
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));"
38+
env:
39+
DEBIAN_FRONTEND: noninteractive
40+
41+
- name: 🧱 Build
42+
run: pnpm --filter './packages/redis' run build
43+
44+
- name: 🚚 Publish
45+
run: |
46+
cd packages/redis
47+
npm publish --access public --tag dev
48+
env:
49+
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}
50+
51+
- name: 🚫 Deprecate Previous Dev Version
52+
run: |
53+
PACKAGE_NAME=$(node -e "console.log(require('./packages/redis/package.json').name);")
54+
ALL_VERSIONS=$(npm info $PACKAGE_NAME versions -json)
55+
VERSION_TO_DEPRECATE=$(echo $ALL_VERSIONS | node -e "
56+
const versions = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
57+
const devVersions = versions.filter(v => v.includes('-dev.'));
58+
const versionToDeprecate = devVersions[devVersions.length - 2];
59+
console.log(versionToDeprecate);
60+
")
61+
echo Deprecating version $VERSION_TO_DEPRECATE
62+
npm deprecate $PACKAGE_NAME@$VERSION_TO_DEPRECATE "Deprecated dev version."
63+
64+
env:
65+
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}

apps/test-bot/commandkit.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from 'commandkit';
2+
3+
export default defineConfig({
4+
main: 'index.js',
5+
src: 'src',
6+
});

apps/test-bot/src/app/commands/prompt/middleware.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { MiddlewareContext } from 'commandkit';
1+
import { Logger, MiddlewareContext } from 'commandkit';
22
import { MessageFlags } from 'discord.js';
33

44
export function beforeExecute(ctx: MiddlewareContext) {
5-
console.log('Pre-command middleware');
5+
Logger.info('Pre-command middleware');
66

77
const user = ctx.isInteraction() ? ctx.interaction.user : ctx.message.author;
88

@@ -21,5 +21,5 @@ export function beforeExecute(ctx: MiddlewareContext) {
2121
}
2222

2323
export function afterExecute(ctx: MiddlewareContext) {
24-
console.log('Post-command middleware executed');
24+
Logger.info('Post-command middleware executed');
2525
}

apps/test-bot/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CommandKit } from 'commandkit';
22
import { Client } from 'discord.js';
3-
import 'dotenv/config';
3+
process.loadEnvFile();
44

55
const client = new Client({
66
intents: ['Guilds', 'GuildMembers', 'GuildMessages', 'MessageContent'],

packages/commandkit/src/app/commands/Context.ts

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
Locale,
77
Interaction,
88
UserContextMenuCommandInteraction,
9+
Client,
910
} from 'discord.js';
1011
import { CommandKit } from '../../CommandKit';
1112
import { Localization } from '../i18n/Localization';
@@ -97,6 +98,11 @@ export class Context<
9798
*/
9899
public readonly message: ContextParameters<ExecutionMode>['message'];
99100

101+
/**
102+
* The client instance.
103+
*/
104+
public readonly client: Client;
105+
100106
#store: Map<string, any>;
101107

102108
private _locale: Locale | null = null;
@@ -113,6 +119,7 @@ export class Context<
113119
// these are assigned to readonly properties to make them accessible via object destructuring
114120
this.interaction = config.interaction;
115121
this.message = config.message;
122+
this.client = commandkit.client;
116123
this.#store = config.store ?? new Map();
117124
}
118125

packages/commandkit/src/cache/cache.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,11 @@ export async function invalidate(tag: string): Promise<void> {
252252
(v) => v.key === tag || v.hash === tag,
253253
);
254254

255-
if (!entry) {
256-
throw new Error(`Cache key ${tag} was not found.`);
257-
}
255+
// if (!entry) {
256+
// throw new Error(`Cache key ${tag} was not found.`);
257+
// }
258+
259+
if (!entry) return;
258260

259261
await provider.delete(entry.key);
260262
}
@@ -280,9 +282,11 @@ export async function revalidate<T = unknown>(
280282
(v) => v.key === tag || v.hash === tag,
281283
);
282284

283-
if (!entry) {
284-
throw new Error(`Cache key ${tag} was not found.`);
285-
}
285+
// if (!entry) {
286+
// throw new Error(`Cache key ${tag} was not found.`);
287+
// }
288+
289+
if (!entry) return undefined as T;
286290

287291
await provider.delete(entry.key);
288292

packages/commandkit/src/cli/build.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { readFile, writeFile } from 'node:fs/promises';
44
import { join } from 'node:path';
55
import { build } from 'tsup';
66
import {
7-
Colors,
87
copyLocaleFiles,
98
erase,
109
findCommandKitConfig,
@@ -13,6 +12,7 @@ import {
1312
} from './common.js';
1413
import ora from 'ora';
1514
import { commandkitPlugin } from './esbuild-plugins/plugin';
15+
import colors from '../utils/colors.js';
1616

1717
export async function bootstrapProductionBuild(config: any) {
1818
const {
@@ -60,13 +60,13 @@ export async function bootstrapProductionBuild(config: any) {
6060
await injectShims(outDir, main, antiCrash, polyfillRequire);
6161

6262
status.succeed(
63-
Colors.green(
63+
colors.green(
6464
`Build completed in ${(performance.now() - start).toFixed(2)}ms!`,
6565
),
6666
);
6767
write(
68-
Colors.green(
69-
`\nRun ${Colors.magenta(`commandkit start`)} ${Colors.green(
68+
colors.green(
69+
`\nRun ${colors.magenta(`commandkit start`)} ${colors.green(
7070
'to start your bot.',
7171
)}`,
7272
),

packages/commandkit/src/cli/common.ts

+53-52
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,9 @@
33
import { rimrafSync } from 'rimraf';
44
import { join } from 'node:path';
55
import fs from 'node:fs';
6+
import colors from '../utils/colors';
67

7-
const resetColor = '\x1b[0m';
8-
9-
export const Colors = {
10-
reset: (text: string) => `${text}${resetColor}`,
11-
bright: (text: string) => `\x1b[1m${text}${resetColor}`,
12-
dim: (text: string) => `\x1b[2m${text}${resetColor}`,
13-
underscore: (text: string) => `\x1b[4m${text}${resetColor}`,
14-
blink: (text: string) => `\x1b[5m${text}${resetColor}`,
15-
reverse: (text: string) => `\x1b[7m${text}${resetColor}`,
16-
hidden: (text: string) => `\x1b[8m${text}${resetColor}`,
17-
18-
black: (text: string) => `\x1b[30m${text}${resetColor}`,
19-
red: (text: string) => `\x1b[31m${text}${resetColor}`,
20-
green: (text: string) => `\x1b[32m${text}${resetColor}`,
21-
yellow: (text: string) => `\x1b[33m${text}${resetColor}`,
22-
blue: (text: string) => `\x1b[34m${text}${resetColor}`,
23-
magenta: (text: string) => `\x1b[35m${text}${resetColor}`,
24-
cyan: (text: string) => `\x1b[36m${text}${resetColor}`,
25-
white: (text: string) => `\x1b[37m${text}${resetColor}`,
26-
27-
bgBlack: (text: string) => `\x1b[40m${text}${resetColor}`,
28-
bgRed: (text: string) => `\x1b[41m${text}${resetColor}`,
29-
bgGreen: (text: string) => `\x1b[42m${text}${resetColor}`,
30-
bgYellow: (text: string) => `\x1b[43m${text}${resetColor}`,
31-
bgBlue: (text: string) => `\x1b[44m${text}${resetColor}`,
32-
bgMagenta: (text: string) => `\x1b[45m${text}${resetColor}`,
33-
bgCyan: (text: string) => `\x1b[46m${text}${resetColor}`,
34-
bgWhite: (text: string) => `\x1b[47m${text}${resetColor}`,
35-
};
8+
let ts: typeof import('typescript') | undefined;
369

3710
export function write(message: any) {
3811
process.stdout.write(message);
@@ -42,8 +15,8 @@ export function write(message: any) {
4215
/**
4316
* @returns {never}
4417
*/
45-
export function panic(message: any) {
46-
write(Colors.red(`Error: ${message}`));
18+
export function panic(message: any): never {
19+
write(colors.red(`Error: ${message}`));
4720
process.exit(1);
4821
}
4922

@@ -59,17 +32,10 @@ export function findPackageJSON() {
5932
}
6033

6134
const possibleFileNames = [
62-
'commandkit.json',
63-
'commandkit.config.json',
6435
'commandkit.js',
65-
'commandkit.config.js',
6636
'commandkit.mjs',
67-
'commandkit.config.mjs',
6837
'commandkit.cjs',
69-
'commandkit.config.cjs',
7038
'commandkit.ts',
71-
'commandkit.mts',
72-
'commandkit.cts',
7339
];
7440

7541
export async function findCommandKitConfig(src: string) {
@@ -89,36 +55,71 @@ export async function findCommandKitConfig(src: string) {
8955
panic(`Could not locate commandkit config from ${cwd}`);
9056
}
9157

92-
function ensureTypeScript(target: string) {
93-
const isTypeScript = /\.(c|m)tsx?$/.test(target);
58+
async function ensureTypeScript(target: string) {
59+
const isTypeScript = /\.(c|m)?tsx?$/.test(target);
9460

95-
if (isTypeScript && !process.features.typescript) {
96-
panic(
97-
'You are trying to load commandkit config file that is written in typescript. The current Node.js version does not have TypeScript feature enabled.',
98-
);
61+
if (!isTypeScript) return false;
62+
if (process.features.typescript) return true;
63+
64+
if (!ts) {
65+
try {
66+
ts = await import('typescript');
67+
} catch {
68+
panic('TypeScript must be installed to use TypeScript config files.');
69+
}
9970
}
71+
72+
return true;
10073
}
10174

10275
async function loadConfigInner(target: string) {
103-
const isJSON = target.endsWith('.json');
104-
10576
await ensureExists(target);
10677

107-
ensureTypeScript(target);
78+
const isTs = await ensureTypeScript(target);
79+
80+
if (isTs && ts) {
81+
const { transpileModule } = ts;
82+
const src = fs.readFileSync(target, 'utf8');
83+
const { outputText } = transpileModule(src, {
84+
compilerOptions: {
85+
module: ts.ModuleKind.ESNext,
86+
target: ts.ScriptTarget.ESNext,
87+
moduleResolution: ts.ModuleResolutionKind.NodeNext,
88+
},
89+
fileName: target,
90+
});
91+
92+
const nodeModulesPath = join(
93+
process.cwd(),
94+
'node_modules',
95+
'.commandkit_tmp',
96+
);
97+
98+
fs.mkdirSync(nodeModulesPath, { recursive: true });
99+
100+
const tmpFile = join(nodeModulesPath, 'compiled-commandkit.config.mjs');
101+
102+
fs.writeFileSync(tmpFile, outputText);
103+
104+
target = tmpFile;
105+
}
108106

109107
/**
110108
* @type {import('..').CommandKitConfig}
111109
*/
112-
// @ts-ignore
113-
const config = await import(`file://${target}`, {
114-
with: isJSON ? { type: 'json' } : undefined,
115-
}).then((conf) => conf.default || conf);
110+
const config = await import(`file://${target}`)
111+
.then((conf) => conf.default || conf)
112+
.catch(console.log);
116113

117114
return config;
118115
}
119116

120117
async function ensureExists(loc: string) {
121-
await fs.promises.access(loc, fs.constants.F_OK);
118+
const exists = fs.existsSync(loc);
119+
120+
if (!exists) {
121+
throw new Error(`File not found: ${loc}`);
122+
}
122123
}
123124

124125
export function erase(dir: string) {

0 commit comments

Comments
 (0)