@atom-js-org/cli 0.5.3-alpha.1 → 0.5.3-alpha.3
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/README.md +2 -2
- package/bin/atom.cjs +3 -3
- package/package.json +1 -1
- package/src/build.cjs +63 -9
- package/src/init.cjs +2 -7
- package/src/utils.cjs +2 -2
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@ atom run build
|
|
|
8
8
|
atom build windows
|
|
9
9
|
atom build macos
|
|
10
10
|
atom build linux
|
|
11
|
-
atom build
|
|
11
|
+
atom build current --local
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`atom.config.json` controls artifact names, Windows EXE/NSIS branding, macOS app/DMG metadata and Linux AppImage/DEB/RPM output. New projects include default PNG and ICO assets that can be replaced directly.
|
|
14
|
+
`atom.config.json` controls artifact names, Windows EXE/NSIS branding, macOS app/DMG metadata and Linux AppImage/DEB/RPM output. New projects include default PNG and ICO assets that can be replaced directly. Builds are local-first and do not require GitHub Actions; run the target build on the matching operating system.
|
|
15
15
|
|
|
16
16
|
Project: https://github.com/Atom-js-org/atom
|
package/bin/atom.cjs
CHANGED
|
@@ -25,10 +25,10 @@ program
|
|
|
25
25
|
program
|
|
26
26
|
.command('build')
|
|
27
27
|
.description('Build an AtomJS project')
|
|
28
|
-
.argument('<target>', 'windows, macos, linux, or all')
|
|
28
|
+
.argument('<target>', 'current, windows, macos, linux, or all')
|
|
29
29
|
.option('-p, --project <path>', 'project directory', process.cwd())
|
|
30
|
-
.option('--local', '
|
|
31
|
-
.option('--remote', '
|
|
30
|
+
.option('--local', 'build on this machine (default; kept for compatibility)')
|
|
31
|
+
.option('--remote', 'deprecated: remote GitHub Actions builds are disabled')
|
|
32
32
|
.option('--skip-install', 'reuse staged node_modules when possible')
|
|
33
33
|
.action(async (target, options) => buildCommand(target, options));
|
|
34
34
|
|
package/package.json
CHANGED
package/src/build.cjs
CHANGED
|
@@ -21,17 +21,33 @@ const { resolveElectronCompatibilityRoot } = require('./electron-compat.cjs');
|
|
|
21
21
|
const cliPackageVersion = require('../package.json').version;
|
|
22
22
|
|
|
23
23
|
async function buildCommand(targetInput, options = {}) {
|
|
24
|
-
const
|
|
24
|
+
const requestedTarget = validateTarget(targetInput);
|
|
25
25
|
const project = loadProject(options.project);
|
|
26
26
|
const host = hostTarget();
|
|
27
|
+
const target = requestedTarget === 'current' ? host : requestedTarget;
|
|
27
28
|
|
|
28
|
-
if (options.
|
|
29
|
-
throw new Error(
|
|
29
|
+
if (options.remote) {
|
|
30
|
+
throw new Error([
|
|
31
|
+
'Remote GitHub Actions builds are disabled.',
|
|
32
|
+
'Build locally on the matching operating system instead:',
|
|
33
|
+
' Windows: atom build windows --local',
|
|
34
|
+
' macOS: atom build macos --local',
|
|
35
|
+
' Linux: atom build linux --local'
|
|
36
|
+
].join('\n'));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (target === 'all') {
|
|
40
|
+
throw new Error([
|
|
41
|
+
"'atom build all' cannot safely cross-build native WebView applications.",
|
|
42
|
+
'Run the matching local build command once on each operating system.'
|
|
43
|
+
].join('\n'));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (target !== host) {
|
|
47
|
+
throw new Error(`Local target mismatch: this machine is ${host}, but '${target}' was requested. Build that target on a ${target} machine.`);
|
|
30
48
|
}
|
|
31
49
|
|
|
32
|
-
|
|
33
|
-
if (needsRemote) return remoteBuild(project, target);
|
|
34
|
-
return localBuild(project, host, options);
|
|
50
|
+
return localBuild(project, target, options);
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
async function localBuild(project, target, options = {}) {
|
|
@@ -61,8 +77,8 @@ async function localBuild(project, target, options = {}) {
|
|
|
61
77
|
await vendorFramework(stagedApp, project, target);
|
|
62
78
|
await installProductionDependencies(stagedApp, options.skipInstall, target);
|
|
63
79
|
|
|
64
|
-
console.log('Embedding application code and production dependencies into the executable...');
|
|
65
|
-
await createApplicationPayload(stagedApp, payloadPath);
|
|
80
|
+
console.log('Embedding application code, assets and production dependencies into the executable...');
|
|
81
|
+
const payloadSummary = await createApplicationPayload(stagedApp, payloadPath);
|
|
66
82
|
|
|
67
83
|
const executableName = target === 'windows' ? `${productName}.exe` : productName;
|
|
68
84
|
const executablePath = path.join(unpacked, executableName);
|
|
@@ -108,6 +124,15 @@ async function localBuild(project, target, options = {}) {
|
|
|
108
124
|
outputs = await packageLinux({ project, buildRoot, unpacked, executableName, productName });
|
|
109
125
|
}
|
|
110
126
|
|
|
127
|
+
const inventoryPath = path.join(buildRoot, 'packed-files.json');
|
|
128
|
+
await fs.promises.writeFile(inventoryPath, JSON.stringify({
|
|
129
|
+
format: 1,
|
|
130
|
+
fileCount: payloadSummary.fileCount,
|
|
131
|
+
sourceBytes: payloadSummary.sourceBytes,
|
|
132
|
+
compressedBytes: payloadSummary.compressedBytes,
|
|
133
|
+
files: payloadSummary.paths
|
|
134
|
+
}, null, 2));
|
|
135
|
+
|
|
111
136
|
const manifest = {
|
|
112
137
|
atomjsVersion: cliPackageVersion,
|
|
113
138
|
target,
|
|
@@ -116,6 +141,12 @@ async function localBuild(project, target, options = {}) {
|
|
|
116
141
|
createdAt: new Date().toISOString(),
|
|
117
142
|
run: path.relative(buildRoot, runPath),
|
|
118
143
|
unpacked: path.relative(buildRoot, unpackedPath),
|
|
144
|
+
payload: {
|
|
145
|
+
fileCount: payloadSummary.fileCount,
|
|
146
|
+
sourceBytes: payloadSummary.sourceBytes,
|
|
147
|
+
compressedBytes: payloadSummary.compressedBytes,
|
|
148
|
+
inventory: path.basename(inventoryPath)
|
|
149
|
+
},
|
|
119
150
|
outputs: outputs.map((file) => path.relative(buildRoot, file))
|
|
120
151
|
};
|
|
121
152
|
await fs.promises.writeFile(path.join(buildRoot, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
@@ -191,15 +222,18 @@ async function vendorFramework(appDir, project, target) {
|
|
|
191
222
|
};
|
|
192
223
|
if (target === 'windows') {
|
|
193
224
|
pkg.dependencies['@webviewjs/webview'] = '0.4.0';
|
|
225
|
+
pkg.dependencies.koffi = '3.1.2';
|
|
194
226
|
delete pkg.dependencies['webview-nodejs'];
|
|
195
227
|
if (pkg.optionalDependencies) delete pkg.optionalDependencies['webview-nodejs'];
|
|
196
228
|
} else if (target === 'linux' && process.env.ATOM_SKIP_WEBVIEW_CHECK !== '1') {
|
|
197
229
|
pkg.dependencies['webview-nodejs'] = '0.5.0';
|
|
198
230
|
delete pkg.dependencies['@webviewjs/webview'];
|
|
231
|
+
delete pkg.dependencies.koffi;
|
|
199
232
|
if (pkg.optionalDependencies) delete pkg.optionalDependencies['webview-nodejs'];
|
|
200
233
|
} else {
|
|
201
234
|
delete pkg.dependencies['webview-nodejs'];
|
|
202
235
|
delete pkg.dependencies['@webviewjs/webview'];
|
|
236
|
+
delete pkg.dependencies.koffi;
|
|
203
237
|
if (pkg.optionalDependencies) delete pkg.optionalDependencies['webview-nodejs'];
|
|
204
238
|
}
|
|
205
239
|
pkg.overrides = { ...(pkg.overrides || {}), tar: '7.5.20' };
|
|
@@ -241,6 +275,15 @@ async function installProductionDependencies(appDir, skipInstall, target) {
|
|
|
241
275
|
if (!fs.existsSync(bindingPath)) {
|
|
242
276
|
throw new Error('@webviewjs/webview was not installed. Remove node_modules and package-lock.json, then retry the build.');
|
|
243
277
|
}
|
|
278
|
+
const nativeDragPath = path.join(appDir, 'node_modules', 'koffi');
|
|
279
|
+
if (!fs.existsSync(nativeDragPath)) {
|
|
280
|
+
throw new Error('koffi was not installed. AtomJS requires its prebuilt Win32 FFI package for native window movement.');
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
await run(process.execPath, ['-e', "require('koffi');"], { cwd: appDir });
|
|
284
|
+
} catch (error) {
|
|
285
|
+
throw new Error(`The prebuilt Koffi package could not load for this Windows architecture: ${error.message}`);
|
|
286
|
+
}
|
|
244
287
|
} else if (target === 'linux') {
|
|
245
288
|
const bindingPath = path.join(appDir, 'node_modules', 'webview-nodejs');
|
|
246
289
|
if (!fs.existsSync(bindingPath) && process.env.ATOM_SKIP_WEBVIEW_CHECK !== '1') {
|
|
@@ -251,12 +294,15 @@ async function installProductionDependencies(appDir, skipInstall, target) {
|
|
|
251
294
|
|
|
252
295
|
async function createApplicationPayload(appDir, outputPath) {
|
|
253
296
|
const files = [];
|
|
297
|
+
let sourceBytes = 0;
|
|
254
298
|
|
|
255
299
|
async function addFile(source, relative, stat) {
|
|
300
|
+
const data = await fs.promises.readFile(source);
|
|
301
|
+
sourceBytes += data.length;
|
|
256
302
|
files.push({
|
|
257
303
|
path: relative.split(path.sep).join('/'),
|
|
258
304
|
mode: stat.mode & 0o777,
|
|
259
|
-
data:
|
|
305
|
+
data: data.toString('base64')
|
|
260
306
|
});
|
|
261
307
|
}
|
|
262
308
|
|
|
@@ -300,6 +346,12 @@ async function createApplicationPayload(appDir, outputPath) {
|
|
|
300
346
|
const payload = Buffer.from(JSON.stringify({ format: 1, files }));
|
|
301
347
|
const compressed = require('node:zlib').gzipSync(payload, { level: 9 });
|
|
302
348
|
await fs.promises.writeFile(outputPath, compressed);
|
|
349
|
+
return {
|
|
350
|
+
fileCount: files.length,
|
|
351
|
+
sourceBytes,
|
|
352
|
+
compressedBytes: compressed.length,
|
|
353
|
+
paths: files.map((entry) => entry.path)
|
|
354
|
+
};
|
|
303
355
|
}
|
|
304
356
|
|
|
305
357
|
async function createSeaLauncher({ executablePath, appDir, target, productName, appId, project = null, payloadPath = null }) {
|
|
@@ -955,6 +1007,8 @@ async function packageMacOS({ project, buildRoot, unpacked, executableName, prod
|
|
|
955
1007
|
<key>CFBundleName</key><string>${xml(bundleName)}</string>
|
|
956
1008
|
<key>CFBundleDisplayName</key><string>${xml(productName)}</string>
|
|
957
1009
|
<key>CFBundlePackageType</key><string>APPL</string>
|
|
1010
|
+
<key>LSUIElement</key><true/>
|
|
1011
|
+
<key>LSMultipleInstancesProhibited</key><true/>
|
|
958
1012
|
<key>CFBundleShortVersionString</key><string>${xml(version)}</string>
|
|
959
1013
|
<key>CFBundleVersion</key><string>${xml(bundleVersion)}</string>
|
|
960
1014
|
<key>LSMinimumSystemVersion</key><string>${xml(config.minimumSystemVersion)}</string>
|
package/src/init.cjs
CHANGED
|
@@ -17,7 +17,6 @@ async function initCommand(directory, options = {}) {
|
|
|
17
17
|
const productName = humanize(packageName);
|
|
18
18
|
|
|
19
19
|
await fse.ensureDir(path.join(root, 'src'));
|
|
20
|
-
await fse.ensureDir(path.join(root, '.github', 'workflows'));
|
|
21
20
|
|
|
22
21
|
await fs.promises.writeFile(path.join(root, 'package.json'), JSON.stringify({
|
|
23
22
|
name: packageName,
|
|
@@ -26,8 +25,8 @@ async function initCommand(directory, options = {}) {
|
|
|
26
25
|
main: 'src/main.js',
|
|
27
26
|
scripts: {
|
|
28
27
|
dev: 'atom run dev',
|
|
29
|
-
build: 'atom build
|
|
30
|
-
'build:current':
|
|
28
|
+
build: 'atom build current --local',
|
|
29
|
+
'build:current': 'atom build current --local',
|
|
31
30
|
start: 'atom run build'
|
|
32
31
|
},
|
|
33
32
|
dependencies: {
|
|
@@ -81,9 +80,6 @@ async function initCommand(directory, options = {}) {
|
|
|
81
80
|
deb: true,
|
|
82
81
|
rpm: true
|
|
83
82
|
}
|
|
84
|
-
},
|
|
85
|
-
github: {
|
|
86
|
-
workflow: 'atom-build.yml'
|
|
87
83
|
}
|
|
88
84
|
}, null, 2));
|
|
89
85
|
|
|
@@ -95,7 +91,6 @@ async function initCommand(directory, options = {}) {
|
|
|
95
91
|
await fs.promises.writeFile(path.join(root, 'src', 'index.html'), htmlTemplate(productName));
|
|
96
92
|
await fs.promises.writeFile(path.join(root, 'src', 'renderer.js'), rendererTemplate());
|
|
97
93
|
await fs.promises.writeFile(path.join(root, '.gitignore'), 'node_modules/\nbuild/\n.atom/\n');
|
|
98
|
-
await fs.promises.writeFile(path.join(root, '.github', 'workflows', 'atom-build.yml'), workflowTemplate());
|
|
99
94
|
|
|
100
95
|
console.log(`Created AtomJS project in ${root}`);
|
|
101
96
|
console.log('Next: npm install && npm run dev');
|
package/src/utils.cjs
CHANGED
|
@@ -4,7 +4,7 @@ const fs = require('node:fs');
|
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const { spawn, spawnSync } = require('node:child_process');
|
|
6
6
|
|
|
7
|
-
const TARGETS = new Set(['windows', 'macos', 'linux', 'all']);
|
|
7
|
+
const TARGETS = new Set(['current', 'windows', 'macos', 'linux', 'all']);
|
|
8
8
|
|
|
9
9
|
function hostTarget() {
|
|
10
10
|
if (process.platform === 'win32') return 'windows';
|
|
@@ -169,7 +169,7 @@ function commandExists(command, args = ['--version']) {
|
|
|
169
169
|
function validateTarget(target) {
|
|
170
170
|
const normalized = String(target).toLowerCase();
|
|
171
171
|
if (!TARGETS.has(normalized)) {
|
|
172
|
-
throw new Error(`Unknown build target '${target}'. Use windows, macos, linux, or all.`);
|
|
172
|
+
throw new Error(`Unknown build target '${target}'. Use current, windows, macos, linux, or all.`);
|
|
173
173
|
}
|
|
174
174
|
return normalized;
|
|
175
175
|
}
|