feat: allow other CWD

This commit is contained in:
Isaac 2024-01-11 00:08:57 +00:00
parent 0e81c4833e
commit c596e237de
No known key found for this signature in database
GPG Key ID: 0DE40AE37BBA5C33
10 changed files with 104 additions and 43 deletions

5
.gitignore vendored
View File

@ -3,13 +3,10 @@
.vscode/ .vscode/
node_modules/ node_modules/
prisma/ prisma/
./user/
# files # files
*.env* *.env*
*.db* *.db*
*.log *.log
user/config.yml
user/**/*.*
!user/**/.gitkeep
!user/templates/*
summary.md summary.md

View File

@ -4,7 +4,7 @@ generator client {
datasource db { datasource db {
provider = "sqlite" provider = "sqlite"
url = "file:../user/database.db" url = env("DB_CONNECTION_URL")
} }
model ArchivedChannel { model ArchivedChannel {

View File

@ -4,9 +4,16 @@ const fs = require('fs-extra');
const util = require('util'); const util = require('util');
const exec = util.promisify(require('child_process').exec); const exec = util.promisify(require('child_process').exec);
const { short } = require('leeks.js'); const { short } = require('leeks.js');
const {
resolve, join,
} = require('path');
const fallback = { prisma: './node_modules/prisma/build/index.js' }; const fallback = { prisma: './node_modules/prisma/build/index.js' };
function pathify(path) {
return resolve(__dirname, '../', path);
}
function log(...strings) { function log(...strings) {
console.log(short('&9[postinstall]&r'), ...strings); console.log(short('&9[postinstall]&r'), ...strings);
} }
@ -24,7 +31,7 @@ async function npx(cmd) {
const { const {
stderr, stderr,
stdout, stdout,
} = await exec(cmd); } = await exec(cmd, { cwd: pathify('./') }); // { env } = process.env
if (stdout) console.log(stdout.toString()); if (stdout) console.log(stdout.toString());
if (stderr) console.log(stderr.toString()); if (stderr) console.log(stderr.toString());
} }
@ -42,15 +49,20 @@ if (!providers.includes(provider)) throw new Error(`DB_PROVIDER must be one of:
log(`provider=${provider}`); log(`provider=${provider}`);
log(`copying ${provider} schema & migrations`); log(`copying ${provider} schema & migrations`);
if (fs.existsSync('./prisma')) { if (fs.existsSync(pathify('./prisma'))) {
fs.rmSync('./prisma', { fs.rmSync('./prisma', {
force: true, force: true,
recursive: true, recursive: true,
}); });
} else { } else {
fs.mkdirSync('./prisma'); fs.mkdirSync(pathify('./prisma'));
}
fs.copySync(pathify(`./db/${provider}`), pathify('./prisma')); // copy schema & migrations
if (provider === 'sqlite' && !process.env.DB_CONNECTION_URL) {
process.env.DB_CONNECTION_URL = 'file:' + join(process.cwd(), './user/database.db');
log(`set DB_CONNECTION_URL=${process.env.DB_CONNECTION_URL}`);
} }
fs.copySync(`./db/${provider}`, './prisma'); // copy schema & migrations
(async () => { (async () => {
await npx('prisma generate'); await npx('prisma generate');

View File

@ -1,10 +1,16 @@
#!/bin/sh #!/usr/bin/env bash
source="${BASH_SOURCE}"
base_dir=$(dirname $(dirname "$source"))
echo "Checking environment..." echo "Checking environment..."
node scripts/preinstall script=scripts/preinstall
node "$base_dir/$script"
echo "Preparing the database..." echo "Preparing the database..."
node scripts/postinstall script=scripts/postinstall
node "$base_dir/$script"
echo "Starting..." echo "Starting..."
node src/ script=src/
node "$base_dir/$script"

View File

@ -15,7 +15,8 @@ const ms = require('ms');
module.exports = class Client extends FrameworkClient { module.exports = class Client extends FrameworkClient {
constructor(config, log) { constructor(config, log) {
super({ super(
{
intents: [ intents: [
...[ ...[
GatewayIntentBits.DirectMessages, GatewayIntentBits.DirectMessages,
@ -33,7 +34,9 @@ module.exports = class Client extends FrameworkClient {
Partials.Message, Partials.Message,
Partials.Reaction, Partials.Reaction,
], ],
}); },
{ baseDir: __dirname },
);
const locales = {}; const locales = {};
fs.readdirSync(join(__dirname, 'i18n')) fs.readdirSync(join(__dirname, 'i18n'))
@ -57,13 +60,19 @@ module.exports = class Client extends FrameworkClient {
const levels = ['error', 'info', 'warn']; const levels = ['error', 'info', 'warn'];
if (this.config.logs.level === 'debug') levels.push('query'); if (this.config.logs.level === 'debug') levels.push('query');
/** @type {PrismaClient} */ const prisma_options = {
this.prisma = new PrismaClient({
log: levels.map(level => ({ log: levels.map(level => ({
emit: 'event', emit: 'event',
level, level,
})), })),
}); };
if (process.env.DB_PROVIDER === 'sqlite' && !process.env.DB_CONNECTION_URL) {
prisma_options.datasources = { db: { url:'file:' + join(process.cwd(), './user/database.db') } };
}
/** @type {PrismaClient} */
this.prisma = new PrismaClient(prisma_options);
this.prisma.$on('error', e => this.log.error.prisma(`${e.target} ${e.message}`)); this.prisma.$on('error', e => this.log.error.prisma(`${e.target} ${e.message}`));
this.prisma.$on('info', e => this.log.info.prisma(`${e.target} ${e.message}`)); this.prisma.$on('info', e => this.log.info.prisma(`${e.target} ${e.message}`));

View File

@ -29,6 +29,7 @@ console.log(banner(pkg.version)); // print big title
const semver = require('semver'); const semver = require('semver');
const { colours } = require('leeks.js'); const { colours } = require('leeks.js');
const path = require('path');
// check node version // check node version
if (!semver.satisfies(process.versions.node, pkg.engines.node)) { if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
@ -36,6 +37,16 @@ if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
process.exit(1); process.exit(1);
} }
const base_dir = path.resolve(path.join(__dirname, '../'));
const cwd = path.resolve(process.cwd());
if (base_dir !== cwd) {
console.log('\x07' + colours.yellowBright('Warning: The current working directory is not the same as the base directory.'));
console.log(colours.yellowBright('This may result in unexpected behaviour, particularly with missing environment variables.'));
console.log(' Base directory: ' + colours.gray(base_dir));
console.log(' CWD: ' + colours.gray(cwd));
console.log(colours.blueBright(' Learn more at https://lnk.earth/dt-cwd.'));
}
// this could be done first, but then there would be no banner :( // this could be done first, but then there would be no banner :(
process.env.NODE_ENV ??= 'production'; // make sure NODE_ENV is set process.env.NODE_ENV ??= 'production'; // make sure NODE_ENV is set
require('./env').load(); // load and check environment variables require('./env').load(); // load and check environment variables
@ -46,16 +57,12 @@ const logger = require('./lib/logger');
const Client = require('./client'); const Client = require('./client');
const http = require('./http'); const http = require('./http');
// user directory may or may not exist depending on if sqlite is being used
// so the config file could be missing even though the directory exists
if (!fs.existsSync('./user/config.yml')) { if (!fs.existsSync('./user/config.yml')) {
const examplePath = './user/example.config.yml'; console.log('The config file does not exist, copying defaults...');
if (!fs.existsSync(examplePath)) { fs.cpSync(path.join(__dirname, 'user'), './user', { recursive: true });
console.log('\x07' + colours.redBright('The config file does not exist, and the example file is missing so cannot be copied from.')); console.log('Created user directory at', path.join(cwd, 'user'));
process.exit(1);
} else {
console.log('Creating config file...');
fs.copyFileSync(examplePath, './user/config.yml');
console.log(`Copied config to ${'./user/config.yml'}`);
}
} }
const config = YAML.parse(fs.readFileSync('./user/config.yml', 'utf8')); const config = YAML.parse(fs.readFileSync('./user/config.yml', 'utf8'));

View File

View File

@ -0,0 +1,30 @@
#{{ channelName }} ticket transcript
---
* ID: {{ ticket.id }} ({{ guildName }})
* Number: {{ ticket.category.name }} #{{ ticket.number }}
* Topic: {{ #ticket.topic }}{{ . }}{{ /ticket.topic }}{{ ^ticket.topic }}(no topic){{ /ticket.topic }}
* Created on: {{ #ticket }}{{ createdAtFull }}{{ /ticket }}
* Created by: {{ #ticket.createdBy }}"{{ displayName }}" @{{ username }}#{{ discriminator }}{{ /ticket.createdBy }}
* Closed on: {{ #ticket }}{{ closedAtFull }}{{ /ticket }}
* Closed by: {{ #ticket.closedBy }}"{{ displayName }}" @{{ username }}#{{ discriminator }}{{ /ticket.closedBy }}{{ ^ticket.closedBy }}(automated){{ /ticket.closedBy }}
* Closed because: {{ #ticket.closedReason }}{{ ticket.closedReason }}{{ /ticket.closedReason }}{{ ^ticket.closedReason }}(no reason){{ /ticket.closedReason }}
* Claimed by: {{ #ticket.claimedBy }}"{{ displayName }}" @{{ username }}#{{ discriminator }}{{ /ticket.claimedBy }}{{ ^ticket.claimedBy }}(not claimed){{ /ticket.claimedBy }}
{{ #ticket.feedback }}
* Feedback:
* Rating: {{ rating }}/5
* Comment: {{ comment }}{{ ^comment }}(no comment){{ /comment }}
{{ /ticket.feedback }}
* Participants:
{{ #ticket.archivedUsers }}
* "{{ displayName }}" @{{ username }}#{{ discriminator }} ({{ userId }})
{{ /ticket.archivedUsers }}
* Pinned messages: {{ #pinned }}{{ . }}{{ /pinned }}
---
{{ #ticket.archivedMessages }}
<{{ number }}> [{{ createdAtTimestamp }}] {{author.displayName}}: {{ text }}
{{ /ticket.archivedMessages }}

View File