bare-build 0.0.0 → 0.0.1

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.
package/bin.js CHANGED
@@ -13,11 +13,12 @@ const cmd = command(
13
13
  flag('--author <name>', 'The name of the application author'),
14
14
  flag('--description <text>', 'The description of the application'),
15
15
  flag('--icon|-i <path>', 'The application icon'),
16
+ flag('--identifier <id>', 'The unique application identifier'),
16
17
  flag('--target|-t <host>', 'The host to target').multiple(),
17
18
  flag('--out|-o <dir>', 'The output directory'),
18
19
  async (cmd) => {
19
20
  const { entry } = cmd.args
20
- const { version, name, author, description, icon, target, out } = cmd.flags
21
+ const { version, name, author, description, icon, identifier, target, out } = cmd.flags
21
22
 
22
23
  if (version) return console.log(`v${pkg.version}`)
23
24
 
@@ -27,6 +28,7 @@ const cmd = command(
27
28
  author,
28
29
  description,
29
30
  icon,
31
+ identifier,
30
32
  target,
31
33
  out
32
34
  })
package/index.js CHANGED
@@ -12,6 +12,8 @@ const windows = require('./lib/platform/windows')
12
12
  module.exports = async function build(entry, opts = {}) {
13
13
  const { base = path.resolve('.'), target = [], hosts = target } = opts
14
14
 
15
+ const pkg = require(path.join(base, 'package.json'))
16
+
15
17
  let bundle = await pack(
16
18
  pathToFileURL(entry),
17
19
  {
@@ -63,6 +65,6 @@ module.exports = async function build(entry, opts = {}) {
63
65
  }
64
66
 
65
67
  for (const [platform, hosts] of groups) {
66
- await platform(base, bundle, { ...opts, hosts })
68
+ await platform(base, pkg, bundle, { ...opts, hosts })
67
69
  }
68
70
  }
@@ -0,0 +1,17 @@
1
+ const fs = require('fs')
2
+
3
+ require.asset = require('require-asset')
4
+
5
+ try {
6
+ const appimagetool = require.asset('#appimagetool', __filename)
7
+
8
+ try {
9
+ fs.accessSync(appimagetool, fs.constants.X_OK)
10
+ } catch {
11
+ fs.chmodSync(appimagetool, 0o755)
12
+ }
13
+
14
+ module.exports = appimagetool
15
+ } catch {
16
+ module.exports = null
17
+ }
package/lib/fs.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const path = require('path')
2
2
  const fs = require('fs')
3
+ const os = require('os')
3
4
 
4
5
  exports.rm = async function rm(name) {
5
6
  return new Promise((resolve, reject) => {
@@ -61,3 +62,19 @@ exports.makeDir = async function makeDir(name) {
61
62
  })
62
63
  })
63
64
  }
65
+
66
+ exports.tempDir = async function tempDir() {
67
+ const name = Math.random().toString(16).slice(2)
68
+
69
+ return new Promise((resolve, reject) => {
70
+ fs.realpath(os.tmpdir(), (err, dir) => {
71
+ if (err) return reject(err)
72
+
73
+ dir = path.join(dir, `bare-build-${name}`)
74
+
75
+ fs.mkdir(dir, { recursive: true }, (err) => {
76
+ err ? reject(err) : resolve(dir)
77
+ })
78
+ })
79
+ })
80
+ }
@@ -5,7 +5,7 @@ const fs = require('../fs')
5
5
  const run = require('../run')
6
6
  const prebuilds = require('../prebuilds')
7
7
 
8
- module.exports = async function build(base, bundle, opts = {}) {
8
+ module.exports = async function build(base, pkg, bundle, opts = {}) {
9
9
  const { hosts = [], out = path.resolve('.') } = opts
10
10
 
11
11
  const archs = new Map([
@@ -44,7 +44,7 @@ module.exports = async function build(base, bundle, opts = {}) {
44
44
 
45
45
  for (const [os, hosts] of archs) {
46
46
  apps.push(
47
- await app(os, base, bundle, hosts, {
47
+ await app(base, pkg, bundle, hosts, {
48
48
  ...opts,
49
49
  out: archs.size === 1 ? out : path.join(out, os)
50
50
  })
@@ -55,10 +55,10 @@ module.exports = async function build(base, bundle, opts = {}) {
55
55
  }
56
56
 
57
57
  // https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle
58
- async function app(os, base, bundle, hosts, opts = {}) {
59
- const isMac = os === 'macos'
58
+ async function app(base, pkg, bundle, hosts, opts = {}) {
59
+ const isMac = hosts.some((host) => host.startsWith('darwin'))
60
60
 
61
- const { name = 'App', version = '1.0.0', icon, out = path.resolve('.') } = opts
61
+ const { name = pkg.name, version = pkg.version, icon, out = path.resolve('.') } = opts
62
62
 
63
63
  const app = path.join(out, `${name}.app`)
64
64
  await fs.makeDir(app)
@@ -85,7 +85,7 @@ async function app(os, base, bundle, hosts, opts = {}) {
85
85
 
86
86
  await run('lipo', ['-create', '-output', executable, ...inputs])
87
87
 
88
- await fs.writeFile(path.join(main, 'Info.plist'), plist(os, name, version))
88
+ await fs.writeFile(path.join(main, 'Info.plist'), plist(isMac, name, version, opts))
89
89
 
90
90
  await fs.writeFile(path.join(main, 'PkgInfo'), 'APPL????')
91
91
 
@@ -100,16 +100,13 @@ async function app(os, base, bundle, hosts, opts = {}) {
100
100
 
101
101
  await fs.writeFile(path.join(resources, 'app.bundle'), bundle.toBuffer())
102
102
 
103
- if (icon) await fs.cp(path.resolve(icon), path.join(resources, 'app' + path.extname(icon)))
103
+ await fs.cp(path.resolve(icon), path.join(resources, 'app' + path.extname(icon)))
104
104
 
105
105
  return app
106
106
  }
107
107
 
108
- // https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleidentifier
109
- const invalidBundleIdentifierCharacter = /[^A-Za-z0-9.-]/g
110
-
111
- function plist(os, name, version) {
112
- const isMac = os === 'macos'
108
+ function plist(isMac, name, version, opts = {}) {
109
+ const { identifier = toIdentifier(name) } = opts
113
110
 
114
111
  version = version.match(/^\d+(\.\d+){0,2}/).at(0)
115
112
 
@@ -119,7 +116,7 @@ function plist(os, name, version) {
119
116
  <plist version="1.0">
120
117
  <dict>
121
118
  <key>CFBundleIdentifier</key>
122
- <string>${name.replace(invalidBundleIdentifierCharacter, '-')}.${version}</string>
119
+ <string>${identifier}</string>
123
120
  <key>CFBundleVersion</key>
124
121
  <string>${version}</string>
125
122
  <key>CFBundleShortVersionString</key>
@@ -138,3 +135,10 @@ function plist(os, name, version) {
138
135
  </plist>
139
136
  `
140
137
  }
138
+
139
+ // https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleidentifier
140
+ const invalidBundleIdentifierCharacter = /[^A-Za-z0-9.-]/g
141
+
142
+ function toIdentifier(input) {
143
+ return input.replace(invalidBundleIdentifierCharacter, '')
144
+ }
@@ -2,9 +2,11 @@ const path = require('path')
2
2
  const link = require('bare-link')
3
3
  const unpack = require('bare-unpack')
4
4
  const fs = require('../fs')
5
+ const run = require('../run')
5
6
  const prebuilds = require('../prebuilds')
7
+ const appimagetool = require('../appimagetool')
6
8
 
7
- module.exports = async function build(base, bundle, opts = {}) {
9
+ module.exports = async function build(base, pkg, bundle, opts = {}) {
8
10
  const { hosts = [], out = path.resolve('.') } = opts
9
11
 
10
12
  const archs = new Map()
@@ -30,7 +32,7 @@ module.exports = async function build(base, bundle, opts = {}) {
30
32
 
31
33
  for (const [arch, host] of archs) {
32
34
  result.push(
33
- await appDir(base, bundle, host, {
35
+ await appImage(pkg, await appDir(base, pkg, bundle, host, opts), {
34
36
  ...opts,
35
37
  out: archs.size === 1 ? out : path.join(out, arch)
36
38
  })
@@ -41,8 +43,10 @@ module.exports = async function build(base, bundle, opts = {}) {
41
43
  }
42
44
 
43
45
  // https://docs.appimage.org/reference/appdir.html
44
- async function appDir(base, bundle, host, opts = {}) {
45
- const { name = 'App', icon, out = path.resolve('.') } = opts
46
+ async function appDir(base, pkg, bundle, host, opts = {}) {
47
+ const { name = pkg.name, icon } = opts
48
+
49
+ const out = await fs.tempDir()
46
50
 
47
51
  const app = path.join(out, name + '.AppDir')
48
52
 
@@ -87,23 +91,31 @@ async function appDir(base, bundle, host, opts = {}) {
87
91
 
88
92
  await fs.writeFile(path.join(data, 'app.bundle'), bundle.toBuffer())
89
93
 
90
- if (icon) {
91
- const icons = path.join(share, 'icons')
92
- await fs.makeDir(icons)
94
+ const icons = path.join(share, 'icons')
95
+ await fs.makeDir(icons)
93
96
 
94
- await fs.cp(path.resolve(icon), path.join(icons, name + path.extname(icon)))
97
+ await fs.cp(path.resolve(icon), path.join(icons, name + path.extname(icon)))
95
98
 
96
- await fs.symlink(
97
- path.join('usr', 'share', 'icons', name + path.extname(icon)),
98
- path.join(app, name + path.extname(icon))
99
- )
99
+ await fs.symlink(
100
+ path.join('usr', 'share', 'icons', name + path.extname(icon)),
101
+ path.join(app, name + path.extname(icon))
102
+ )
100
103
 
101
- await fs.symlink(name + path.extname(icon), path.join(app, '.DirIcon'))
102
- }
104
+ await fs.symlink(name + path.extname(icon), path.join(app, '.DirIcon'))
103
105
 
104
106
  return app
105
107
  }
106
108
 
109
+ async function appImage(pkg, appDir, opts = {}) {
110
+ const { name = pkg.name, out = path.resolve('.') } = opts
111
+
112
+ const appImage = path.join(out, name + '.AppImage')
113
+
114
+ await run(appimagetool, [appDir, appImage])
115
+
116
+ return appImage
117
+ }
118
+
107
119
  function desktop(name) {
108
120
  return `\
109
121
  [Desktop Entry]
@@ -2,9 +2,10 @@ const path = require('path')
2
2
  const link = require('bare-link')
3
3
  const unpack = require('bare-unpack')
4
4
  const fs = require('../fs')
5
+ const run = require('../run')
5
6
  const prebuilds = require('../prebuilds')
6
7
 
7
- module.exports = async function build(base, bundle, opts = {}) {
8
+ module.exports = async function build(base, pkg, bundle, opts = {}) {
8
9
  const { hosts = [], out = path.resolve('.') } = opts
9
10
 
10
11
  const archs = new Map()
@@ -30,8 +31,9 @@ module.exports = async function build(base, bundle, opts = {}) {
30
31
 
31
32
  for (const [arch, host] of archs) {
32
33
  result.push(
33
- await appx(base, bundle, host, {
34
+ await appx(base, pkg, bundle, {
34
35
  ...opts,
36
+ host,
35
37
  out: archs.size === 1 ? out : path.join(out, arch)
36
38
  })
37
39
  )
@@ -40,10 +42,12 @@ module.exports = async function build(base, bundle, opts = {}) {
40
42
  return result
41
43
  }
42
44
 
43
- async function appx(base, bundle, host, opts = {}) {
44
- const { name = 'App', icon, out = path.resolve('.') } = opts
45
+ async function appx(base, pkg, bundle, opts = {}) {
46
+ const { name = pkg.name, icon, host, out = path.resolve('.') } = opts
45
47
 
46
- const app = path.join(out, name)
48
+ const tmp = await fs.tempDir()
49
+
50
+ const app = path.join(tmp, name)
47
51
 
48
52
  const bin = path.join(app, 'App')
49
53
  await fs.makeDir(bin)
@@ -70,7 +74,7 @@ async function appx(base, bundle, host, opts = {}) {
70
74
 
71
75
  await fs.writeFile(path.join(resources, 'app.bundle'), bundle.toBuffer())
72
76
 
73
- await fs.writeFile(path.join(app, 'AppxManifest.xml'), appxManifest(host, opts))
77
+ await fs.writeFile(path.join(app, 'AppxManifest.xml'), appxManifest(pkg, host, opts))
74
78
 
75
79
  if (icon) {
76
80
  const icons = path.join(app, 'Assets')
@@ -79,10 +83,30 @@ async function appx(base, bundle, host, opts = {}) {
79
83
  await fs.cp(path.resolve(icon), path.join(icons, name + path.extname(icon)))
80
84
  }
81
85
 
82
- return app
86
+ const appx = path.join(out, name + '.msix')
87
+
88
+ await fs.rm(appx)
89
+
90
+ await run('makeappx', ['pack', '/d', app, '/p', appx])
91
+
92
+ return appx
83
93
  }
84
94
 
85
- function appxManifest(host, opts = {}) {
95
+ // https://learn.microsoft.com/en-us/windows/msix/package/unsigned-package
96
+ const unsignedSubject = 'CN=AppModelSamples, OID.2.25.311729368913984317654407730594956997722=1'
97
+
98
+ function appxManifest(pkg, host, opts = {}) {
99
+ let {
100
+ name = pkg.name,
101
+ identifier = toIdentifier(name),
102
+ version = pkg.version,
103
+ description = pkg.description,
104
+ author = pkg.author,
105
+ language = 'en-US',
106
+ icon,
107
+ subject = unsignedSubject
108
+ } = opts
109
+
86
110
  let arch
87
111
 
88
112
  switch (host) {
@@ -94,17 +118,9 @@ function appxManifest(host, opts = {}) {
94
118
  break
95
119
  }
96
120
 
97
- const {
98
- name = 'App',
99
- identifier = name.replace(/[^a-z0-9.-]+/gi, ''),
100
- version = '1.0.0',
101
- description = '',
102
- author = '',
103
- language = 'en-US',
121
+ version = version.match(/^\d+(\.\d+){0,2}/).at(0)
104
122
 
105
- // https://learn.microsoft.com/en-us/windows/msix/package/unsigned-package
106
- publisher = 'CN=AppModelSamples, OID.2.25.311729368913984317654407730594956997722=1'
107
- } = opts
123
+ const logo = `Assets\\${name}${path.extname(icon)}`
108
124
 
109
125
  return `\
110
126
  <?xml version="1.0" encoding="utf-8"?>
@@ -117,66 +133,36 @@ function appxManifest(host, opts = {}) {
117
133
  xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
118
134
  IgnorableNamespaces="rescap desktop6 virtualization"
119
135
  >
120
- <Identity
121
- Name="${identifier}"
122
- Version="${version}.0"
123
- Publisher="${publisher}"
124
- ProcessorArchitecture="${arch}"
125
- />
136
+ <Identity Name="${identifier}" Version="${version}.0" Publisher="${subject}" ProcessorArchitecture="${arch}" />
126
137
  <Properties>
127
138
  <DisplayName>${name}</DisplayName>
128
139
  <PublisherDisplayName>${author}</PublisherDisplayName>
129
140
  <Description>${description}</Description>
130
- <Logo>Assets\\${name}.png</Logo>
131
-
141
+ <Logo>${logo}</Logo>
132
142
  <desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
133
143
  <desktop6:FileSystemWriteVirtualization>disabled</desktop6:FileSystemWriteVirtualization>
134
144
  </Properties>
135
-
136
145
  <Resources>
137
146
  <Resource Language="${language}" />
138
147
  </Resources>
139
-
140
148
  <Dependencies>
141
- <TargetDeviceFamily
142
- Name="Windows.Desktop"
143
- MinVersion="10.0.19045.0"
144
- MaxVersionTested="10.0.22621.0"
145
- />
146
- <PackageDependency
147
- Name="Microsoft.WindowsAppRuntime.1.4"
148
- MinVersion="4000.1049.117.0"
149
- Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
150
- />
151
- <PackageDependency
152
- Name="Microsoft.VCLibs.140.00"
153
- MinVersion="14.0.30704.0"
154
- Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
155
- />
149
+ <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19045.0" MaxVersionTested="10.0.22621.0" />
150
+ <PackageDependency Name="Microsoft.WindowsAppRuntime.1.4" MinVersion="4000.1049.117.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
151
+ <PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.30704.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
156
152
  </Dependencies>
157
-
158
153
  <Capabilities>
159
154
  <rescap:Capability Name="runFullTrust" />
160
155
  <rescap:Capability Name="unvirtualizedResources" />
161
156
  </Capabilities>
162
-
163
157
  <Applications>
164
- <Application
165
- Id="App"
166
- Executable="App\\${name}.exe"
167
- EntryPoint="Windows.FullTrustApplication"
168
- uap10:RuntimeBehavior="packagedClassicApp"
169
- uap10:TrustLevel="mediumIL"
170
- >
171
- <uap:VisualElements
172
- DisplayName="${name}"
173
- Description="${description}"
174
- Square150x150Logo="Assets\\${name}.png"
175
- Square44x44Logo="Assets\\${name}.png"
176
- BackgroundColor="transparent"
177
- />
158
+ <Application Id="App" Executable="App\\${name}.exe" EntryPoint="Windows.FullTrustApplication" uap10:RuntimeBehavior="packagedClassicApp" uap10:TrustLevel="mediumIL">
159
+ <uap:VisualElements DisplayName="${name}" Description="${description}" Square150x150Logo="${logo}" Square44x44Logo="${logo}" BackgroundColor="transparent" />
178
160
  </Application>
179
161
  </Applications>
180
162
  </Package>
181
163
  `
182
164
  }
165
+
166
+ function toIdentifier(input) {
167
+ return input.replace(/[^a-z0-9.-]+/gi, '')
168
+ }
package/lib/runtime.c CHANGED
@@ -81,6 +81,8 @@ main(int argc, char *argv[]) {
81
81
  err = path_join(
82
82
  #if defined(BARE_PLATFORM_DARWIN) || defined(BARE_PLATFORM_WIN32)
83
83
  (const char *[]) {bin, "..", "..", "Resources", "app.bundle", NULL},
84
+ #elif defined(BARE_PLATFORM_IOS)
85
+ (const char *[]) {bin, "..", "app.bundle", NULL},
84
86
  #elif defined(BARE_PLATFORM_LINUX)
85
87
  (const char *[]) {bin, "..", "..", "share", &bin[dir], "app.bundle", NULL},
86
88
  #endif
package/package.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "bare-build",
3
- "version": "0.0.0",
3
+ "version": "0.0.1",
4
4
  "description": "Application builder for Bare",
5
5
  "exports": {
6
6
  "./package": "./package.json",
7
7
  ".": "./index.js"
8
8
  },
9
9
  "imports": {
10
+ "#appimagetool": {
11
+ "linux": {
12
+ "arm64": "./prebuilds/linux-arm64/appimagetool.AppImage",
13
+ "x64": "./prebuilds/linux-x64/appimagetool.AppImage"
14
+ }
15
+ },
10
16
  "child_process": {
11
17
  "bare": "bare-subprocess",
12
18
  "default": "child_process"
@@ -15,6 +21,10 @@
15
21
  "bare": "bare-fs",
16
22
  "default": "fs"
17
23
  },
24
+ "os": {
25
+ "bare": "bare-os",
26
+ "default": "os"
27
+ },
18
28
  "path": {
19
29
  "bare": "bare-path",
20
30
  "default": "path"
@@ -52,6 +62,7 @@
52
62
  "bare-fs": "^4.5.1",
53
63
  "bare-link": "^1.5.5",
54
64
  "bare-module-traverse": "^1.8.1",
65
+ "bare-os": "^3.6.2",
55
66
  "bare-pack": "^1.5.1",
56
67
  "bare-path": "^3.0.0",
57
68
  "bare-subprocess": "^5.1.5",
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file