@atom-js-org/cli 0.3.0-alpha.0 → 0.4.0-alpha.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.
- package/package.json +1 -1
- package/src/build.cjs +50 -52
- package/src/utils.cjs +13 -3
package/package.json
CHANGED
package/src/build.cjs
CHANGED
|
@@ -39,8 +39,8 @@ async function localBuild(project, target, options = {}) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const buildRoot = path.join(project.root, 'build', target);
|
|
42
|
-
const unpacked = path.join(buildRoot, '
|
|
43
|
-
const appDir =
|
|
42
|
+
const unpacked = path.join(buildRoot, 'portable');
|
|
43
|
+
const appDir = null;
|
|
44
44
|
const productName = sanitizeFilename(project.config.productName);
|
|
45
45
|
|
|
46
46
|
console.log(`\nAtomJS build (${target})`);
|
|
@@ -50,7 +50,8 @@ async function localBuild(project, target, options = {}) {
|
|
|
50
50
|
await fse.remove(buildRoot);
|
|
51
51
|
await fse.ensureDir(unpacked);
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
const stageBase = await resolveShortStageBase();
|
|
54
|
+
const stageRoot = await fs.promises.mkdtemp(path.join(stageBase, 's-'));
|
|
54
55
|
const stagedApp = path.join(stageRoot, 'app');
|
|
55
56
|
const payloadPath = path.join(stageRoot, 'atom-app.payload.gz');
|
|
56
57
|
|
|
@@ -59,21 +60,8 @@ async function localBuild(project, target, options = {}) {
|
|
|
59
60
|
await vendorFramework(stagedApp, project, target);
|
|
60
61
|
await installProductionDependencies(stagedApp, options.skipInstall, target);
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
await createApplicationPayload(stagedApp, payloadPath);
|
|
65
|
-
} else {
|
|
66
|
-
await fse.move(stagedApp, appDir, { overwrite: true });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (target !== 'macos') {
|
|
70
|
-
const runtimeDir = path.join(unpacked, 'runtime');
|
|
71
|
-
await fse.ensureDir(runtimeDir);
|
|
72
|
-
const runtimeNodeName = target === 'windows' ? 'node.exe' : 'node';
|
|
73
|
-
const runtimeNodePath = path.join(runtimeDir, runtimeNodeName);
|
|
74
|
-
await fs.promises.copyFile(process.execPath, runtimeNodePath);
|
|
75
|
-
if (target !== 'windows') await fs.promises.chmod(runtimeNodePath, 0o755);
|
|
76
|
-
}
|
|
63
|
+
console.log('Embedding application code and production dependencies into the executable...');
|
|
64
|
+
await createApplicationPayload(stagedApp, payloadPath);
|
|
77
65
|
|
|
78
66
|
const executableName = target === 'windows' ? `${productName}.exe` : productName;
|
|
79
67
|
const executablePath = path.join(unpacked, executableName);
|
|
@@ -82,7 +70,7 @@ async function localBuild(project, target, options = {}) {
|
|
|
82
70
|
appDir,
|
|
83
71
|
target,
|
|
84
72
|
productName,
|
|
85
|
-
payloadPath
|
|
73
|
+
payloadPath
|
|
86
74
|
});
|
|
87
75
|
|
|
88
76
|
const creditPath = path.join(unpacked, 'ATOMJS-CREDIT.txt');
|
|
@@ -138,6 +126,28 @@ async function localBuild(project, target, options = {}) {
|
|
|
138
126
|
}
|
|
139
127
|
}
|
|
140
128
|
|
|
129
|
+
|
|
130
|
+
async function resolveShortStageBase() {
|
|
131
|
+
const configured = process.env.ATOMJS_TEMP_DIR || process.env.ATOM_TEMP_DIR;
|
|
132
|
+
const candidates = configured
|
|
133
|
+
? [path.resolve(configured)]
|
|
134
|
+
: process.platform === 'win32'
|
|
135
|
+
? [path.join(path.parse(process.cwd()).root, '.atomjs-tmp'), path.join(os.tmpdir(), 'atomjs')]
|
|
136
|
+
: [path.join(os.tmpdir(), 'atomjs')];
|
|
137
|
+
|
|
138
|
+
let lastError;
|
|
139
|
+
for (const candidate of candidates) {
|
|
140
|
+
try {
|
|
141
|
+
await fse.ensureDir(candidate);
|
|
142
|
+
await fs.promises.access(candidate, fs.constants.W_OK);
|
|
143
|
+
return candidate;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
lastError = error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`AtomJS could not create a writable short staging directory: ${lastError ? lastError.message : 'unknown error'}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
141
151
|
async function copyApplication(projectRoot, appDir) {
|
|
142
152
|
await fse.copy(projectRoot, appDir, {
|
|
143
153
|
dereference: false,
|
|
@@ -284,9 +294,8 @@ async function createSeaLauncher({ executablePath, appDir, target, productName,
|
|
|
284
294
|
const blobPath = path.join(work, target === 'windows' ? 'sea-prep.blob.exe' : 'sea-prep.blob');
|
|
285
295
|
const configPath = path.join(work, 'sea-config.json');
|
|
286
296
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
: createLooseLauncherSource();
|
|
297
|
+
if (!payloadPath) throw new Error('AtomJS SEA payload is required.');
|
|
298
|
+
const launcher = createEmbeddedLauncherSource(productName);
|
|
290
299
|
await fs.promises.writeFile(launcherPath, launcher, 'utf8');
|
|
291
300
|
|
|
292
301
|
const seaConfig = {
|
|
@@ -295,7 +304,7 @@ async function createSeaLauncher({ executablePath, appDir, target, productName,
|
|
|
295
304
|
disableExperimentalSEAWarning: true,
|
|
296
305
|
useSnapshot: false,
|
|
297
306
|
useCodeCache: false,
|
|
298
|
-
|
|
307
|
+
assets: { 'atom-app': payloadPath }
|
|
299
308
|
};
|
|
300
309
|
await fs.promises.writeFile(configPath, JSON.stringify(seaConfig, null, 2));
|
|
301
310
|
|
|
@@ -318,33 +327,6 @@ async function createSeaLauncher({ executablePath, appDir, target, productName,
|
|
|
318
327
|
await fse.remove(work);
|
|
319
328
|
}
|
|
320
329
|
|
|
321
|
-
function createLooseLauncherSource() {
|
|
322
|
-
return `
|
|
323
|
-
'use strict';
|
|
324
|
-
const path = require('node:path');
|
|
325
|
-
const fs = require('node:fs');
|
|
326
|
-
const { createRequire } = require('node:module');
|
|
327
|
-
|
|
328
|
-
const executableDir = path.dirname(process.execPath);
|
|
329
|
-
const appDir = path.join(executableDir, 'app');
|
|
330
|
-
const packagePath = path.join(appDir, 'package.json');
|
|
331
|
-
if (!fs.existsSync(packagePath)) {
|
|
332
|
-
console.error('AtomJS application files are missing:', appDir);
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const runtimeNode = path.join(executableDir, 'runtime', process.platform === 'win32' ? 'node.exe' : 'node');
|
|
337
|
-
process.chdir(appDir);
|
|
338
|
-
process.env.ATOM_PROJECT_ROOT = appDir;
|
|
339
|
-
process.env.ATOM_BUILD = '1';
|
|
340
|
-
process.env.ATOM_NODE_EXECUTABLE = runtimeNode;
|
|
341
|
-
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
342
|
-
const mainPath = path.resolve(appDir, pkg.main || 'main.js');
|
|
343
|
-
const load = createRequire(packagePath);
|
|
344
|
-
load(mainPath);
|
|
345
|
-
`;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
330
|
function createEmbeddedLauncherSource(productName) {
|
|
349
331
|
return `
|
|
350
332
|
'use strict';
|
|
@@ -354,6 +336,7 @@ const os = require('node:os');
|
|
|
354
336
|
const crypto = require('node:crypto');
|
|
355
337
|
const zlib = require('node:zlib');
|
|
356
338
|
const { createRequire } = require('node:module');
|
|
339
|
+
const { pathToFileURL } = require('node:url');
|
|
357
340
|
const { getAsset } = require('node:sea');
|
|
358
341
|
|
|
359
342
|
const productName = ${JSON.stringify(productName)};
|
|
@@ -397,7 +380,20 @@ const executableDir = path.dirname(process.execPath);
|
|
|
397
380
|
process.chdir(appDir);
|
|
398
381
|
process.env.ATOM_PROJECT_ROOT = appDir;
|
|
399
382
|
process.env.ATOM_BUILD = '1';
|
|
383
|
+
process.env.ATOM_EMBEDDED_RUNTIME = '1';
|
|
384
|
+
process.env.ATOM_WINDOW_HOST_ENTRY = path.join(appDir, 'vendor', 'atomjs', 'src', 'runtime', 'window-host.mjs');
|
|
400
385
|
process.env.ATOM_MACOS_HOST_EXECUTABLE = path.join(executableDir, 'AtomJSWindowHost');
|
|
386
|
+
const hostModeIndex = process.argv.indexOf('--atomjs-window-host');
|
|
387
|
+
if (hostModeIndex !== -1) {
|
|
388
|
+
const hostEntry = process.env.ATOM_WINDOW_HOST_ENTRY;
|
|
389
|
+
const configPath = process.argv[hostModeIndex + 1];
|
|
390
|
+
process.argv = [process.argv[0], hostEntry, configPath];
|
|
391
|
+
import(pathToFileURL(hostEntry).href).catch((error) => {
|
|
392
|
+
console.error(error && error.stack ? error.stack : error);
|
|
393
|
+
process.exit(1);
|
|
394
|
+
});
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
401
397
|
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
402
398
|
const mainPath = path.resolve(appDir, pkg.main || 'main.js');
|
|
403
399
|
const load = createRequire(packagePath);
|
|
@@ -419,11 +415,14 @@ async function packageWindows({ project, buildRoot, unpacked, executableName, pr
|
|
|
419
415
|
: '';
|
|
420
416
|
const script = `
|
|
421
417
|
Unicode true
|
|
418
|
+
SetCompressor /SOLID lzma
|
|
422
419
|
!include "MUI2.nsh"
|
|
423
420
|
Name "${escapeNsis(productName)}"
|
|
424
421
|
OutFile "${installerPath.replace(/\\/g, '\\\\')}"
|
|
425
422
|
InstallDir "$LOCALAPPDATA\\Programs\\${escapeNsis(productName)}"
|
|
426
423
|
RequestExecutionLevel user
|
|
424
|
+
ShowInstDetails show
|
|
425
|
+
ShowUninstDetails show
|
|
427
426
|
${credit}
|
|
428
427
|
!insertmacro MUI_PAGE_WELCOME
|
|
429
428
|
!insertmacro MUI_PAGE_DIRECTORY
|
|
@@ -441,6 +440,7 @@ SectionEnd
|
|
|
441
440
|
Section "Uninstall"
|
|
442
441
|
Delete "$DESKTOP\\${escapeNsis(productName)}.lnk"
|
|
443
442
|
RMDir /r "$SMPROGRAMS\\${escapeNsis(productName)}"
|
|
443
|
+
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${escapeNsis(project.config.appId)}"
|
|
444
444
|
RMDir /r "$INSTDIR"
|
|
445
445
|
SectionEnd
|
|
446
446
|
`;
|
|
@@ -555,8 +555,6 @@ async function packageLinux({ project, buildRoot, unpacked, executableName, prod
|
|
|
555
555
|
await fse.ensureDir(usrBin);
|
|
556
556
|
await fse.ensureDir(usrLibApp);
|
|
557
557
|
await fse.copy(path.join(unpacked, executableName), path.join(usrBin, productName));
|
|
558
|
-
await fse.copy(path.join(unpacked, 'app'), path.join(usrBin, 'app'));
|
|
559
|
-
await fse.copy(path.join(unpacked, 'runtime'), path.join(usrBin, 'runtime'));
|
|
560
558
|
await fse.copy(path.join(unpacked, 'ATOMJS-CREDIT.txt'), path.join(usrLibApp, 'ATOMJS-CREDIT.txt'));
|
|
561
559
|
|
|
562
560
|
const appRun = `#!/bin/sh\nHERE="$(dirname "$(readlink -f "$0")")"\nexec "$HERE/usr/bin/${productName}" "$@"\n`;
|
package/src/utils.cjs
CHANGED
|
@@ -54,9 +54,17 @@ function loadProject(projectInput) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
function normalizeSpawn(command, args) {
|
|
58
|
+
if (process.platform === 'win32' && /\.(?:cmd|bat)$/i.test(command)) {
|
|
59
|
+
return { command: process.env.ComSpec || 'cmd.exe', args: ['/d', '/s', '/c', command, ...args] };
|
|
60
|
+
}
|
|
61
|
+
return { command, args };
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
function run(command, args, options = {}) {
|
|
58
65
|
return new Promise((resolve, reject) => {
|
|
59
|
-
const
|
|
66
|
+
const normalized = normalizeSpawn(command, args);
|
|
67
|
+
const child = spawn(normalized.command, normalized.args, {
|
|
60
68
|
cwd: options.cwd || process.cwd(),
|
|
61
69
|
env: options.env || process.env,
|
|
62
70
|
stdio: options.stdio || 'inherit',
|
|
@@ -71,7 +79,8 @@ function run(command, args, options = {}) {
|
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
function capture(command, args, options = {}) {
|
|
74
|
-
const
|
|
82
|
+
const normalized = normalizeSpawn(command, args);
|
|
83
|
+
const result = spawnSync(normalized.command, normalized.args, {
|
|
75
84
|
cwd: options.cwd || process.cwd(),
|
|
76
85
|
env: options.env || process.env,
|
|
77
86
|
encoding: 'utf8',
|
|
@@ -86,7 +95,8 @@ function capture(command, args, options = {}) {
|
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
function commandExists(command, args = ['--version']) {
|
|
89
|
-
const
|
|
98
|
+
const normalized = normalizeSpawn(command, args);
|
|
99
|
+
const result = spawnSync(normalized.command, normalized.args, { stdio: 'ignore', shell: false });
|
|
90
100
|
return !result.error && result.status === 0;
|
|
91
101
|
}
|
|
92
102
|
|