info.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import toml from '@tauri-apps/toml'
  2. import chalk from 'chalk'
  3. import { sync as spawn } from 'cross-spawn'
  4. import fs from 'fs'
  5. import os from 'os'
  6. import path from 'path'
  7. import { appDir, tauriDir } from '../helpers/app-paths'
  8. import { TauriConfig } from './../types/config'
  9. import { CargoLock, CargoManifest } from '../types/cargo'
  10. import nonWebpackRequire from '../helpers/non-webpack-require'
  11. import { version } from '../../package.json'
  12. interface DirInfo {
  13. path: string
  14. name: string
  15. type?: 'folder' | 'file'
  16. children?: DirInfo[]
  17. }
  18. /* eslint-disable security/detect-non-literal-fs-filename */
  19. function dirTree(filename: string, recurse = true): DirInfo {
  20. const stats = fs.lstatSync(filename)
  21. const info: DirInfo = {
  22. path: filename,
  23. name: path.basename(filename)
  24. }
  25. if (stats.isDirectory()) {
  26. info.type = 'folder'
  27. if (recurse) {
  28. info.children = fs.readdirSync(filename).map(function(child: string) {
  29. return dirTree(filename + '/' + child, false)
  30. })
  31. }
  32. } else {
  33. info.type = 'file'
  34. }
  35. return info
  36. }
  37. function getVersion(
  38. command: string,
  39. args: string[] = [],
  40. formatter?: (output: string) => string
  41. ): string {
  42. try {
  43. const child = spawn(command, [...args, '--version'])
  44. if (child.status === 0) {
  45. const output = String(child.output[1])
  46. return chalk
  47. .green(formatter === undefined ? output : formatter(output))
  48. .replace('\n', '')
  49. }
  50. return chalk.red('Not installed')
  51. } catch (err) {
  52. return chalk.red('Not installed')
  53. }
  54. }
  55. interface Info {
  56. section?: boolean
  57. key: string
  58. value?: string
  59. }
  60. function printInfo(info: Info): void {
  61. console.log(
  62. `${info.section ? '\n' : ''}${info.key}${
  63. info.value === undefined ? '' : ' - ' + info.value
  64. }`
  65. )
  66. }
  67. function readTomlFile<T extends CargoLock | CargoManifest>(path: string): T {
  68. const file = fs.readFileSync(path).toString()
  69. return toml.parse(file) as unknown as T
  70. }
  71. function printAppInfo(tauriDir: string): void {
  72. printInfo({ key: 'App', section: true })
  73. const lockPath = path.join(tauriDir, 'Cargo.lock')
  74. const lockContents = readTomlFile<CargoLock>(lockPath)
  75. const tauriPackages = lockContents.package.filter(pkg => pkg.name === 'tauri')
  76. let tauriVersion: string
  77. if (tauriPackages.length <= 0) {
  78. tauriVersion = chalk.red('unknown')
  79. } else if (tauriPackages.length === 1) {
  80. tauriVersion = chalk.green(tauriPackages[0].version)
  81. } else {
  82. // there are multiple `tauri` packages in the lockfile
  83. // load and check the manifest version to display alongside the found versions
  84. const manifestPath = path.join(tauriDir, 'Cargo.toml')
  85. const manifestContent = readTomlFile<CargoManifest>(manifestPath)
  86. const manifestVersion = (): string => {
  87. const tauri = manifestContent.dependencies.tauri
  88. if (tauri) {
  89. if (typeof tauri === 'string') {
  90. return chalk.yellow(tauri)
  91. } else if (tauri.version) {
  92. return chalk.yellow(tauri.version)
  93. } else if (tauri.path) {
  94. const manifestPath = path.resolve(tauriDir, tauri.path, 'Cargo.toml')
  95. const manifestContent = readTomlFile<CargoManifest>(manifestPath)
  96. const pathVersion = chalk.yellow(manifestContent.package.version)
  97. return `path:${tauri.path} [${pathVersion}]`
  98. }
  99. }
  100. return chalk.red('unknown')
  101. }
  102. const versions = tauriPackages.map(p => p.version).join(', ')
  103. tauriVersion = `${manifestVersion()} (${chalk.yellow(versions)})`
  104. }
  105. printInfo({ key: ' tauri', value: tauriVersion })
  106. try {
  107. const tauriMode = (config: TauriConfig): string => {
  108. if (config.tauri.embeddedServer) {
  109. return chalk.green(
  110. config.tauri.embeddedServer.active ? 'embedded-server' : 'no-server'
  111. )
  112. }
  113. return chalk.red('unset')
  114. }
  115. const configPath = path.join(tauriDir, 'tauri.conf.json')
  116. const config = nonWebpackRequire(configPath) as TauriConfig
  117. printInfo({ key: ' mode', value: tauriMode(config) })
  118. printInfo({
  119. key: ' build-type',
  120. value:
  121. config.tauri.bundle?.active ? 'bundle' : 'build'
  122. })
  123. printInfo({
  124. key: ' CSP',
  125. value: config.tauri.security ? config.tauri.security.csp : 'unset'
  126. })
  127. printInfo({
  128. key: ' Windows',
  129. value: config.tauri.edge?.active ? 'Edge' : 'MSHTML'
  130. })
  131. printInfo({
  132. key: ' distDir',
  133. value: config.build
  134. ? chalk.green(config.build.distDir)
  135. : chalk.red('unset')
  136. })
  137. printInfo({
  138. key: ' devPath',
  139. value: config.build
  140. ? chalk.green(config.build.devPath)
  141. : chalk.red('unset')
  142. })
  143. } catch (_) {}
  144. }
  145. module.exports = () => {
  146. printInfo({
  147. key: 'Operating System',
  148. value: chalk.green(
  149. `${os.type()}(${os.release()}) - ${os.platform()}/${os.arch()}`
  150. ),
  151. section: true
  152. })
  153. printInfo({ key: 'Node.js environment', section: true })
  154. printInfo({ key: ' Node.js', value: chalk.green(process.version.slice(1)) })
  155. printInfo({
  156. key: ' tauri.js',
  157. value: chalk.green(version)
  158. })
  159. printInfo({ key: 'Rust environment', section: true })
  160. printInfo({
  161. key: ' rustc',
  162. value: getVersion('rustc', [], output => output.split(' ')[1])
  163. })
  164. printInfo({
  165. key: ' cargo',
  166. value: getVersion('cargo', [], output => output.split(' ')[1])
  167. })
  168. printInfo({ key: ' tauri-bundler', value: getVersion('cargo', ['tauri-bundler']) })
  169. printInfo({ key: 'Global packages', section: true })
  170. printInfo({ key: ' NPM', value: getVersion('npm') })
  171. printInfo({ key: ' yarn', value: getVersion('yarn') })
  172. printInfo({ key: 'App directory structure', section: true })
  173. const tree = dirTree(appDir)
  174. // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
  175. for (const artifact of tree.children || []) {
  176. if (artifact.type === 'folder') {
  177. console.log(`/${artifact.name}`)
  178. }
  179. }
  180. printAppInfo(tauriDir)
  181. }
  182. /* eslint-enable security/detect-non-literal-fs-filename */