From 828a3deb33cad538337f7cee3951a4a5bd1bbd9c Mon Sep 17 00:00:00 2001 From: Danya H Date: Mon, 28 Oct 2024 12:10:58 +0000 Subject: [PATCH] upd cli - added rpc tests - removed git clone --- cli/src/commands/create.ts | 30 +++++-------- cli/src/commands/download-updater.ts | 33 ++++++++------ cli/src/commands/test-rpc.ts | 67 ++++++++++++++++++++++++++++ cli/src/index.ts | 37 ++++++++++----- cli/src/utils/cloner.ts | 24 ++++++++++ cli/src/utils/update.ts | 10 +++-- pnpm-lock.yaml | 32 +++++++------ 7 files changed, 175 insertions(+), 58 deletions(-) create mode 100644 cli/src/commands/test-rpc.ts create mode 100644 cli/src/utils/cloner.ts diff --git a/cli/src/commands/create.ts b/cli/src/commands/create.ts index f6429e6..6de4cba 100644 --- a/cli/src/commands/create.ts +++ b/cli/src/commands/create.ts @@ -1,7 +1,7 @@ import c from 'chalk' import { input, select } from '@inquirer/prompts' -import clone from 'git-clone' import path from 'node:path' +import { cloneBranch } from '../utils/cloner' export async function initProject() { let folder @@ -10,7 +10,7 @@ export async function initProject() { if (!folder) { folder = await input({ message: c.gray('Enter project name:'), - default: 'rage-fw', + default: 'rage-fw-example', }) } else { console.log(c.gray('Project name:'), folder) @@ -19,19 +19,14 @@ export async function initProject() { if (!framework) { framework = await select({ message: c.gray('Select frontend:'), - default: 'react', + default: 'react-18', loop: true, choices: [ { name: 'React + TypeScript (Vite)', - value: 'react', + value: 'react-18', description: 'React + TypeScript (Vite) as a frontend', }, - // { - // name: 'vue', - // value: 'vue', - // description: 'npm is the most popular package manager', - // }, ], }) } else { @@ -46,21 +41,20 @@ export async function initProject() { c.gray('as a frontend..'), ) - clone( + cloneBranch( 'https://git.entityseven.com/entityseven/rage-framework-example', path.join(process.cwd(), folder), - {}, - err => { - if (err) { - console.log(c.red('Error occured: \n', err)) - return - } + framework, + ) + .then(() => { console.log(c.gray('Scaffolded project into'), folder) console.log( c.gray( `Project was created ar dir: ${path.join(process.cwd(), folder)}`, ), ) - }, - ) + }) + .catch(e => { + console.log(c.red('Error occured: \n', e)) + }) } diff --git a/cli/src/commands/download-updater.ts b/cli/src/commands/download-updater.ts index 4ce885f..4833aa2 100644 --- a/cli/src/commands/download-updater.ts +++ b/cli/src/commands/download-updater.ts @@ -1,4 +1,3 @@ -import axios from 'axios' import * as fs from 'node:fs' const latestReleases = @@ -13,25 +12,33 @@ type Asset = { } export async function downloadUpdater(): Promise { + const ky = await import('ky').then(ky => ky.default) const id = await getLatestReleaseID() const latestAssets = `https://git.entityseven.com/api/v1/repos/entityseven/rage-server-downloader/releases/${id}/assets?page=1&limit=1` - axios.get(latestAssets).then(async ({ data }) => { - const downloadURL = data[0].browser_download_url + ky.get(latestAssets) + .then(response => response.json()) + .then(async data => { + const downloadURL = data[0].browser_download_url - const file = await axios.get(data[0].browser_download_url, { - responseType: 'arraybuffer', + const file = await ky.get(data[0].browser_download_url) + const fileData = Buffer.from( + file as unknown as WithImplicitCoercion, + 'binary', + ) + + const fileSplit = downloadURL.split('/') + const fileName = fileSplit[fileSplit.length - 1] + + fs.writeFileSync(`./${fileName}`, fileData) }) - const fileData = Buffer.from(file.data, 'binary') - - const fileSplit = downloadURL.split('/') - const fileName = fileSplit[fileSplit.length - 1] - - fs.writeFileSync(`./${fileName}`, fileData) - }) } async function getLatestReleaseID() { - return axios.get(latestReleases).then(({ data }) => data[0].id) + const ky = await import('ky').then(ky => ky.default) + return ky + .get(latestReleases) + .then(response => response.json()) + .then(data => data[0].id) } diff --git a/cli/src/commands/test-rpc.ts b/cli/src/commands/test-rpc.ts new file mode 100644 index 0000000..9a96fb7 --- /dev/null +++ b/cli/src/commands/test-rpc.ts @@ -0,0 +1,67 @@ +import c from 'chalk' +import { input, select } from '@inquirer/prompts' +import path from 'node:path' +import { cloneBranch } from '../utils/cloner' + +const choices = { + 'rpc-react-18': { + name: 'Vite + React 18 + TypeScript', + value: 'rpc-react-18', + description: 'Vite + React 18 + TypeScript as a frontend', + }, + 'rpc-svelte-5': { + name: 'Vite + Svelte 5 + TypeScript', + value: 'rpc-svelte-5', + description: 'Vite + Svelte 5 + TypeScript as a frontend', + }, +} as const + +export async function testRpc() { + let folder + let framework + + if (!folder) { + folder = await input({ + message: c.gray('Enter project name:'), + default: 'rage-fw-rpc-example', + }) + } else { + console.log(c.gray('Project name:'), folder) + } + + if (!framework) { + framework = await select({ + message: c.gray('Select frontend:'), + default: 'rpc-react-18', + loop: true, + choices: Object.values(choices), + }) + } else { + console.log(c.gray('Frontend:'), framework) + } + + console.log( + c.gray('\nScaffolding template project into'), + folder, + c.gray('with'), + choices[framework].name, + c.gray('as a frontend..'), + ) + + cloneBranch( + 'https://git.entityseven.com/entityseven/rage-framework-example', + path.join(process.cwd(), folder), + framework, + ) + .then(() => { + console.log(c.gray('Scaffolded project into'), folder) + console.log( + c.gray( + `Project was created at dir: ${path.join(process.cwd(), folder)}`, + ), + ) + }) + .catch(e => { + console.log(c.red('Error occured: \n', e)) + }) +} diff --git a/cli/src/index.ts b/cli/src/index.ts index 912bc83..f7414ac 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -1,40 +1,57 @@ import c from 'chalk' import { select } from '@inquirer/prompts' -import { checkForUpdate } from './utils/update' +import { checkForUpdates } from './utils/update' import { initProject } from './commands/create' import { downloadUpdater } from './commands/download-updater' +import { testRpc } from './commands/test-rpc' enum Actions { INIT_PROJECT = 'INIT_PROJECT', + TEST_RPC = 'TEST_RPC', UPDATER = 'UPDATER', } ;(async () => { - await checkForUpdate() + await checkForUpdates() - console.log( - c.blueBright('Rage FW CLI | Powered by Entity Seven Group ️ <3'), - ) + console.log(c.blueBright('Rage FW CLI | Powered by Entity Seven Group ️<3')) const action = await select({ message: c.gray('Select action:'), choices: [ { - name: 'Initialize new project', + name: 'Initialize a new project', value: Actions.INIT_PROJECT, - description: 'Initialize new project and start develop', + description: 'Initialize a new project and start developing', + }, + { + name: 'Test our RPC', + value: Actions.TEST_RPC, + description: + 'Initialize a new skeleton project with our RPC set up', }, { name: 'Install RAGE:MP updater', value: Actions.UPDATER, description: - 'Use our custom updater to download and update RAGE:MP server files.', + 'Use our tool to download or update RAGE:MP server files in two clicks', }, ], loop: true, }) - if (action === Actions.INIT_PROJECT) await initProject() - if (action === Actions.UPDATER) await downloadUpdater() + switch (action) { + case Actions.INIT_PROJECT: + await initProject() + break + case Actions.TEST_RPC: + await testRpc() + break + case Actions.UPDATER: + await downloadUpdater() + break + default: + console.log(c.red('Something went wrong..')) + } })() diff --git a/cli/src/utils/cloner.ts b/cli/src/utils/cloner.ts new file mode 100644 index 0000000..a5e5c18 --- /dev/null +++ b/cli/src/utils/cloner.ts @@ -0,0 +1,24 @@ +import { exec } from 'child_process' + +export async function cloneBranch(link: string, path: string, branch: string) { + return new Promise((resolve, reject) => { + const args = ['--single-branch', '-b', branch, '--', link, path] + const proc = exec('git clone ' + args.join(' ')) + + proc.on('close', (status: number) => { + if (status == 0) { + resolve(true) + } else if (status == 128) { + reject( + `Folder already exists. 'git clone' from branch ${branch} failed with status ` + + status, + ) + } else { + reject( + `'git clone' from branch ${branch} failed with status ` + + status, + ) + } + }) + }) +} diff --git a/cli/src/utils/update.ts b/cli/src/utils/update.ts index cb8a44d..80f71f7 100644 --- a/cli/src/utils/update.ts +++ b/cli/src/utils/update.ts @@ -1,4 +1,3 @@ -import axios from 'axios' import c from 'chalk' import yargs from 'yargs' @@ -10,12 +9,15 @@ type Version = { message: string } -export async function checkForUpdate(): Promise { +export async function checkForUpdates(): Promise { + const ky = await import('ky').then(ky => ky.default) + return new Promise(res => { yargs.showVersion(version => - axios + ky .get(latestVersionURL) - .then(({ data }) => { + .then(response => response.json()) + .then(data => { const latestVersion = data[0].name if (latestVersion !== `v${version}`) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5376927..42e2457 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,27 +53,27 @@ importers: '@ragempcommunity/types-cef': specifier: ^2.1.8 version: 2.1.8 + rage-fw-rpc: + specifier: workspace:^ + version: link:../rpc rage-fw-shared-types: specifier: workspace:^ version: link:../shared-types - rage-trpc: - specifier: workspace:^ - version: link:../rpc cli: dependencies: '@inquirer/prompts': specifier: ^5.0.5 version: 5.0.5 - axios: - specifier: ^1.7.2 - version: 1.7.2 chalk: specifier: 4.1.2 version: 4.1.2 git-clone: specifier: ^0.2.0 version: 0.2.0 + ky: + specifier: ^1.7.2 + version: 1.7.2 yargs: specifier: ^17.7.2 version: 17.7.2 @@ -99,17 +99,17 @@ importers: '@ragempcommunity/types-client': specifier: ^2.1.8 version: 2.1.8 + rage-fw-rpc: + specifier: workspace:^ + version: link:../rpc rage-fw-shared-types: specifier: workspace:^ version: link:../shared-types - rage-trpc: - specifier: workspace:^ - version: link:../rpc rpc: dependencies: typescript: - specifier: ^5.0.0 + specifier: ^5 version: 5.4.5 devDependencies: '@microsoft/api-extractor': @@ -127,12 +127,12 @@ importers: '@ragempcommunity/types-server': specifier: ^2.1.8 version: 2.1.8 + rage-fw-rpc: + specifier: workspace:^ + version: link:../rpc rage-fw-shared-types: specifier: workspace:^ version: link:../shared-types - rage-trpc: - specifier: workspace:^ - version: link:../rpc shared-types: {} @@ -2269,6 +2269,10 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + ky@1.7.2: + resolution: {integrity: sha512-OzIvbHKKDpi60TnF9t7UUVAF1B4mcqc02z5PIvrm08Wyb+yOcz63GRvEuVxNT18a9E1SrNouhB4W2NNLeD7Ykg==} + engines: {node: '>=18'} + lerna@8.1.3: resolution: {integrity: sha512-Dg/r1dGnRCXKsOUC3lol7o6ggYTA6WWiPQzZJNKqyygn4fzYGuA3Dro2d5677pajaqFnFA72mdCjzSyF16Vi2Q==} engines: {node: '>=18.0.0'} @@ -5797,6 +5801,8 @@ snapshots: kuler@2.0.0: {} + ky@1.7.2: {} + lerna@8.1.3(encoding@0.1.13): dependencies: '@lerna/create': 8.1.3(encoding@0.1.13)(typescript@5.4.5)