Skip to content

Commit

Permalink
prepare new template
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoobes committed Dec 23, 2023
1 parent fa3b220 commit a30cf79
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 167 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"build": "tsc"
},
"bin": {
"@sern/create-bot": "index.js",
"create-bot": "index.js",
"mkbot": "index.js"
},
"files": [
Expand Down
166 changes: 81 additions & 85 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,30 @@ import minimist from 'minimist';
import path from 'path';
import fs from 'fs';
import assert from 'node:assert';
import { spawn } from 'node:child_process';
import { spawn, } from 'node:child_process';
import { fileURLToPath } from 'node:url';

const argv = minimist<{
template?: string;
name?: string;
'no-build'?: boolean;
overwrite?: boolean;
install?: 'pnpm' | 'yarn' | 'npm';
}>(process.argv.slice(2), { boolean: true, '--': true });

const cwd = process.cwd();
const templateChoices = [
{
title: 'ts',
},
{
title: 'ts-esm',
},
{
title: 'js',
},
{
title: 'js-esm',
},
];
const packageDirectory = fileURLToPath(import.meta.url);
const metadataPath = path.resolve(packageDirectory, "../..", "metadata", "templateChoices.json");
const templateChoices =
JSON.parse(fs.readFileSync(metadataPath, 'utf8')) as { title: string, value: string }[];

const template: PromptObject = {
message: 'Choose template',
name: 'template',
type: 'select',
choices: templateChoices.map((t) => ({
title: t.title,
value: `template-${t.title}`,
title: t.title,
value: `template-${t.value}`,
})),
};
const name: PromptObject = {
Expand All @@ -46,6 +40,7 @@ const name: PromptObject = {
: 'Invalid name',
};


const which_manager: PromptObject = {
message: `Which manager do you want to use?`,
name: 'manager',
Expand Down Expand Up @@ -75,17 +70,17 @@ const which_manager: PromptObject = {
],
};
async function runInteractive() {
const result: prompt.Answers<'template' | 'name'> = await prompt(
const result: prompt.Answers<'template' | 'name' | 'manageBuild'> = await prompt(
[template, name],
{
onCancel: () => {
throw new Error(red('✖') + ' Operation cancelled');
},
onCancel: () => {
throw new Error(red('✖') + ' Operation cancelled');
},
}
);
const root = path.join(cwd, result.name);
const selectedTemplate = path.resolve(
fileURLToPath(import.meta.url),
packageDirectory,
'../..',
result.template
);
Expand All @@ -95,44 +90,45 @@ async function runInteractive() {
} else if (!fs.existsSync(root)) {
fs.mkdirSync(root, { recursive: true });
}

const configJson = createConfig(
(result.template as string).includes('ts')
);
(result.template as string).includes('ts'));
await createProject(
result.name,
configJson,
root,
selectedTemplate,
argv.overwrite
result.name,
configJson,
root,
selectedTemplate,
argv.overwrite
);

const installPkgs = await prompt([which_manager], {
onCancel: () => {
console.log('Canceled install '), process.exit(0);
},
onCancel: () => {
console.log('Canceled install '), process.exit(0);
},
});
runInstall(installPkgs.manager !== 'skip', root, installPkgs.manager);
}

async function runShort(
templateName: string,
name: string,
usebuild: boolean,
pkgManager?: 'yarn' | 'npm' | 'pnpm'
) {
const fullTemplateName = `template-${templateName}`;
const doesTemplateExist = templateChoices.some((tName) =>
tName.title.localeCompare(fullTemplateName, undefined, {
sensitivity: 'base',
})
tName.title.localeCompare(fullTemplateName, undefined, {
sensitivity: 'base',
})
);
if (!doesTemplateExist) {
throw new Error(red('✖') + ' Could not find template: ' + templateName);
}
const root = path.join(cwd, name);
const selectedTemplate = path.resolve(
fileURLToPath(import.meta.url),
'../..',
fullTemplateName
packageDirectory,
'../..',
fullTemplateName
);
if (argv.overwrite) {
emptyDir(root);
Expand All @@ -153,6 +149,7 @@ async function createProject(
selectedTemplate: string,
overwrite?: boolean
) {

console.log(
magentaBright(`overwrite`) +
`: ${overwrite ?? false};` +
Expand All @@ -162,52 +159,52 @@ async function createProject(
);
await copyFolderRecursiveAsync(selectedTemplate, root);
console.log(
`Writing ${magentaBright('sern.config.json')} to ${name}/sern.config.json`
`Writing ${magentaBright('sern.config.json')} to ${name}/sern.config.json`
);
console.log(`Writing ${magentaBright('dependencies.d.ts')}`);

await Promise.all([
fs.promises.writeFile(
path.join(root, 'sern.config.json'),
JSON.stringify(config, null, 2),
'utf8'
path.join(root, 'sern.config.json'),
JSON.stringify(config, null, 2),
'utf8'
),
fs.promises.writeFile(
path.join(root, 'src', 'dependencies.d.ts'),
await fs.promises.readFile(
path.resolve(
fileURLToPath(import.meta.url),
'../..',
'dependencies.d.txt'
packageDirectory,
'../..',
'dependencies.d.txt'
)
),
'utf8'
),
]);

}

async function runInstall(
runInstall: boolean,
cwd: string,
pkgManager?: 'yarn' | 'npm' | 'pnpm'
runInstall: boolean,
cwd: string,
pkgManager?: 'yarn' | 'npm' | 'pnpm'
) {
if (!runInstall) return;
console.log('Installing dependencies with ', magentaBright(pkgManager!));
spawn(pkgManager!, ['install'], { stdio: 'inherit', cwd, shell: true });
process.on('data', (s) => console.log(s.toString()));
process.on('error', (e) => {
console.error(e);
console.log(
red('Something went wrong with installing. Please do it yourself.')
);
console.log(red('Something went wrong with installing. Please do it yourself.'));
});
}

function createConfig(isTypescript: boolean) {
return {
language: isTypescript ? 'typescript' : 'javascript',
paths: {
base: 'src',
commands: 'commands',
base: 'src',
commands: 'commands',
},
};
}
Expand All @@ -217,20 +214,19 @@ async function init() {
if (!argv.template) {
await runInteractive();
} else {
assert(argv.name);
assert.match(
argv.name,
new RegExp(
'^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$',
'g'
)
);
await runShort(argv.template, argv.name, argv.install);
assert(argv.name);
assert.match(
argv.name,
new RegExp(
'^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$',
'g'),
"project name does not match the regular expression");
const usebuild = argv['no-build'] ?? true;
await runShort(argv.template, argv.name, usebuild, argv.install);
}
console.log(
magentaBright('Done!') +
' visit https://sern.dev for documentation and join https://sern.dev/discord! Happy hacking :)'
);
magentaBright('Done!')
+ ' visit https://sern.dev for documentation and join https://sern.dev/discord! Happy hacking :)');
}

function emptyDir(dir: string) {
Expand All @@ -239,37 +235,37 @@ function emptyDir(dir: string) {
}
for (const file of fs.readdirSync(dir)) {
if (file === '.git') {
continue;
continue;
}
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true });
}
}

async function copyFolderRecursiveAsync(source: string, target: string) {
try {
// Create target folder if it doesn't exist
if (!fs.existsSync(target)) {
fs.mkdirSync(target);
}
// Create target folder if it doesn't exist
if (!fs.existsSync(target)) {
fs.mkdirSync(target);
}

// Get all files and folders in the source folder
const files = await fs.promises.readdir(source);
// Get all files and folders in the source folder
const files = await fs.promises.readdir(source);

for (const file of files) {
const currentSource = path.join(source, file);
const currentTarget = path.join(target, file);
for (const file of files) {
const currentSource = path.join(source, file);
const currentTarget = path.join(target, file);

// Check if the current item is a file or a folder
const stats = await fs.promises.stat(currentSource);
// Check if the current item is a file or a folder
const stats = await fs.promises.stat(currentSource);

if (stats.isDirectory()) {
// Recursively copy the subfolder
await copyFolderRecursiveAsync(currentSource, currentTarget);
} else {
// Copy the file
await fs.promises.copyFile(currentSource, currentTarget);
}
}
if (stats.isDirectory()) {
// Recursively copy the subfolder
await copyFolderRecursiveAsync(currentSource, currentTarget);
} else {
// Copy the file
await fs.promises.copyFile(currentSource, currentTarget);
}
}
} catch (err) {
throw Error('An error occurred: ' + err);
}
Expand Down
2 changes: 1 addition & 1 deletion template-js-esm/src/commands/ping.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CommandType, commandModule } from '@sern/handler';

export default commandModule({
type: CommandType.Both,
plugins: [],
plugins: [], //optional
description: 'A ping command',
//alias : [],
execute: async (ctx, args) => {
Expand Down
13 changes: 5 additions & 8 deletions template-js-esm/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,18 @@ const client = new Client({
/**
* Where all of your dependencies are composed.
* '@sern/client' is usually your Discord Client.
* View documentation for pluggable dependencies
* Configure your dependency root to your liking.
* It follows the npm package iti https://itijs.org/.
* Use this function to access all of your dependencies.
* This is used for external event modules as well
*/
await makeDependencies({
build: (root) => root.add({ '@sern/client': single(() => client) }),
await makeDependencies(({ add }) => {
add('@sern/client', single(() => client));
});

//View docs for all options
Sern.init({
defaultPrefix: '!', // removing defaultPrefix will shut down text commands
commands: 'src/commands',
// events: 'src/events', //(optional)
defaultPrefix: '!', // removing defaultPrefix will shut down text commands
commands: 'src/commands',
// events: 'src/events', //(optional)
});

client.login();
2 changes: 1 addition & 1 deletion template-js/src/commands/ping.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { CommandType, commandModule } = require('@sern/handler');

exports.default = commandModule({
type: CommandType.Both,
plugins: [],
plugins: [], //optional
description: 'A ping command',
//alias : [],
execute: async (ctx, args) => {
Expand Down
7 changes: 2 additions & 5 deletions template-js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@ const client = new Client({
* Where all of your dependencies are composed.
* '@sern/client' is usually your Discord Client.
* View documentation for pluggable dependencies
* Configure your dependency root to your liking.
* It follows the npm package iti https://itijs.org/.
* Use this function to access all of your dependencies.
* This is used for external event modules as well
*/

async function init() {
await makeDependencies({
build: (root) => root.add({ '@sern/client': single(() => client) }),
await makeDependencies(({ add }) => {
add('@sern/client', single(() => client));
});

//View docs for all options
Expand Down
Loading

0 comments on commit a30cf79

Please sign in to comment.