Skip to content

Commit

Permalink
Partial revert "refactor(tauri.js): remove create command (#1265)"
Browse files Browse the repository at this point in the history
This reverts commit b29c068.
  • Loading branch information
jbolda committed Mar 4, 2021
1 parent 1f5692e commit d0e2591
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 0 deletions.
207 changes: 207 additions & 0 deletions cli/tauri.js/bin/tauri-create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
const parseArgs = require('minimist')
const inquirer = require('inquirer')
const { resolve } = require('path')
const { merge } = require('lodash')
const {
recipeShortNames,
recipeDescriptiveNames,
recipeByDescriptiveName,
recipeByShortName
} = require('../dist/api/recipes')

/**
* @type {object}
* @property {boolean} h
* @property {boolean} help
* @property {string|boolean} f
* @property {string|boolean} force
* @property {boolean} l
* @property {boolean} log
* @property {boolean} d
* @property {boolean} directory
* @property {string} r
* @property {string} recipe
*/
function main(cliArgs) {
const argv = parseArgs(cliArgs, {
alias: {
h: 'help',
f: 'force',
l: 'log',
d: 'directory',
t: 'tauri-path',
A: 'app-name',
W: 'window-title',
D: 'dist-dir',
P: 'dev-path',
r: 'recipe'
},
boolean: ['h', 'l', 'ci']
})

if (argv.help) {
printUsage()
return 0
}

if (argv.ci) {
runInit(argv)
} else {
getOptionsInteractive(argv).then((responses) => runInit(argv, responses))
}
}

function printUsage() {
console.log(`
Description
Inits the Tauri template. If Tauri cannot find the tauri.conf.json
it will create one.
Usage
$ tauri create
Options
--help, -h Displays this message
--ci Skip prompts
--force, -f Force init to overwrite [conf|template|all]
--log, -l Logging [boolean]
--directory, -d Set target directory for init
--tauri-path, -t Path of the Tauri project to use (relative to the cwd)
--app-name, -A Name of your Tauri application
--window-title, -W Window title of your Tauri application
--dist-dir, -D Web assets location, relative to <project-dir>/src-tauri
--dev-path, -P Url of your dev server
--recipe, -r Add UI framework recipe. None by default.
Supported recipes: [${recipeShortNames.join('|')}]
`)
}

const getOptionsInteractive = (argv) => {
let defaultAppName = argv.A
if (!defaultAppName) {
try {
const packageJson = JSON.parse(
readFileSync(resolve(process.cwd(), 'package.json')).toString()
)
defaultAppName = packageJson.displayName || packageJson.name
} catch {}
}

return inquirer
.prompt([
{
type: 'input',
name: 'appName',
message: 'What is your app name?',
default: defaultAppName,
when: !argv.A
},
{
type: 'input',
name: 'tauri.window.title',
message: 'What should the window title be?',
default: 'Tauri App',
when: () => !argv.W
},
{
type: 'list',
name: 'recipeName',
message: 'Would you like to add a UI recipe?',
choices: recipeDescriptiveNames,
default: 'No recipe',
when: () => !argv.r
}
])
.then((answers) =>
inquirer
.prompt([
{
type: 'input',
name: 'build.devPath',
message: 'What is the url of your dev server?',
default: 'http://localhost:4000',
when: () =>
(!argv.P && !argv.p && answers.recipeName === 'No recipe') ||
argv.r === 'none'
},
{
type: 'input',
name: 'build.distDir',
message:
'Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri" folder that will be created?',
default: '../dist',
when: () =>
(!argv.D && answers.recipeName === 'No recipe') ||
argv.r === 'none'
}
])
.then((answers2) => ({ ...answers, ...answers2 }))
)
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
console.log(
'It appears your terminal does not support interactive prompts. Using default values.'
)
runInit()
} else {
// Something else when wrong
console.error('An unknown error occurred:', error)
}
})
}

async function runInit(argv, config = {}) {
const { appName, recipeName, ...configOptions } = config
const init = require('../dist/api/init')

let recipe
let recipeSelection = 'none'

if (recipeName !== undefined) {
recipe = recipeByDescriptiveName(recipeName)
} else if (argv.r) {
recipe = recipeByShortName(argv.r)
}

let buildConfig = {
distDir: argv.D,
devPath: argv.P
}

if (recipe !== undefined) {
recipeSelection = recipe.shortName
buildConfig = recipe.configUpdate(buildConfig)
}

const directory = argv.d || process.cwd()

init({
directory,
force: argv.f || null,
logging: argv.l || null,
tauriPath: argv.t || null,
appName: appName || argv.A || null,
customConfig: merge(configOptions, {
build: buildConfig,
tauri: {
window: {
title: argv.W
}
}
})
})

const { installDependencies } = require('../dist/api/dependency-manager')
await installDependencies()

if (recipe !== undefined) {
const {
installRecipeDependencies,
runRecipePostConfig
} = require('../dist/api/recipes/install')

await installRecipeDependencies(recipe, directory)
await runRecipePostConfig(recipe, directory)
}
}

module.exports = main
44 changes: 44 additions & 0 deletions cli/tauri.js/src/api/recipes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { map, identity, find } from 'lodash'
import { TauriBuildConfig } from '../../types/config'
import { reactjs, reactts } from './react'

export interface Recipe {
descriptiveName: string
shortName: string
configUpdate: (cfg: TauriBuildConfig) => TauriBuildConfig
extraNpmDependencies: string[]
extraNpmDevDependencies: string[]
postConfiguration: (cwd: string) => void
}

const none = {
descriptiveName: 'No recipe',
shortName: 'none',
configUpdate: identity,
extraNpmDependencies: [],
extraNpmDevDependencies: [],
postConfiguration: (cwd: string) => {}
}

export const allRecipes: Recipe[] = [none, reactjs, reactts]

export const recipeNames: Array<[string, string]> = map(
allRecipes,
(r: Recipe) => [r.shortName, r.descriptiveName]
)

export const recipeByShortName = (name: string): Recipe | undefined =>
find(allRecipes, (r: Recipe) => r.shortName === name)

export const recipeByDescriptiveName = (name: string): Recipe | undefined =>
find(allRecipes, (r: Recipe) => r.descriptiveName === name)

export const recipeShortNames: string[] = map(
allRecipes,
(r: Recipe) => r.shortName
)

export const recipeDescriptiveNames: string[] = map(
allRecipes,
(r: Recipe) => r.descriptiveName
)
35 changes: 35 additions & 0 deletions cli/tauri.js/src/api/recipes/install.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
installThese,
installTheseDev
} from '../dependency-manager/npm-packages'
import { Recipe } from '.'
import { Result } from '../dependency-manager/types'
import logger from '../../helpers/logger'

export async function installRecipeDependencies(
recipe: Recipe
): Promise<Result> {
const log = logger('recipe:install')

log(`Installing dependencies for ${recipe.descriptiveName}`)
return await installThese(recipe.extraNpmDependencies).then(
async (results) =>
await installTheseDev(recipe.extraNpmDevDependencies).then(
(results2) =>
new Map([
...Array.from(results.entries()),
...Array.from(results2.entries())
])
)
)
}

export async function runRecipePostConfig(
recipe: Recipe,
cwd: string
): Promise<void> {
const log = logger('recipe:postconfig')

log(`Running post configuration for ${recipe.descriptiveName}`)
return await new Promise(() => recipe.postConfiguration(cwd))
}
65 changes: 65 additions & 0 deletions cli/tauri.js/src/api/recipes/react.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Recipe } from '.'
import { TauriBuildConfig } from '../../types/config'
import { spawnSync } from '../../helpers/spawn'
import logger from '../../helpers/logger'
import copyTemplates from '../../helpers/copy-templates'
import { resolve, join } from 'path'

const uiAppDir = 'app-ui'

const log = logger('react-recipe')

const completeLogMsg = `
Your installation completed.
To start, run yarn tauri dev
`

const afterCra = (): void => {
copyTemplates({
source: resolve(__dirname, '../../templates/recipes/react/'),
scope: {},
target: join(uiAppDir, './src/')
})
log(completeLogMsg)
}

const reactjs: Recipe = {
descriptiveName: 'React.js',
shortName: 'reactjs',
configUpdate: (cfg: TauriBuildConfig): TauriBuildConfig => ({
...cfg,
distDir: `../${uiAppDir}/build`,
devPath: 'http://localhost:3000',
beforeDevCommand: `yarn --cwd ${uiAppDir} start`,
beforeBuildCommand: `yarn --cwd ${uiAppDir} build`
}),
extraNpmDevDependencies: ['create-react-app'],
extraNpmDependencies: ['react'],
postConfiguration: (cwd: string) => {
spawnSync('yarn', ['create-react-app', uiAppDir], cwd)
afterCra()
}
}

const reactts: Recipe = {
...reactjs,
descriptiveName: 'React with Typescript',
shortName: 'reactts',
extraNpmDependencies: [
'typescript',
'@types/node',
'@types/react',
'@types/react-dom',
'@types/jest'
],
postConfiguration: (cwd: string) => {
spawnSync(
'yarn',
['create-react-app', '--template', 'typescript', uiAppDir],
cwd
)
afterCra()
}
}

export { reactjs, reactts }

0 comments on commit d0e2591

Please sign in to comment.