tauri-create.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. const parseArgs = require('minimist')
  2. const inquirer = require('inquirer')
  3. const { resolve } = require('path')
  4. const { merge } = require('lodash')
  5. const {
  6. recipeShortNames,
  7. recipeDescriptiveNames,
  8. recipeByDescriptiveName,
  9. recipeByShortName
  10. } = require('../dist/api/recipes')
  11. /**
  12. * @type {object}
  13. * @property {boolean} h
  14. * @property {boolean} help
  15. * @property {string|boolean} f
  16. * @property {string|boolean} force
  17. * @property {boolean} l
  18. * @property {boolean} log
  19. * @property {boolean} d
  20. * @property {boolean} directory
  21. * @property {string} r
  22. * @property {string} recipe
  23. */
  24. function main(cliArgs) {
  25. const argv = parseArgs(cliArgs, {
  26. alias: {
  27. h: 'help',
  28. f: 'force',
  29. l: 'log',
  30. d: 'directory',
  31. t: 'tauri-path',
  32. A: 'app-name',
  33. W: 'window-title',
  34. D: 'dist-dir',
  35. P: 'dev-path',
  36. r: 'recipe'
  37. },
  38. boolean: ['h', 'l', 'ci']
  39. })
  40. if (argv.help) {
  41. printUsage()
  42. return 0
  43. }
  44. if (argv.ci) {
  45. runInit(argv)
  46. } else {
  47. getOptionsInteractive(argv).then(responses => runInit(argv, responses))
  48. }
  49. }
  50. function printUsage() {
  51. console.log(`
  52. Description
  53. Inits the Tauri template. If Tauri cannot find the tauri.conf.json
  54. it will create one.
  55. Usage
  56. $ tauri create
  57. Options
  58. --help, -h Displays this message
  59. --ci Skip prompts
  60. --force, -f Force init to overwrite [conf|template|all]
  61. --log, -l Logging [boolean]
  62. --directory, -d Set target directory for init
  63. --tauri-path, -t Path of the Tauri project to use (relative to the cwd)
  64. --app-name, -A Name of your Tauri application
  65. --window-title, -W Window title of your Tauri application
  66. --dist-dir, -D Web assets location, relative to <project-dir>/src-tauri
  67. --dev-path, -P Url of your dev server
  68. --recipe, -r Add UI framework recipe. None by default.
  69. Supported recipes: [${recipeShortNames.join('|')}]
  70. `)
  71. }
  72. const getOptionsInteractive = (argv) => {
  73. let defaultAppName = argv.A
  74. if (!defaultAppName) {
  75. try {
  76. const packageJson = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json')).toString())
  77. defaultAppName = packageJson.displayName || packageJson.name
  78. } catch {}
  79. }
  80. return inquirer
  81. .prompt([{
  82. type: 'input',
  83. name: 'appName',
  84. message: 'What is your app name?',
  85. default: defaultAppName
  86. }, {
  87. type: 'input',
  88. name: 'tauri.window.title',
  89. message: 'What should the window title be?',
  90. default: 'Tauri App',
  91. when: () => !argv.W
  92. },
  93. {
  94. type: 'list',
  95. name: 'recipeName',
  96. message: 'Would you like to add a UI recipe?',
  97. choices: recipeDescriptiveNames,
  98. default: 'No recipe',
  99. when: () => !argv.r
  100. }
  101. ])
  102. .then(answers =>
  103. inquirer
  104. .prompt([
  105. {
  106. type: 'input',
  107. name: 'build.devPath',
  108. message: 'What is the url of your dev server?',
  109. default: 'http://localhost:4000',
  110. when: () => !argv.P && !argv.p && answers.recipeName === 'No recipe' || argv.r === 'none'
  111. },
  112. {
  113. type: 'input',
  114. name: 'build.distDir',
  115. message: 'Where are your web assets (HTML/CSS/JS) located, relative to the "<current dir>/src-tauri" folder that will be created?',
  116. default: '../dist',
  117. when: () => !argv.D && answers.recipeName === 'No recipe' || argv.r === 'none'
  118. }
  119. ])
  120. .then(answers2 => ({...answers, ...answers2}))
  121. )
  122. .catch(error => {
  123. if (error.isTtyError) {
  124. // Prompt couldn't be rendered in the current environment
  125. console.log(
  126. 'It appears your terminal does not support interactive prompts. Using default values.'
  127. )
  128. runInit()
  129. } else {
  130. // Something else when wrong
  131. console.error('An unknown error occurred:', error)
  132. }
  133. })
  134. }
  135. async function runInit(argv, config = {}) {
  136. const {
  137. appName,
  138. recipeName,
  139. ...configOptions
  140. } = config
  141. const init = require('../dist/api/init')
  142. let recipe;
  143. let recipeSelection = 'none'
  144. if (recipeName !== undefined) {
  145. recipe = recipeByDescriptiveName(recipeName)
  146. } else if (argv.r) {
  147. recipe = recipeByShortName(argv.r)
  148. }
  149. let buildConfig = {
  150. distDir: argv.D,
  151. devPath: argv.P
  152. }
  153. if (recipe !== undefined) {
  154. recipeSelection = recipe.shortName
  155. buildConfig = recipe.configUpdate(buildConfig)
  156. }
  157. const directory = argv.d || process.cwd()
  158. init({
  159. directory,
  160. force: argv.f || null,
  161. logging: argv.l || null,
  162. tauriPath: argv.t || null,
  163. appName: appName || argv.A || null,
  164. customConfig: merge(configOptions, {
  165. build: buildConfig,
  166. tauri: {
  167. window: {
  168. title: argv.W
  169. }
  170. }
  171. })
  172. })
  173. const {
  174. installDependencies
  175. } = require('../dist/api/dependency-manager')
  176. await installDependencies()
  177. if (recipe !== undefined) {
  178. const {
  179. installRecipeDependencies,
  180. runRecipePostConfig
  181. } = require('../dist/api/recipes/install')
  182. await installRecipeDependencies(recipe, directory)
  183. await runRecipePostConfig(recipe, directory)
  184. }
  185. }
  186. module.exports = main