2019-08-20 00:09:29 +03:00
|
|
|
const
|
2019-11-16 21:51:46 +03:00
|
|
|
chokidar = require('chokidar')
|
|
|
|
const debounce = require('lodash.debounce')
|
|
|
|
const path = require('path')
|
2019-12-19 21:08:36 +03:00
|
|
|
const { readFileSync, writeFileSync, existsSync } = require('fs-extra')
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
const
|
2019-11-16 21:51:46 +03:00
|
|
|
{ spawn } = require('./helpers/spawn')
|
|
|
|
const onShutdown = require('./helpers/on-shutdown')
|
|
|
|
const generator = require('./generator')
|
2019-12-18 00:39:34 +03:00
|
|
|
const entry = require('./entry')
|
2019-11-16 21:51:46 +03:00
|
|
|
const { appDir, tauriDir } = require('./helpers/app-paths')
|
|
|
|
|
|
|
|
const logger = require('./helpers/logger')
|
|
|
|
const log = logger('app:tauri', 'green')
|
2019-11-24 18:03:42 +03:00
|
|
|
const warn = logger('app:tauri (template)', 'red')
|
2019-08-20 00:09:29 +03:00
|
|
|
|
2019-10-07 21:36:56 +03:00
|
|
|
class Runner {
|
2019-11-16 21:51:46 +03:00
|
|
|
constructor () {
|
2019-08-20 00:09:29 +03:00
|
|
|
this.pid = 0
|
|
|
|
this.tauriWatcher = null
|
|
|
|
onShutdown(() => {
|
|
|
|
this.stop()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
async run (cfg) {
|
2019-11-30 14:48:39 +03:00
|
|
|
const devPath = cfg.build.devPath
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
if (this.pid) {
|
2019-11-30 14:48:39 +03:00
|
|
|
if (this.devPath !== devPath) {
|
2019-08-20 00:09:29 +03:00
|
|
|
await this.stop()
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.__manipulateToml(toml => {
|
|
|
|
this.__whitelistApi(cfg, toml)
|
|
|
|
})
|
|
|
|
|
2019-12-18 00:39:34 +03:00
|
|
|
const runningDevServer = devPath.startsWith('http')
|
|
|
|
let inlinedAssets = []
|
|
|
|
|
|
|
|
if (!runningDevServer) {
|
2019-12-18 04:00:49 +03:00
|
|
|
inlinedAssets = await this.__parseHtml(cfg, path.resolve(appDir, devPath))
|
2019-12-18 00:39:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
generator.generate({
|
|
|
|
devPath: runningDevServer ? devPath : path.resolve(appDir, devPath),
|
|
|
|
inlinedAssets,
|
|
|
|
...cfg.tauri
|
|
|
|
})
|
|
|
|
entry.generate(tauriDir, cfg)
|
2019-08-22 00:35:52 +03:00
|
|
|
|
2019-11-30 14:48:39 +03:00
|
|
|
this.devPath = devPath
|
2019-08-20 00:09:29 +03:00
|
|
|
|
2019-12-18 00:39:34 +03:00
|
|
|
const features = runningDevServer ? ['dev-server'] : []
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
const startDevTauri = () => {
|
|
|
|
return this.__runCargoCommand({
|
2019-12-18 00:39:34 +03:00
|
|
|
cargoArgs: ['run'].concat(features.length ? ['--features', ...features] : []),
|
|
|
|
dev: true
|
2019-08-20 00:09:29 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start watching for tauri app changes
|
2019-12-19 02:19:09 +03:00
|
|
|
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
2019-08-20 00:09:29 +03:00
|
|
|
this.tauriWatcher = chokidar
|
|
|
|
.watch([
|
2019-10-07 21:36:56 +03:00
|
|
|
path.join(tauriDir, 'src'),
|
|
|
|
path.join(tauriDir, 'Cargo.toml'),
|
2019-10-15 15:53:34 +03:00
|
|
|
path.join(tauriDir, 'build.rs'),
|
2019-10-15 18:07:48 +03:00
|
|
|
path.join(appDir, 'tauri.conf.js')
|
2019-08-20 00:09:29 +03:00
|
|
|
], {
|
|
|
|
watchers: {
|
|
|
|
chokidar: {
|
|
|
|
ignoreInitial: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-11-30 14:48:39 +03:00
|
|
|
.on('change', debounce(async (path) => {
|
2019-08-20 00:09:29 +03:00
|
|
|
await this.__stopCargo()
|
2019-11-30 14:48:39 +03:00
|
|
|
if (path.includes('tauri.conf.js')) {
|
2019-12-18 00:39:34 +03:00
|
|
|
this.run(require('./helpers/tauri-config')({ ctx: cfg.ctx }))
|
2019-11-30 14:48:39 +03:00
|
|
|
} else {
|
|
|
|
startDevTauri()
|
|
|
|
}
|
2019-08-20 00:09:29 +03:00
|
|
|
}, 1000))
|
|
|
|
|
|
|
|
return startDevTauri()
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
async build (cfg) {
|
2019-08-20 00:09:29 +03:00
|
|
|
this.__manipulateToml(toml => {
|
|
|
|
this.__whitelistApi(cfg, toml)
|
|
|
|
})
|
|
|
|
|
2019-12-18 04:00:49 +03:00
|
|
|
const inlinedAssets = await this.__parseHtml(cfg, cfg.build.distDir)
|
2019-08-22 00:35:52 +03:00
|
|
|
|
2019-12-18 00:39:34 +03:00
|
|
|
generator.generate({
|
|
|
|
inlinedAssets,
|
|
|
|
...cfg.tauri
|
|
|
|
})
|
|
|
|
entry.generate(tauriDir, cfg)
|
|
|
|
|
|
|
|
const features = [
|
|
|
|
cfg.tauri.embeddedServer.active ? 'embedded-server' : 'no-server'
|
|
|
|
]
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
const buildFn = target => this.__runCargoCommand({
|
2019-12-18 00:39:34 +03:00
|
|
|
cargoArgs: [cfg.tauri.bundle.active ? 'tauri-cli' : 'build', '--features', ...features]
|
2019-08-20 00:09:29 +03:00
|
|
|
.concat(cfg.ctx.debug ? [] : ['--release'])
|
|
|
|
.concat(target ? ['--target', target] : [])
|
|
|
|
})
|
|
|
|
|
|
|
|
if (cfg.ctx.debug || !cfg.ctx.targetName) {
|
2019-10-07 21:36:56 +03:00
|
|
|
// on debug mode or if no target specified,
|
2019-08-20 00:09:29 +03:00
|
|
|
// build only for the current platform
|
2019-11-30 14:48:39 +03:00
|
|
|
await buildFn()
|
|
|
|
} else {
|
|
|
|
const targets = cfg.ctx.target.split(',')
|
2019-08-20 00:09:29 +03:00
|
|
|
|
2019-11-30 14:48:39 +03:00
|
|
|
for (const target of targets) {
|
|
|
|
await buildFn(target)
|
|
|
|
}
|
2019-08-20 00:09:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-18 04:00:49 +03:00
|
|
|
__parseHtml (cfg, indexDir) {
|
2019-12-18 03:13:01 +03:00
|
|
|
const Inliner = require('@tauri-apps/tauri-inliner')
|
2019-12-18 00:39:34 +03:00
|
|
|
const jsdom = require('jsdom')
|
|
|
|
const { JSDOM } = jsdom
|
|
|
|
const inlinedAssets = []
|
2019-12-19 02:19:09 +03:00
|
|
|
|
2019-12-18 00:39:34 +03:00
|
|
|
return new Promise((resolve, reject) => {
|
2019-12-19 21:08:36 +03:00
|
|
|
const distIndexPath = path.join(indexDir, 'index.html')
|
|
|
|
if (!existsSync(distIndexPath)) {
|
|
|
|
warn(`Error: cannot find index.html in "${indexDir}". Did you forget to build your web code or update the build.distDir in tauri.conf.js?`)
|
|
|
|
reject(new Error('Could not find index.html in dist dir.'))
|
|
|
|
}
|
|
|
|
new Inliner(distIndexPath, (err, html) => {
|
2019-12-18 00:39:34 +03:00
|
|
|
if (err) {
|
|
|
|
reject(err)
|
|
|
|
} else {
|
|
|
|
const dom = new JSDOM(html)
|
|
|
|
const document = dom.window.document
|
|
|
|
document.querySelectorAll('link').forEach(link => {
|
|
|
|
link.removeAttribute('rel')
|
|
|
|
link.removeAttribute('as')
|
|
|
|
})
|
|
|
|
|
|
|
|
const tauriScript = document.createElement('script')
|
|
|
|
tauriScript.text = readFileSync(path.join(tauriDir, 'tauri.js'))
|
|
|
|
document.body.insertBefore(tauriScript, document.body.firstChild)
|
2019-12-18 04:00:49 +03:00
|
|
|
|
|
|
|
const csp = cfg.tauri.security.csp
|
|
|
|
if (csp) {
|
|
|
|
const cspTag = document.createElement('meta')
|
|
|
|
cspTag.setAttribute('http-equiv', 'Content-Security-Policy')
|
|
|
|
cspTag.setAttribute('content', csp)
|
|
|
|
document.head.appendChild(cspTag)
|
|
|
|
}
|
|
|
|
|
2019-12-18 00:39:34 +03:00
|
|
|
writeFileSync(path.join(indexDir, 'index.tauri.html'), dom.serialize())
|
|
|
|
resolve(inlinedAssets)
|
|
|
|
}
|
|
|
|
}).on('progress', event => {
|
|
|
|
const match = event.match(/([\S\d]+)\.([\S\d]+)/g)
|
|
|
|
match && inlinedAssets.push(match[0])
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
stop () {
|
2019-08-20 00:09:29 +03:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.tauriWatcher && this.tauriWatcher.close()
|
|
|
|
this.__stopCargo().then(resolve)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
__runCargoCommand ({
|
2019-08-20 00:09:29 +03:00
|
|
|
cargoArgs,
|
2019-12-18 00:39:34 +03:00
|
|
|
extraArgs,
|
|
|
|
dev = false
|
2019-08-20 00:09:29 +03:00
|
|
|
}) {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
this.pid = spawn(
|
|
|
|
'cargo',
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
extraArgs
|
|
|
|
? cargoArgs.concat(['--']).concat(extraArgs)
|
|
|
|
: cargoArgs,
|
2019-08-20 00:09:29 +03:00
|
|
|
|
2019-10-07 21:36:56 +03:00
|
|
|
tauriDir,
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
code => {
|
|
|
|
if (code) {
|
|
|
|
warn()
|
2019-11-16 21:51:46 +03:00
|
|
|
warn('⚠️ [FAIL] Cargo CLI has failed')
|
2019-08-20 00:09:29 +03:00
|
|
|
warn()
|
|
|
|
process.exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.killPromise) {
|
|
|
|
this.killPromise()
|
|
|
|
this.killPromise = null
|
2019-12-18 00:39:34 +03:00
|
|
|
} else if (dev) {
|
2019-08-20 00:09:29 +03:00
|
|
|
warn()
|
|
|
|
warn('Cargo process was killed. Exiting...')
|
|
|
|
warn()
|
|
|
|
process.exit(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
resolve()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
__stopCargo () {
|
2019-08-20 00:09:29 +03:00
|
|
|
const pid = this.pid
|
|
|
|
|
|
|
|
if (!pid) {
|
|
|
|
return Promise.resolve()
|
|
|
|
}
|
|
|
|
|
|
|
|
log('Shutting down tauri process...')
|
|
|
|
this.pid = 0
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.killPromise = resolve
|
|
|
|
process.kill(pid)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
__manipulateToml (callback) {
|
2019-11-30 21:39:13 +03:00
|
|
|
const toml = require('@tauri-apps/toml')
|
2019-11-16 21:51:46 +03:00
|
|
|
const tomlPath = path.join(tauriDir, 'Cargo.toml')
|
|
|
|
const tomlFile = readFileSync(tomlPath)
|
|
|
|
const tomlContents = toml.parse(tomlFile)
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
callback(tomlContents)
|
|
|
|
|
|
|
|
const output = toml.stringify(tomlContents)
|
|
|
|
writeFileSync(tomlPath, output)
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:51:46 +03:00
|
|
|
__whitelistApi (cfg, tomlContents) {
|
2019-11-30 14:48:39 +03:00
|
|
|
const tomlFeatures = []
|
2019-08-20 00:09:29 +03:00
|
|
|
|
|
|
|
if (cfg.tauri.whitelist.all) {
|
2019-11-30 14:48:39 +03:00
|
|
|
tomlFeatures.push('all-api')
|
2019-08-20 00:09:29 +03:00
|
|
|
} else {
|
|
|
|
const whitelist = Object.keys(cfg.tauri.whitelist).filter(w => cfg.tauri.whitelist[w] === true)
|
2019-11-30 14:48:39 +03:00
|
|
|
tomlFeatures.push(...whitelist)
|
2019-08-20 00:09:29 +03:00
|
|
|
}
|
2019-11-30 14:48:39 +03:00
|
|
|
|
|
|
|
if (cfg.tauri.edge.active) {
|
|
|
|
tomlFeatures.push('edge')
|
|
|
|
}
|
|
|
|
|
|
|
|
tomlContents.dependencies.tauri.features = tomlFeatures
|
2019-08-20 00:09:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-07 21:36:56 +03:00
|
|
|
module.exports = Runner
|