index.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { CargoManifest } from './../types/cargo'
  2. import { existsSync, removeSync, writeFileSync } from 'fs-extra'
  3. import { join, normalize, resolve, isAbsolute } from 'path'
  4. import { merge } from 'webpack-merge'
  5. import copyTemplates from '../helpers/copy-templates'
  6. import logger from '../helpers/logger'
  7. import defaultConfig from './defaultConfig'
  8. import chalk from 'chalk'
  9. const log = logger('app:tauri')
  10. const warn = logger('app:tauri (template)', chalk.red)
  11. interface InjectOptions {
  12. force: false | InjectionType
  13. logging: boolean
  14. tauriPath?: string
  15. }
  16. type InjectionType = 'conf' | 'template' | 'all'
  17. interface UnknownObject {
  18. [index: string]: any
  19. }
  20. const injectConfFile = (
  21. injectPath: string,
  22. { force, logging }: InjectOptions,
  23. customConfig: Object = {}
  24. ): boolean | undefined => {
  25. const path = join(injectPath, 'tauri.conf.json')
  26. if (existsSync(path) && force !== 'conf' && force !== 'all') {
  27. warn(`tauri.conf.json found in ${path}
  28. Run \`tauri init --force conf\` to overwrite.`)
  29. if (!force) return false
  30. } else {
  31. removeSync(path)
  32. Object.keys(defaultConfig).forEach((key) => {
  33. // Options marked `null` should be removed
  34. /* eslint-disable security/detect-object-injection */
  35. if ((customConfig as UnknownObject)[key] === null) {
  36. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  37. delete (defaultConfig as UnknownObject)[key]
  38. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  39. delete (customConfig as UnknownObject)[key]
  40. }
  41. /* eslint-enable security/detect-object-injection */
  42. })
  43. // Window config should be merged
  44. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
  45. if ((customConfig as UnknownObject).tauri?.windows[0]) {
  46. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
  47. ;(customConfig as UnknownObject).tauri.windows[0] = {
  48. ...defaultConfig.tauri.windows[0],
  49. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
  50. ...(customConfig as UnknownObject).tauri.windows[0]
  51. }
  52. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
  53. delete (defaultConfig as UnknownObject).tauri.windows
  54. }
  55. const finalConf = merge(
  56. defaultConfig as any,
  57. customConfig as any
  58. ) as UnknownObject
  59. writeFileSync(path, JSON.stringify(finalConf, undefined, 2))
  60. if (logging) log('Successfully wrote tauri.conf.json')
  61. }
  62. }
  63. const injectTemplate = (
  64. injectPath: string,
  65. { force, logging, tauriPath }: InjectOptions
  66. ): boolean | undefined => {
  67. const dir = normalize(join(injectPath, 'src-tauri'))
  68. if (existsSync(dir) && force !== 'template' && force !== 'all') {
  69. warn(`Tauri dir (${dir}) not empty.
  70. Run \`tauri init --force template\` to overwrite.`)
  71. if (!force) return false
  72. }
  73. const resolveTauriPath = (tauriPath: string, crate: string): string => {
  74. const resolvedPath = isAbsolute(tauriPath)
  75. ? join(tauriPath, crate) // we received a full path as argument
  76. : join('..', tauriPath, crate) // we received a relative path
  77. return resolvedPath.replace(/\\/g, '/')
  78. }
  79. const resolveCurrentTauriVersion = (manifest: CargoManifest): string => {
  80. const version = manifest.package.version
  81. return version.substring(0, version.lastIndexOf('.'))
  82. }
  83. // eslint-disable-next-line @typescript-eslint/no-var-requires
  84. const tauriManifest = require('../../../../tauri/Cargo.toml') as CargoManifest
  85. // eslint-disable-next-line @typescript-eslint/no-var-requires
  86. const tauriBuildManifest = require('../../../../core/tauri-build/Cargo.toml') as CargoManifest
  87. const tauriDep = tauriPath
  88. ? `{ path = "${resolveTauriPath(tauriPath, 'tauri')}" }`
  89. : `{ version = "${resolveCurrentTauriVersion(tauriManifest)}" }`
  90. const tauriBuildDep = tauriPath
  91. ? `{ path = "${resolveTauriPath(tauriPath, 'core/tauri-build')}" }`
  92. : `{ version = "${resolveCurrentTauriVersion(tauriBuildManifest)}" }`
  93. removeSync(dir)
  94. copyTemplates({
  95. source: resolve(__dirname, '../../templates/src-tauri'),
  96. scope: {
  97. tauriDep,
  98. tauriBuildDep
  99. },
  100. target: dir
  101. })
  102. if (logging) log('Successfully wrote src-tauri')
  103. }
  104. const inject = (
  105. injectPath: string,
  106. type: InjectionType,
  107. { force = false, logging = false, tauriPath }: InjectOptions,
  108. customConfig?: Object
  109. ): boolean => {
  110. if (typeof type !== 'string' || typeof injectPath !== 'string') {
  111. warn('- internal error. Required params missing.')
  112. return false
  113. }
  114. if (type === 'template' || type === 'all') {
  115. injectTemplate(injectPath, { force, logging, tauriPath })
  116. }
  117. if (type === 'conf' || type === 'all') {
  118. injectConfFile(
  119. join(injectPath, 'src-tauri'),
  120. { force, logging },
  121. customConfig
  122. )
  123. }
  124. return true
  125. }
  126. export { inject }