Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
twlite committed Dec 30, 2023
1 parent 48345f7 commit d7fc569
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 345 deletions.
24 changes: 20 additions & 4 deletions packages/commandkit/bin/common.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ export function findPackageJSON() {
return JSON.parse(fs.readFileSync(target, 'utf8'));
}

export function findTsconfig() {
const cwd = process.cwd();
const target = join(cwd, 'tsconfig.json');

if (!fs.existsSync(target)) {
return null;
}

return target;
}

const possibleFileNames = [
'commandkit.json',
'commandkit.config.json',
Expand All @@ -69,24 +80,29 @@ const possibleFileNames = [
'commandkit.config.cjs',
];

export async function findCommandKitConfig(src) {

export async function findCommandKitConfig(src, skipLoad = false) {
const cwd = process.cwd();
const locations = src ? [join(cwd, src)] : possibleFileNames.map((name) => join(cwd, name));

for (const location of locations) {
try {
return await loadConfigInner(location);
const conf = await loadConfigInner(location, skipLoad);
if (!conf) continue;
return conf;
} catch (e) {
continue;
}
}

if (skipLoad) return null;
panic('Could not locate commandkit config.');
}

async function loadConfigInner(target) {
async function loadConfigInner(target, skipLoad = false) {
const isJSON = target.endsWith('.json');

if (skipLoad) return fs.existsSync(target) ? target : null;

/**
* @type {import('..').CommandKitConfig}
*/
Expand Down
9 changes: 0 additions & 9 deletions packages/commandkit/bin/dependency-tracker.mjs

This file was deleted.

257 changes: 177 additions & 80 deletions packages/commandkit/bin/development.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,35 @@ import { parseEnv } from './parse-env.mjs';
import child_process from 'node:child_process';
import ora from 'ora';
import { injectShims } from './build.mjs';
import { CommandKit, CommandKitSignalType } from '../dist';
import { watchFiles } from './watcher.mjs';

const RESTARTING_MSG_PATTERN = /^Restarting '|".+'|"\n?$/;
const FAILED_RUNNING_PATTERN = /^Failed running '.+'|"\n?$/;

function readEnv(envExtra) {
const processEnv = {};
const env = dotenv({
path: join(process.cwd(), '.env'),
// @ts-expect-error
processEnv,
});

if (envExtra) {
parseEnv(processEnv);
}

if (env.error) {
write(Colors.yellow(`[DOTENV] Warning: ${env.error.message}`));
}

if (env.parsed) {
write(Colors.blue('[DOTENV] Loaded .env file!'));
}

return processEnv;
}

export async function bootstrapDevelopmentServer(opts) {
const {
src,
Expand Down Expand Up @@ -47,6 +72,22 @@ export async function bootstrapDevelopmentServer(opts) {

erase('.commandkit');

let watchEmitted = false, serverProcess = null, watching = false;
const watchModeMetadata = {
didEventsChange: false,
didCommandsChange: false,
didValidatorsChange: false,
didOthersChange: false,
};

const knownPaths = {
commands: '',
events: '',
validators: '',
source: join(process.cwd(), src),
config: await findCommandKitConfig(opts.config, true)
};

try {
await build({
clean: true,
Expand All @@ -61,107 +102,163 @@ export async function bootstrapDevelopmentServer(opts) {
silent: true,
entry: [src, '!dist', '!.commandkit', `!${outDir}`].filter(Boolean),
watch: watchMode,
});

await injectShims('.commandkit', main, false, requirePolyfill);
async onSuccess() {
await injectShims('.commandkit', main, false, requirePolyfill);
status.succeed(
Colors.green(`Dev server started in ${(performance.now() - start).toFixed(2)}ms!\n`),
);
const processEnv = readEnv(envExtra);
if (watchMode) {
if (!watchEmitted) { write(Colors.cyan('Watching for file changes...\n')); watchEmitted = true }
if (!watching) {
watchFiles(Object.values(knownPaths).filter(Boolean), (path) => {
watchModeMetadata.didCommandsChange = path === knownPaths.commands;
watchModeMetadata.didEventsChange = path === knownPaths.events;
watchModeMetadata.didValidatorsChange = path === knownPaths.validators;

status.succeed(
Colors.green(`Dev server started in ${(performance.now() - start).toFixed(2)}ms!\n`),
);

if (watchMode) write(Colors.cyan('Watching for file changes...\n'));

const processEnv = {};
watchModeMetadata.didOthersChange = [
watchModeMetadata.didCommandsChange,
watchModeMetadata.didEventsChange,
watchModeMetadata.didValidatorsChange,
].every(p => !p);
});
watching = true;
}
}

const env = dotenv({
path: join(process.cwd(), '.env'),
// @ts-expect-error
processEnv,
serverProcess = triggerRestart({
serverProcess,
processEnv,
main,
nodeOptions,
clearRestartLogs,
...watchModeMetadata,
});
}
});
} catch (e) {
status.fail(`Error occurred after ${(performance.now() - start).toFixed(2)}ms!\n`);
panic(e.stack ?? e);
}
}

if (envExtra) {
parseEnv(processEnv);
async function triggerRestart({
serverProcess,
processEnv,
main,
nodeOptions,
clearRestartLogs,
didEventsChange,
didCommandsChange,
didValidatorsChange,
didOthersChange
}) {
if (didOthersChange && serverProcess) {
serverProcess.kill();
} else if (!didOthersChange && serverProcess) {
/**
* @type {import('node:child_process').ChildProcessWithoutNullStreams}
*/
const commandkit = serverProcess;
if (didEventsChange) {
commandkit.send(CommandKitSignalType.ReloadEvents);
write(Colors.cyan('⌀ Reloading events...'));
}

if (env.error) {
write(Colors.yellow(`[DOTENV] Warning: ${env.error.message}`));
if (didCommandsChange) {
commandkit.send(CommandKitSignalType.ReloadCommands);
write(Colors.cyan('⌀ Reloading commands...'));
}

if (env.parsed) {
write(Colors.blue('[DOTENV] Loaded .env file!'));
if (didValidatorsChange) {
commandkit.send(CommandKitSignalType.ReloadValidations);
write(Colors.cyan('⌀ Reloading validators...'));
}

/**
* @type {child_process.ChildProcessWithoutNullStreams}
*/
const ps = child_process.spawn(
'node',
[...nodeOptions, join(process.cwd(), '.commandkit', main)],
{
env: {
...process.env,
...processEnv,
NODE_ENV: 'development',
// @ts-expect-error
COMMANDKIT_DEV: true,
// @ts-expect-error
COMMANDKIT_PRODUCTION: false,
},
cwd: process.cwd(),
return serverProcess;
}

return bootstrapNodeServer({
main,
nodeOptions,
processEnv,
clearRestartLogs,
});
}

function bootstrapNodeServer({
main,
nodeOptions,
processEnv,
clearRestartLogs,
}) {
/**
* @type {child_process.ChildProcessWithoutNullStreams}
*/
const ps = child_process.spawn(
'node',
[...nodeOptions.filter(o => o !== '--watch'), join(process.cwd(), '.commandkit', main)],
{
env: {
...process.env,
...processEnv,
NODE_ENV: 'development',
COMMANDKIT_DEV: true,
COMMANDKIT_PRODUCTION: false,
},
);
cwd: process.cwd(),
},
);

let isLastLogRestarting = false,
hasStarted = false;
let isLastLogRestarting = false,
hasStarted = false;

ps.stdout.on('data', (data) => {
const message = data.toString();
ps.stdout.on('data', (data) => {
const message = data.toString();

if (FAILED_RUNNING_PATTERN.test(message)) {
write(Colors.cyan('Failed running the bot, waiting for changes...'));
isLastLogRestarting = false;
if (FAILED_RUNNING_PATTERN.test(message)) {
write(Colors.cyan('Failed running the bot, waiting for changes...'));
isLastLogRestarting = false;
if (!hasStarted) hasStarted = true;
return;
}

if (clearRestartLogs && !RESTARTING_MSG_PATTERN.test(message)) {
write(message);
isLastLogRestarting = false;
} else {
if (isLastLogRestarting || !hasStarted) {
if (!hasStarted) hasStarted = true;
return;
}
write(Colors.cyan('⌀ Restarting the bot...'));
isLastLogRestarting = true;
}

if (clearRestartLogs && !RESTARTING_MSG_PATTERN.test(message)) {
write(message);
isLastLogRestarting = false;
} else {
if (isLastLogRestarting || !hasStarted) {
if (!hasStarted) hasStarted = true;
return;
}
write(Colors.cyan('⌀ Restarting the bot...'));
isLastLogRestarting = true;
}
if (!hasStarted) hasStarted = true;
});

if (!hasStarted) hasStarted = true;
});

ps.stderr.on('data', (data) => {
const message = data.toString();
ps.stderr.on('data', (data) => {
const message = data.toString();

if (
message.includes(
'ExperimentalWarning: Watch mode is an experimental feature and might change at any time',
)
if (
message.includes(
'ExperimentalWarning: Watch mode is an experimental feature and might change at any time',
)
return;
)
return;

write(Colors.red(message));
});
write(Colors.red(message));
});

ps.on('close', (code) => {
write('\n');
process.exit(code ?? 0);
});
ps.on('close', (code) => {
write('\n');
process.exit(code ?? 0);
});

ps.on('error', (err) => {
panic(err);
});
} catch (e) {
status.fail(`Error occurred after ${(performance.now() - start).toFixed(2)}ms!\n`);
panic(e.stack ?? e);
}
}
ps.on('error', (err) => {
panic(err);
});

return ps;
}
2 changes: 1 addition & 1 deletion packages/commandkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"commander": "^11.1.0",
"dotenv": "^16.3.1",
"ora": "^7.0.1",
"precinct": "^11.0.5",
"reflect-metadata": "^0.2.1",
"rfdc": "^1.3.0",
"rimraf": "^5.0.5",
"tsup": "^7.2.0"
Expand Down
Loading

0 comments on commit d7fc569

Please sign in to comment.