diff --git a/src/index.ts b/src/index.ts index 3876d09..64f5f98 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,46 +4,48 @@ import minimist from 'minimist'; import path from 'path'; import fs from 'fs'; import assert from 'node:assert'; -import { spawn } from 'node:child_process' -import { fileURLToPath } from 'node:url' +import { spawn } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; const argv = minimist<{ - template?: string; - name?: string; - overwrite?: boolean; - install?: 'pnpm' | 'yarn' | 'npm' + template?: string; + name?: string; + 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' - }, + { + title: 'ts', + }, + { + title: 'ts-esm', + }, + { + title: 'js', + }, + { + title: 'js-esm', + }, ]; const template: PromptObject = { - message: 'Choose template', - name: 'template', - type: 'select', - choices: templateChoices.map(t => ({ title: t.title, value: `template-${t.title}` }) ) + message: 'Choose template', + name: 'template', + type: 'select', + choices: templateChoices.map((t) => ({ + title: t.title, + value: `template-${t.title}`, + })), }; const name: PromptObject = { - message: 'What is your project name?', - name: 'name', - type: 'text', - validate: (name: string) => - name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$') - ? true - : 'Invalid name', + message: 'What is your project name?', + name: 'name', + type: 'text', + validate: (name: string) => + name.match('^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$') + ? true + : 'Invalid name', }; - const which_manager: PromptObject = { message: `Which manager do you want to use?`, name: 'manager', @@ -61,10 +63,10 @@ const which_manager: PromptObject = { value: 'yarn', }, { - title: 'PNPM', - description: 'PNPM Package Manager', - value: 'pnpm', - }, + title: 'PNPM', + description: 'PNPM Package Manager', + value: 'pnpm', + }, { title: 'Skip', description: 'Skip selection', @@ -73,150 +75,204 @@ const which_manager: PromptObject = { ], }; async function runInteractive() { - const result: prompt.Answers<'template'|'name'> = await prompt([ - template, - name, - ], - { - onCancel: () => { - throw new Error(red('✖') + ' Operation cancelled') - }, - }, - ); - const root = path.join(cwd, result.name); - const selectedTemplate =path.resolve( - fileURLToPath(import.meta.url), - "../..", - result.template - ); - console.log(selectedTemplate) - if (argv.overwrite) { - emptyDir(root); - } else if (!fs.existsSync(root)) { - fs.mkdirSync(root, { recursive: true }) - } - const configJson = createConfig((result.template as string).includes('typescript')) - await createProject(result.name, configJson, root, selectedTemplate, argv.overwrite); - - const installPkgs = await prompt([which_manager], { onCancel: () => { console.log("Canceled install "), process.exit(0) } }); - runInstall(installPkgs.manager !== 'skip', root, installPkgs.manager); + const result: prompt.Answers<'template' | 'name'> = await prompt( + [template, name], + { + onCancel: () => { + throw new Error(red('✖') + ' Operation cancelled'); + }, + } + ); + const root = path.join(cwd, result.name); + const selectedTemplate = path.resolve( + fileURLToPath(import.meta.url), + '../..', + result.template + ); + console.log(selectedTemplate); + if (argv.overwrite) { + emptyDir(root); + } else if (!fs.existsSync(root)) { + fs.mkdirSync(root, { recursive: true }); + } + const configJson = createConfig( + (result.template as string).includes('typescript') + ); + await createProject( + result.name, + configJson, + root, + selectedTemplate, + argv.overwrite + ); + const installPkgs = await prompt([which_manager], { + onCancel: () => { + console.log('Canceled install '), process.exit(0); + }, + }); + runInstall(installPkgs.manager !== 'skip', root, installPkgs.manager); } +async function runShort( + templateName: string, + name: string, + pkgManager?: 'yarn' | 'npm' | 'pnpm' +) { + const fullTemplateName = `template-${templateName}`; + const doesTemplateExist = templateChoices.some((tName) => + 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 + ); + if (argv.overwrite) { + emptyDir(root); + } else if (!fs.existsSync(root)) { + fs.mkdirSync(root, { recursive: true }); + } + const configJson = createConfig(templateName.includes('typescript')); -async function runShort(templateName: string, name:string, pkgManager?: 'yarn'|'npm'|'pnpm') { - const fullTemplateName = `template-${templateName}`; - const doesTemplateExist = templateChoices - .some(tName => 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 - ); - if (argv.overwrite) { - emptyDir(root); - } else if (!fs.existsSync(root)) { - fs.mkdirSync(root, { recursive: true }) - } - const configJson = createConfig(templateName.includes('typescript')); - - await createProject(name, configJson, root, selectedTemplate, argv.overwrite); - - runInstall(Boolean(pkgManager), root, pkgManager); + await createProject(name, configJson, root, selectedTemplate, argv.overwrite); + + runInstall(Boolean(pkgManager), root, pkgManager); } -async function createProject(name: string, config: Record, root: string, selectedTemplate: string, overwrite?: boolean) { - console.log(magentaBright(`overwrite`)+ `: ${overwrite ?? false};`+`\n`+magentaBright('copy')+`: ${selectedTemplate} ${root}`); - await copyFolderRecursiveAsync(selectedTemplate , root); - console.log(`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), 'utf8'), - fs.promises.writeFile( - path.join(root, 'src', 'dependencies.d.ts'), - await fs.promises.readFile(path.resolve(fileURLToPath(import.meta.url), '../..', 'dependencies.d.txt')), 'utf8') - ]); - +async function createProject( + name: string, + config: Record, + root: string, + selectedTemplate: string, + overwrite?: boolean +) { + console.log( + magentaBright(`overwrite`) + + `: ${overwrite ?? false};` + + `\n` + + magentaBright('copy') + + `: ${selectedTemplate} ${root}` + ); + await copyFolderRecursiveAsync(selectedTemplate, root); + console.log( + `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), + 'utf8' + ), + fs.promises.writeFile( + path.join(root, 'src', 'dependencies.d.ts'), + await fs.promises.readFile( + path.resolve( + fileURLToPath(import.meta.url), + '../..', + 'dependencies.d.txt' + ) + ), + 'utf8' + ), + ]); } -async function runInstall(runInstall: boolean, cwd: string, pkgManager?:'yarn'|'npm'|'pnpm') { - if(!runInstall) return; - console.log('Installing dependencies with ', magentaBright(pkgManager!)); - spawn(pkgManager!, ['install'], { stdio: 'inherit', cwd }); - 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.')) - }) +async function runInstall( + runInstall: boolean, + cwd: string, + pkgManager?: 'yarn' | 'npm' | 'pnpm' +) { + if (!runInstall) return; + console.log('Installing dependencies with ', magentaBright(pkgManager!)); + spawn(pkgManager!, ['install'], { stdio: 'inherit', cwd }); + 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.') + ); + }); } function createConfig(isTypescript: boolean) { - return { - language : isTypescript ? 'typescript' : 'javascript', - paths: { - base: 'src', - cmds_dir: 'commands' - } - } + return { + language: isTypescript ? 'typescript' : 'javascript', + paths: { + base: 'src', + cmds_dir: 'commands', + }, + }; } async function init() { - console.log(`Working in: `+ cwd); - 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); - } - console.log(magentaBright('Done!')+ ' visit https://sern.dev for documentation and join https://sern.dev/discord! Happy hacking :)' ); + console.log(`Working in: ` + cwd); + 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); + } + console.log( + magentaBright('Done!') + + ' visit https://sern.dev for documentation and join https://sern.dev/discord! Happy hacking :)' + ); } function emptyDir(dir: string) { - if (!fs.existsSync(dir)) { - return - } - for (const file of fs.readdirSync(dir)) { - if (file === '.git') { - continue - } - fs.rmSync(path.resolve(dir, file), { recursive: true, force: true }) - } + if (!fs.existsSync(dir)) { + return; + } + for (const file of fs.readdirSync(dir)) { + if (file === '.git') { + 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); - } + try { + // 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); - } - } - } catch (err) { - throw Error('An error occurred: '+ err); - } + 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); + } } init(); - diff --git a/template-js-esm/package.json b/template-js-esm/package.json index f0f5b8a..62dc343 100644 --- a/template-js-esm/package.json +++ b/template-js-esm/package.json @@ -1,24 +1,24 @@ { - "name": "js-example", - "version": "1.0.0", - "description": "", - "private": true, - "main": "src/index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "javacsript", - "sern", - "discord.js" - ], - "license": "UNLICENSED", - "dependencies": { - "@sern/handler": "^latest", - "discord.js": "latest" - }, - "devDependencies": { - "@types/node": "^17.0.25" - }, - "type": "module" + "name": "js-example", + "version": "1.0.0", + "description": "", + "private": true, + "main": "src/index.js", + "scripts": { + "test": "node ./src/index.js" + }, + "keywords": [ + "javacsript", + "sern", + "discord.js" + ], + "license": "UNLICENSED", + "dependencies": { + "@sern/handler": "latest", + "discord.js": "latest" + }, + "devDependencies": { + "@types/node": "^17.0.25" + }, + "type": "module" } diff --git a/template-js-esm/src/index.js b/template-js-esm/src/index.js index f7eb9bf..e9e914b 100644 --- a/template-js-esm/src/index.js +++ b/template-js-esm/src/index.js @@ -20,16 +20,14 @@ const client = new Client({ * This is used for external event modules as well */ await makeDependencies({ - build: (root) => - root - .add({ '@sern/client': single(() => client) }) + build: (root) => root.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), + // events: 'src/events', //(optional) }); client.login(); diff --git a/template-js/package.json b/template-js/package.json index 6d4db39..bc9370a 100644 --- a/template-js/package.json +++ b/template-js/package.json @@ -1,23 +1,23 @@ { - "name": "js-example", - "version": "1.0.0", - "description": "", - "private": true, - "main": "src/index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "javacsript", - "sern", - "discord.js" - ], - "license": "UNLICENSED", - "dependencies": { - "@sern/handler": "^latest", - "discord.js": "latest" - }, - "devDependencies": { - "@types/node": "^17.0.25" - } + "name": "js-example", + "version": "1.0.0", + "description": "", + "private": true, + "main": "src/index.js", + "scripts": { + "test": "node ./src/index.js" + }, + "keywords": [ + "javacsript", + "sern", + "discord.js" + ], + "license": "UNLICENSED", + "dependencies": { + "@sern/handler": "latest", + "discord.js": "latest" + }, + "devDependencies": { + "@types/node": "^17.0.25" + } } diff --git a/template-js/src/index.js b/template-js/src/index.js index 1dc4070..925cc44 100644 --- a/template-js/src/index.js +++ b/template-js/src/index.js @@ -21,17 +21,16 @@ const client = new Client({ */ async function init() { - await makeDependencies({ - build: (root) => - root.add({ '@sern/client': single(() => client) }) - }); + await makeDependencies({ + build: (root) => root.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), - }); + //View docs for all options + Sern.init({ + defaultPrefix: '!', // removing defaultPrefix will shut down text commands + commands: 'src/commands', + // events: 'src/events', //(optional) + }); } init(); diff --git a/template-ts-esm/package.json b/template-ts-esm/package.json index 855a07c..9952173 100644 --- a/template-ts-esm/package.json +++ b/template-ts-esm/package.json @@ -1,26 +1,25 @@ { - "name": "ts-example", - "version": "1.0.0", - "description": "", - "main": "dist/index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc", - "start": "tsc && node ./dist/index.js" - }, - "keywords": [ - "typescript", - "sern", - "discord.js" - ], - "license": "UNLICENSED", - "dependencies": { - "@sern/handler": "^latest", - "discord.js": "^latest" - }, - "devDependencies": { - "@types/node": "^17.0.25", - "typescript": "5.0" - }, - "type": "module" + "name": "ts-example", + "version": "1.0.0", + "description": "", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "start": "tsc && node ./dist/index.js" + }, + "keywords": [ + "typescript", + "sern", + "discord.js" + ], + "license": "UNLICENSED", + "dependencies": { + "@sern/handler": "latest", + "discord.js": "latest" + }, + "devDependencies": { + "@types/node": "^17.0.25", + "typescript": "5.0" + }, + "type": "module" } diff --git a/template-ts-esm/src/index.ts b/template-ts-esm/src/index.ts index 37af360..d79c84b 100644 --- a/template-ts-esm/src/index.ts +++ b/template-ts-esm/src/index.ts @@ -1,9 +1,5 @@ import { Client, GatewayIntentBits } from 'discord.js'; -import { - Sern, - makeDependencies, - single, -} from '@sern/handler'; +import { Sern, makeDependencies, single } from '@sern/handler'; const client = new Client({ intents: [ @@ -24,15 +20,14 @@ const client = new Client({ * This is used for external event modules as well */ await makeDependencies({ - build: (root) => - root.add({ '@sern/client': single(() => client) }) + build: (root) => root.add({ '@sern/client': single(() => client) }), }); //View docs for all options Sern.init({ defaultPrefix: '!', // removing defaultPrefix will shut down text commands commands: 'dist/commands', - // events: 'dist/events' (optional), + // events: 'dist/events', //(optional) }); client.login(); diff --git a/template-ts-esm/tsconfig.json b/template-ts-esm/tsconfig.json index 4f0157c..25e2f20 100644 --- a/template-ts-esm/tsconfig.json +++ b/template-ts-esm/tsconfig.json @@ -1,16 +1,16 @@ { - "compilerOptions": { - "resolveJsonModule": true, - "target": "ESNext", - "module": "ESNext", - "outDir": "dist", - "rootDir": "src", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": true, - "strictNullChecks": true, - "importsNotUsedAsValues": "error", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true - } + "compilerOptions": { + "moduleResolution": "nodenext", + "resolveJsonModule": true, + "target": "ESNext", + "module": "ESNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "noImplicitAny": true, + "strictNullChecks": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } } diff --git a/template-ts/package.json b/template-ts/package.json index f5135a1..222470a 100644 --- a/template-ts/package.json +++ b/template-ts/package.json @@ -1,25 +1,24 @@ { - "name": "ts-example", - "version": "1.0.0", - "private": true, - "description": "", - "main": "dist/index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc", - "start": "tsc && node ./dist/index.js" - }, - "keywords": [ - "typescript", - "sern", - "discord.js" - ], - "dependencies": { - "@sern/handler": "^latest", - "discord.js": "latest" - }, - "devDependencies": { - "@types/node": "^17.0.25", - "typescript": "^5.0" - } + "name": "ts-example", + "version": "1.0.0", + "private": true, + "description": "", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "start": "tsc && node ./dist/index.js" + }, + "keywords": [ + "typescript", + "sern", + "discord.js" + ], + "dependencies": { + "@sern/handler": "latest", + "discord.js": "latest" + }, + "devDependencies": { + "@types/node": "^17.0.25", + "typescript": "^5.0" + } } diff --git a/template-ts/src/index.ts b/template-ts/src/index.ts index 6c34015..eef4a50 100644 --- a/template-ts/src/index.ts +++ b/template-ts/src/index.ts @@ -1,9 +1,5 @@ import { Client, GatewayIntentBits } from 'discord.js'; -import { - Sern, - single, - makeDependencies -} from '@sern/handler'; +import { Sern, single, makeDependencies } from '@sern/handler'; const client = new Client({ intents: [ @@ -24,18 +20,16 @@ const client = new Client({ * This is used for external event modules as well */ async function init() { - await makeDependencies({ - build: (root) => - root.add({ '@sern/client': single(() => client) }) - }); - - //View docs for all options - Sern.init({ - defaultPrefix: '!', // removing defaultPrefix will shut down text commands - commands: 'dist/commands', - // events: 'dist/events' (optional), - }); + await makeDependencies({ + build: (root) => root.add({ '@sern/client': single(() => client) }), + }); + + //View docs for all options + Sern.init({ + defaultPrefix: '!', // removing defaultPrefix will shut down text commands + commands: 'dist/commands', + // events: 'dist/events', //(optional) + }); } - client.login(); diff --git a/template-ts/tsconfig.json b/template-ts/tsconfig.json index c87a775..7da08ce 100644 --- a/template-ts/tsconfig.json +++ b/template-ts/tsconfig.json @@ -9,7 +9,6 @@ "esModuleInterop": true, "noImplicitAny": true, "strictNullChecks": true, - "importsNotUsedAsValues": "error", "skipLibCheck": true, "forceConsistentCasingInFileNames": true }