@tauri-apps/cli 1.0.0-beta.9 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.github-example/workflows/CI.yml +469 -0
  2. package/CHANGELOG.md +14 -302
  3. package/Cargo.toml +16 -0
  4. package/README.md +1 -1
  5. package/build.rs +7 -0
  6. package/index.d.ts +12 -0
  7. package/index.js +241 -0
  8. package/jest.config.js +14 -0
  9. package/package.json +45 -89
  10. package/src/lib.rs +10 -0
  11. package/tauri.js +50 -0
  12. package/test/jest/__tests__/template.spec.js +41 -0
  13. package/test/jest/fixtures/app/dist/index.html +140 -0
  14. package/test/jest/fixtures/app/index.js +53 -0
  15. package/test/jest/fixtures/app/package.json +22 -0
  16. package/test/jest/fixtures/app/src-tauri/Cargo.toml +34 -0
  17. package/test/jest/fixtures/app/src-tauri/build.rs +7 -0
  18. package/test/jest/fixtures/app/src-tauri/icons/128x128.png +0 -0
  19. package/test/jest/fixtures/app/src-tauri/icons/128x128@2x.png +0 -0
  20. package/test/jest/fixtures/app/src-tauri/icons/32x32.png +0 -0
  21. package/test/jest/fixtures/app/src-tauri/icons/icon.icns +0 -0
  22. package/test/jest/fixtures/app/src-tauri/icons/icon.ico +0 -0
  23. package/test/jest/fixtures/app/src-tauri/icons/icon.png +0 -0
  24. package/test/jest/fixtures/app/src-tauri/src/main.rs +20 -0
  25. package/test/jest/fixtures/app/src-tauri/tauri.conf.json +28 -0
  26. package/test/jest/fixtures/app-test-setup.js +86 -0
  27. package/test/jest/fixtures/empty/dist/index.html +6 -0
  28. package/test/jest/fixtures/empty/package.json +1 -0
  29. package/test/jest/helpers/logger.js +25 -0
  30. package/test/jest/helpers/spawn.js +73 -0
  31. package/test/jest/jest.setup.js +6 -0
  32. package/LICENSE_APACHE-2.0 +0 -177
  33. package/LICENSE_MIT +0 -21
  34. package/bin/tauri-deps.js +0 -26
  35. package/bin/tauri-icon.js +0 -61
  36. package/bin/tauri.js +0 -101
  37. package/dist/api/cli.js +0 -1
  38. package/dist/api/dependency-manager.js +0 -1
  39. package/dist/api/tauricon.js +0 -1
  40. package/dist/app-paths-46150e8b.js +0 -1
  41. package/dist/helpers/download-binary.js +0 -1
  42. package/dist/helpers/rust-cli.js +0 -1
  43. package/dist/helpers/spawn.js +0 -1
  44. package/dist/logger-27e93e7d.js +0 -1
  45. package/dist/tslib.es6-753a81cf.js +0 -1
package/jest.config.js ADDED
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ setupFilesAfterEnv: ['<rootDir>/test/jest/jest.setup.js'],
3
+ testMatch: [
4
+ '<rootDir>/test/jest/__tests__/**/*.spec.js',
5
+ '<rootDir>/test/jest/__tests__/**/*.test.js'
6
+ ],
7
+ moduleFileExtensions: ['ts', 'js', 'json'],
8
+ moduleNameMapper: {
9
+ '^~/(.*)$': '<rootDir>/$1'
10
+ },
11
+ transform: {
12
+ '\\.toml$': 'jest-transform-toml'
13
+ }
14
+ }
package/package.json CHANGED
@@ -1,33 +1,11 @@
1
1
  {
2
2
  "name": "@tauri-apps/cli",
3
- "version": "1.0.0-beta.9",
3
+ "version": "1.0.0-rc.0",
4
4
  "description": "Command line interface for building Tauri apps",
5
- "type": "module",
6
- "bin": {
7
- "tauri": "./bin/tauri.js"
8
- },
9
- "files": [
10
- "bin",
11
- "dist",
12
- "scripts"
13
- ],
14
5
  "funding": {
15
6
  "type": "opencollective",
16
7
  "url": "https://opencollective.com/tauri"
17
8
  },
18
- "scripts": {
19
- "build": "rimraf ./dist && rollup -c --silent",
20
- "build-release": "rimraf ./dist && cross-env NODE_ENV=production rollup -c",
21
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --runInBand --forceExit --no-cache --testPathIgnorePatterns=\"(build|dev)\"",
22
- "pretest": "yarn build",
23
- "prepublishOnly": "yarn build-release",
24
- "test:local": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --runInBand --forceExit",
25
- "lint": "eslint --ext ts \"./src/**/*.ts\"",
26
- "lint-fix": "eslint --fix --ext ts \"./src/**/*.ts\"",
27
- "lint:lockfile": "lockfile-lint --path yarn.lock --type yarn --validate-https --allowed-hosts npm yarn",
28
- "format": "prettier --write --end-of-line=auto \"./**/*.{cjs,js,jsx,ts,tsx,html,css,json}\" --ignore-path .gitignore",
29
- "format:check": "prettier --check --end-of-line=auto \"./**/*.{cjs,js,jsx,ts,tsx,html,css,json}\" --ignore-path .gitignore"
30
- },
31
9
  "repository": {
32
10
  "type": "git",
33
11
  "url": "git+https://github.com/tauri-apps/tauri.git"
@@ -43,75 +21,53 @@
43
21
  "publishConfig": {
44
22
  "access": "public"
45
23
  },
46
- "engines": {
47
- "node": ">= 12.20.0",
48
- "npm": ">= 6.6.0",
49
- "yarn": ">= 1.19.1"
24
+ "main": "index.js",
25
+ "types": "index.d.ts",
26
+ "napi": {
27
+ "name": "cli",
28
+ "triples": {
29
+ "additional": [
30
+ "aarch64-apple-darwin",
31
+ "aarch64-unknown-linux-gnu",
32
+ "aarch64-unknown-linux-musl",
33
+ "armv7-unknown-linux-gnueabihf",
34
+ "x86_64-unknown-linux-musl"
35
+ ]
36
+ }
50
37
  },
51
- "dependencies": {
52
- "@tauri-apps/toml": "2.2.4",
53
- "chalk": "4.1.2",
54
- "cross-env": "7.0.3",
38
+ "devDependencies": {
39
+ "@napi-rs/cli": "2.4.2",
55
40
  "cross-spawn": "7.0.3",
56
41
  "fs-extra": "10.0.0",
57
- "global-agent": "3.0.0",
58
- "got": "11.8.2",
59
- "imagemin": "8.0.1",
60
- "imagemin-optipng": "8.0.0",
61
- "imagemin-zopfli": "7.0.0",
62
- "inquirer": "8.1.2",
63
- "is-png": "3.0.0",
64
- "minimist": "1.2.5",
65
- "ms": "2.1.3",
66
- "png2icons": "2.0.1",
67
- "read-chunk": "3.2.0",
68
- "semver": "7.3.5",
69
- "sharp": "0.28.3",
70
- "update-notifier": "5.1.0"
71
- },
72
- "devDependencies": {
73
- "@babel/core": "7.15.0",
74
- "@babel/preset-env": "7.15.0",
75
- "@babel/preset-typescript": "7.15.0",
76
- "@jest/globals": "27.0.6",
77
- "@rollup/plugin-babel": "5.3.0",
78
- "@rollup/plugin-commonjs": "20.0.0",
79
- "@rollup/plugin-node-resolve": "13.0.4",
80
- "@rollup/plugin-replace": "^3.0.0",
81
- "@rollup/plugin-typescript": "8.2.5",
82
- "@types/cross-spawn": "6.0.2",
83
- "@types/fs-extra": "9.0.12",
84
- "@types/global-agent": "2.1.1",
85
- "@types/imagemin": "7.0.1",
86
- "@types/imagemin-optipng": "5.2.1",
87
- "@types/inquirer": "7.3.3",
88
- "@types/ms": "0.7.31",
89
- "@types/semver": "7.3.8",
90
- "@types/sharp": "0.28.5",
91
- "@typescript-eslint/eslint-plugin": "4.29.1",
92
- "@typescript-eslint/parser": "4.29.1",
93
- "babel-jest": "27.0.6",
94
- "eslint": "7.32.0",
95
- "eslint-config-prettier": "8.3.0",
96
- "eslint-config-standard-with-typescript": "20.0.0",
97
- "eslint-plugin-import": "2.24.0",
98
- "eslint-plugin-lodash-template": "0.19.0",
99
- "eslint-plugin-node": "11.1.0",
100
- "eslint-plugin-promise": "5.1.0",
101
- "eslint-plugin-security": "1.4.0",
102
- "is-running": "2.1.0",
103
- "jest": "27.0.6",
42
+ "jest": "27.5.1",
104
43
  "jest-transform-toml": "1.0.0",
105
- "lockfile-lint": "4.6.2",
106
- "prettier": "2.3.2",
107
- "promise": "8.1.0",
108
- "rimraf": "3.0.2",
109
- "rollup": "2.56.2",
110
- "rollup-plugin-terser": "7.0.2",
111
- "tslib": "2.3.1",
112
- "typescript": "4.3.5"
44
+ "prettier": "2.5.1"
45
+ },
46
+ "engines": {
47
+ "node": ">= 10"
48
+ },
49
+ "bin": {
50
+ "tauri": "./tauri.js"
51
+ },
52
+ "scripts": {
53
+ "artifacts": "napi artifacts",
54
+ "build": "napi build --platform --release",
55
+ "build:debug": "napi build --platform",
56
+ "prepublishOnly": "napi prepublish -t npm",
57
+ "test": "jest --runInBand --forceExit --no-cache",
58
+ "version": "napi version",
59
+ "tauri": "node ./tauri.js",
60
+ "format": "prettier --write ./package.json ./tauri.js",
61
+ "format:check": "prettier --check ./package.json ./tauri.js"
113
62
  },
114
- "resolutions": {
115
- "**/trim-newlines": "4.0.2"
63
+ "optionalDependencies": {
64
+ "@tauri-apps/cli-win32-x64-msvc": "1.0.0-rc.0",
65
+ "@tauri-apps/cli-darwin-x64": "1.0.0-rc.0",
66
+ "@tauri-apps/cli-linux-x64-gnu": "1.0.0-rc.0",
67
+ "@tauri-apps/cli-darwin-arm64": "1.0.0-rc.0",
68
+ "@tauri-apps/cli-linux-arm64-gnu": "1.0.0-rc.0",
69
+ "@tauri-apps/cli-linux-arm64-musl": "1.0.0-rc.0",
70
+ "@tauri-apps/cli-linux-arm-gnueabihf": "1.0.0-rc.0",
71
+ "@tauri-apps/cli-linux-x64-musl": "1.0.0-rc.0"
116
72
  }
117
- }
73
+ }
package/src/lib.rs ADDED
@@ -0,0 +1,10 @@
1
+ // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-License-Identifier: MIT
4
+
5
+ use napi::{Error, Result, Status};
6
+
7
+ #[napi_derive::napi]
8
+ pub fn run(args: Vec<String>, bin_name: Option<String>) -> Result<()> {
9
+ tauri_cli::run(args, bin_name).map_err(|e| Error::new(Status::GenericFailure, e.to_string()))
10
+ }
package/tauri.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+
3
+ const cli = require('./index')
4
+ const path = require('path')
5
+
6
+ const [bin, script, ...arguments] = process.argv
7
+ const binStem = path.parse(bin).name.toLowerCase()
8
+
9
+ // We want to make a helpful binary name for the underlying CLI helper, if we
10
+ // can successfully detect what command likely started the execution.
11
+ let binName
12
+
13
+ // Even if started by a package manager, the binary will be NodeJS.
14
+ // Some distribution still use "nodejs" as the binary name.
15
+ if (binStem === 'node' || binStem === 'nodejs') {
16
+ const managerStem = process.env.npm_execpath
17
+ ? path.parse(process.env.npm_execpath).name.toLowerCase()
18
+ : null
19
+ if (managerStem) {
20
+ let manager
21
+ switch (managerStem) {
22
+ // Only supported package manager that has a different filename is npm.
23
+ case 'npm-cli':
24
+ manager = 'npm'
25
+ break
26
+
27
+ // Yarn and pnpm have the same stem name as their bin.
28
+ // We assume all unknown package managers do as well.
29
+ default:
30
+ manager = managerStem
31
+ break
32
+ }
33
+
34
+ binName = `${manager} run ${process.env.npm_lifecycle_event}`
35
+ } else {
36
+ // Assume running NodeJS if we didn't detect a manager from the env.
37
+ // We normalize the path to prevent the script's absolute path being used.
38
+ const scriptNormal = path.normalize(path.relative(process.cwd(), script))
39
+ binName = `${binStem} ${scriptNormal}`
40
+ }
41
+ } else {
42
+ // We don't know what started it, assume it's already stripped.
43
+ arguments.unshift(bin)
44
+ }
45
+
46
+ try {
47
+ cli.run(arguments, binName)
48
+ } catch (e) {
49
+ console.log(`Eror running CLI: ${e.message}`)
50
+ }
@@ -0,0 +1,41 @@
1
+ const fixtureSetup = require('../fixtures/app-test-setup.js')
2
+ const { resolve } = require('path')
3
+ const { existsSync, readFileSync, writeFileSync } = require('fs')
4
+ const { move } = require('fs-extra')
5
+ const cli = require('~/index.js')
6
+
7
+ const currentDirName = __dirname
8
+
9
+ describe('[CLI] cli.js template', () => {
10
+ it('init a project and builds it', async () => {
11
+ const cwd = process.cwd()
12
+ const fixturePath = resolve(currentDirName, '../fixtures/empty')
13
+ const tauriFixturePath = resolve(fixturePath, 'src-tauri')
14
+ const outPath = resolve(tauriFixturePath, 'target')
15
+ const cacheOutPath = resolve(fixturePath, 'target')
16
+
17
+ fixtureSetup.initJest('empty')
18
+
19
+ process.chdir(fixturePath)
20
+
21
+ const outExists = existsSync(outPath)
22
+ if (outExists) {
23
+ await move(outPath, cacheOutPath)
24
+ }
25
+
26
+ cli.run(['init', '--directory', process.cwd(), '--force', '--tauri-path', resolve(currentDirName, '../../../../../..'), '--ci'])
27
+
28
+ if (outExists) {
29
+ await move(cacheOutPath, outPath)
30
+ }
31
+
32
+ process.chdir(tauriFixturePath)
33
+
34
+ const manifestPath = resolve(tauriFixturePath, 'Cargo.toml')
35
+ const manifestFile = readFileSync(manifestPath).toString()
36
+ writeFileSync(manifestPath, `workspace = { }\n${manifestFile}`)
37
+
38
+ cli.run(['build', '--verbose'])
39
+ process.chdir(cwd)
40
+ })
41
+ })
@@ -0,0 +1,140 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <body>
4
+ <script>
5
+ function callBackEnd(route, args) {
6
+ console.log(route)
7
+ console.log(args)
8
+ window.__TAURI__.http
9
+ .fetch('http://localhost:7000/' + route, {
10
+ method: 'POST',
11
+ body: window.__TAURI__.http.Body.json(args),
12
+ responseType: window.__TAURI__.http.ResponseType.Binary
13
+ })
14
+ .catch(console.error)
15
+ }
16
+
17
+ function reply(args) {
18
+ return callBackEnd('reply', args)
19
+ }
20
+
21
+ function sendError(error) {
22
+ return callBackEnd('error', error)
23
+ }
24
+
25
+ function testFs(dir) {
26
+ var contents = 'TAURI E2E TEST FILE'
27
+ var commandSuffix = dir ? 'WithDir' : ''
28
+
29
+ var options = {
30
+ dir: dir || null
31
+ }
32
+
33
+ return window.__TAURI__.fs
34
+ .writeFile(
35
+ {
36
+ path: 'tauri-test.txt',
37
+ contents: contents
38
+ },
39
+ options
40
+ )
41
+ .then(function (res) {
42
+ reply({
43
+ cmd: 'writeFile' + commandSuffix
44
+ })
45
+ return window.__TAURI__.fs
46
+ .readTextFile('tauri-test.txt', options)
47
+ .then(function (res) {
48
+ if (res === contents) {
49
+ reply({
50
+ cmd: 'readFile' + commandSuffix
51
+ })
52
+
53
+ return window.__TAURI__.fs
54
+ .readDir('.', options)
55
+ .then((res) => {
56
+ reply({
57
+ cmd: 'readDir' + commandSuffix
58
+ })
59
+
60
+ return window.__TAURI__.fs
61
+ .copyFile(
62
+ 'tauri-test.txt',
63
+ 'tauri-test-copy.txt',
64
+ options
65
+ )
66
+ .then(function (res) {
67
+ reply({
68
+ cmd: 'copyFile' + commandSuffix
69
+ })
70
+
71
+ return window.__TAURI__.fs
72
+ .createDir('tauri-test-dir', options)
73
+ .then(function (res) {
74
+ reply({
75
+ cmd: 'createDir' + commandSuffix
76
+ })
77
+ return window.__TAURI__.fs
78
+ .removeDir('tauri-test-dir', options)
79
+ .then(function (res) {
80
+ reply({
81
+ cmd: 'removeDir' + commandSuffix
82
+ })
83
+ })
84
+ })
85
+ .then(function (res) {
86
+ return window.__TAURI__.fs
87
+ .renameFile(
88
+ 'tauri-test.txt',
89
+ 'tauri.testt.txt',
90
+ options
91
+ )
92
+ .then(function (res) {
93
+ reply({
94
+ cmd: 'renameFile' + commandSuffix
95
+ })
96
+ return Promise.all([
97
+ window.__TAURI__.fs.removeFile(
98
+ 'tauri.testt.txt',
99
+ options
100
+ ),
101
+ window.__TAURI__.fs.removeFile(
102
+ 'tauri-test-copy.txt',
103
+ options
104
+ )
105
+ ]).then(function (res) {
106
+ reply({
107
+ cmd: 'removeFile' + commandSuffix
108
+ })
109
+ })
110
+ })
111
+ })
112
+ })
113
+ })
114
+ } else {
115
+ sendError('expected "' + contents + '" found "' + res + '"')
116
+ }
117
+ })
118
+ })
119
+ .catch(sendError)
120
+ }
121
+
122
+ window.__TAURI__.event.listen('reply', function (res) {
123
+ reply({
124
+ cmd: 'listen'
125
+ })
126
+ })
127
+ window.onTauriInit = function () {
128
+ window.__TAURI__.event.emit('hello')
129
+ }
130
+
131
+ testFs(null).then(function () {
132
+ testFs(window.__TAURI__.fs.Dir.Config)
133
+ })
134
+
135
+ setTimeout(function () {
136
+ window.__TAURI__.invoke('exit')
137
+ }, 15000)
138
+ </script>
139
+ </body>
140
+ </html>
@@ -0,0 +1,53 @@
1
+ const express = require('express')
2
+ const cors = require('cors')
3
+ const app = express()
4
+ app.use(cors())
5
+ app.use(express.json())
6
+ const port = 7000
7
+ let appPid
8
+
9
+ app.post('/reply', (req, res) => {
10
+ if (req.body && req.body.msg !== 'TEST') {
11
+ throw new Error(`unexpected reply ${JSON.stringify(req.body)}`)
12
+ }
13
+ console.log('App event replied')
14
+ exit(0)
15
+ })
16
+
17
+ const server = app.listen(port, () =>
18
+ console.log(`Test listening on port ${port}!`)
19
+ )
20
+
21
+ const exit = (code) => {
22
+ server.close()
23
+ process.kill(appPid)
24
+ process.exit(code)
25
+ }
26
+
27
+ const path = require('path')
28
+ const dist = path.resolve(__dirname, 'dist')
29
+
30
+ const build = require('../tooling/cli.js/dist/api/build')
31
+ build({
32
+ build: {
33
+ devPath: dist
34
+ },
35
+ ctx: {
36
+ debug: true
37
+ }
38
+ }).then(() => {
39
+ const spawn = require('../tooling/cli.js/dist/helpers/spawn').spawn
40
+ const artifactPath = path.resolve(__dirname, 'src-tauri/target/debug/app')
41
+ appPid = spawn(
42
+ process.platform === 'win32'
43
+ ? `${artifactPath}.exe`
44
+ : artifactPath.replace('debug/app', 'debug/./app'),
45
+ [],
46
+ null
47
+ )
48
+
49
+ // if it didn't reply, throw an error
50
+ setTimeout(() => {
51
+ throw new Error("App didn't reply")
52
+ }, 2000)
53
+ })
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "test",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "tauri:prod": "tauri",
8
+ "tauri:source": "node ../../../../bin/tauri",
9
+ "tauri:source:init": "yarn tauri:source init --tauriPath ..",
10
+ "tauri:prod:init": "yarn tauri:prod init",
11
+ "tauri:source:dev": "yarn tauri:source dev",
12
+ "tauri:prod:dev": "yarn tauri:prod dev",
13
+ "tauri:source:build": "yarn tauri:source build",
14
+ "tauri:prod:build": "yarn tauri:prod build"
15
+ },
16
+ "author": "",
17
+ "license": "Apache-2.0 OR MIT",
18
+ "dependencies": {
19
+ "cors": "^2.8.5",
20
+ "express": "^4.17.1"
21
+ }
22
+ }
@@ -0,0 +1,34 @@
1
+ workspace = { }
2
+
3
+ [package]
4
+ name = "app"
5
+ version = "0.1.0"
6
+ description = "A Tauri App"
7
+ authors = [ "Tauri Programme within The Commons Conservancy" ]
8
+ license = ""
9
+ repository = ""
10
+ edition = "2021"
11
+ rust-version = "1.57"
12
+
13
+ [package.metadata.bundle]
14
+ identifier = "com.tauri.dev"
15
+ icon = [
16
+ "icons/32x32.png",
17
+ "icons/128x128.png",
18
+ "icons/128x128@2x.png",
19
+ "icons/icon.icns",
20
+ "icons/icon.ico"
21
+ ]
22
+
23
+ [build-dependencies]
24
+ tauri-build = { path = "../../../../../../../core/tauri-build", features = [] }
25
+
26
+ [dependencies]
27
+ serde_json = "1.0.74"
28
+ serde = "1.0"
29
+ serde_derive = "1.0"
30
+ tauri = { path = "../../../../../../../core/tauri", features = ["api-all"] }
31
+
32
+ [features]
33
+ default = [ "custom-protocol" ]
34
+ custom-protocol = [ "tauri/custom-protocol" ]
@@ -0,0 +1,7 @@
1
+ // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-License-Identifier: MIT
4
+
5
+ fn main() {
6
+ tauri_build::build()
7
+ }
@@ -0,0 +1,20 @@
1
+ #[tauri::command(with_window)]
2
+ fn exit(window: tauri::Window) {
3
+ window.close().unwrap();
4
+ }
5
+
6
+ fn main() {
7
+ tauri::Builder::default()
8
+ .on_page_load(|window, _| {
9
+ let window_ = window.clone();
10
+ window.listen("hello".into(), move |_| {
11
+ window_
12
+ .emit(&"reply".to_string(), Some("{ msg: 'TEST' }".to_string()))
13
+ .unwrap();
14
+ });
15
+ window.eval("window.onTauriInit()").unwrap();
16
+ })
17
+ .invoke_handler(tauri::generate_handler![exit])
18
+ .run(tauri::generate_context!())
19
+ .expect("error encountered while running tauri application");
20
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "build": {
3
+ "devPath": "../dist",
4
+ "distDir": "../dist",
5
+ "withGlobalTauri": true
6
+ },
7
+ "tauri": {
8
+ "allowlist": {
9
+ "all": true
10
+ },
11
+ "bundle": {
12
+ "icon": [
13
+ "icons/32x32.png",
14
+ "icons/128x128.png",
15
+ "icons/128x128@2x.png",
16
+ "icons/icon.icns",
17
+ "icons/icon.ico"
18
+ ],
19
+ "identifier": "fixture.app"
20
+ },
21
+ "windows": [
22
+ {
23
+ "title": "Fixture",
24
+ "visible": false
25
+ }
26
+ ]
27
+ }
28
+ }