Rpc integration + type fixes #3
@ -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))
 | 
			
		||||
        })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<void> {
 | 
			
		||||
    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<Asset[]>(latestAssets).then(async ({ data }) => {
 | 
			
		||||
        const downloadURL = data[0].browser_download_url
 | 
			
		||||
    ky.get<Asset[]>(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<string>,
 | 
			
		||||
                '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<Release[]>(latestReleases).then(({ data }) => data[0].id)
 | 
			
		||||
    const ky = await import('ky').then(ky => ky.default)
 | 
			
		||||
    return ky
 | 
			
		||||
        .get<Release[]>(latestReleases)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(data => data[0].id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								cli/src/commands/test-rpc.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								cli/src/commands/test-rpc.ts
									
									
									
									
									
										Normal file
									
								
							@ -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))
 | 
			
		||||
        })
 | 
			
		||||
}
 | 
			
		||||
@ -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..'))
 | 
			
		||||
    }
 | 
			
		||||
})()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								cli/src/utils/cloner.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cli/src/utils/cloner.ts
									
									
									
									
									
										Normal file
									
								
							@ -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,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
@ -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<void> {
 | 
			
		||||
export async function checkForUpdates(): Promise<void> {
 | 
			
		||||
    const ky = await import('ky').then(ky => ky.default)
 | 
			
		||||
 | 
			
		||||
    return new Promise(res => {
 | 
			
		||||
        yargs.showVersion(version =>
 | 
			
		||||
            axios
 | 
			
		||||
            ky
 | 
			
		||||
                .get<Version[]>(latestVersionURL)
 | 
			
		||||
                .then(({ data }) => {
 | 
			
		||||
                .then(response => response.json<Version[]>())
 | 
			
		||||
                .then(data => {
 | 
			
		||||
                    const latestVersion = data[0].name
 | 
			
		||||
 | 
			
		||||
                    if (latestVersion !== `v${version}`)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@ -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)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user