@atom-js-org/cli 0.2.0-alpha.0 → 0.3.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 +275 -82
- package/src/doctor.cjs +4 -3
- package/src/init.cjs +3 -3
- package/src/run.cjs +3 -1
package/package.json
CHANGED
package/src/build.cjs
CHANGED
|
@@ -52,54 +52,90 @@ async function localBuild(project, target, options = {}) {
|
|
|
52
52
|
|
|
53
53
|
const stageRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'atomjs-stage-'));
|
|
54
54
|
const stagedApp = path.join(stageRoot, 'app');
|
|
55
|
+
const payloadPath = path.join(stageRoot, 'atom-app.payload.gz');
|
|
56
|
+
|
|
55
57
|
try {
|
|
56
58
|
await copyApplication(project.root, stagedApp);
|
|
57
59
|
await vendorFramework(stagedApp, project, target);
|
|
58
60
|
await installProductionDependencies(stagedApp, options.skipInstall, target);
|
|
59
|
-
await fse.move(stagedApp, appDir, { overwrite: true });
|
|
60
|
-
} finally {
|
|
61
|
-
await fse.remove(stageRoot);
|
|
62
|
-
}
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
if (target === 'macos') {
|
|
63
|
+
console.log('Embedding application code and production dependencies into the native executable...');
|
|
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
|
+
}
|
|
70
77
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
const executableName = target === 'windows' ? `${productName}.exe` : productName;
|
|
79
|
+
const executablePath = path.join(unpacked, executableName);
|
|
80
|
+
await createSeaLauncher({
|
|
81
|
+
executablePath,
|
|
82
|
+
appDir,
|
|
83
|
+
target,
|
|
84
|
+
productName,
|
|
85
|
+
payloadPath: target === 'macos' ? payloadPath : null
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const creditPath = path.join(unpacked, 'ATOMJS-CREDIT.txt');
|
|
89
|
+
await fs.promises.writeFile(
|
|
90
|
+
creditPath,
|
|
91
|
+
'Built with AtomJS\nhttps://github.com/Atom-js-org/atom\nCredit is optional inside applications.\n',
|
|
92
|
+
'utf8'
|
|
93
|
+
);
|
|
74
94
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
'Built with AtomJS\nhttps://github.com/Atom-js-org/atom\nCredit is optional inside applications.\n',
|
|
79
|
-
'utf8'
|
|
80
|
-
);
|
|
95
|
+
let outputs = [];
|
|
96
|
+
let runPath = executablePath;
|
|
97
|
+
let unpackedPath = unpacked;
|
|
81
98
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
if (target === 'windows') {
|
|
100
|
+
outputs = await packageWindows({ project, buildRoot, unpacked, executableName, productName });
|
|
101
|
+
}
|
|
102
|
+
if (target === 'macos') {
|
|
103
|
+
const packaged = await packageMacOS({
|
|
104
|
+
project,
|
|
105
|
+
buildRoot,
|
|
106
|
+
unpacked,
|
|
107
|
+
executableName,
|
|
108
|
+
productName,
|
|
109
|
+
hostSource: path.join(resolveFrameworkRoot(project.root), 'src', 'runtime', 'macos-native-host.m')
|
|
110
|
+
});
|
|
111
|
+
outputs = packaged.outputs;
|
|
112
|
+
runPath = packaged.appBundle;
|
|
113
|
+
unpackedPath = packaged.appBundle;
|
|
114
|
+
await fse.remove(unpacked);
|
|
115
|
+
}
|
|
116
|
+
if (target === 'linux') {
|
|
117
|
+
outputs = await packageLinux({ project, buildRoot, unpacked, executableName, productName });
|
|
118
|
+
}
|
|
98
119
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
const manifest = {
|
|
121
|
+
atomjsVersion: '0.3.0-alpha.0',
|
|
122
|
+
target,
|
|
123
|
+
productName,
|
|
124
|
+
appId: project.config.appId,
|
|
125
|
+
createdAt: new Date().toISOString(),
|
|
126
|
+
run: path.relative(buildRoot, runPath),
|
|
127
|
+
unpacked: path.relative(buildRoot, unpackedPath),
|
|
128
|
+
outputs: outputs.map((file) => path.relative(buildRoot, file))
|
|
129
|
+
};
|
|
130
|
+
await fs.promises.writeFile(path.join(buildRoot, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
131
|
+
|
|
132
|
+
console.log('\nBuild complete:');
|
|
133
|
+
console.log(` ${path.relative(project.root, unpackedPath)}`);
|
|
134
|
+
for (const output of outputs) console.log(` ${path.relative(project.root, output)}`);
|
|
135
|
+
return manifest;
|
|
136
|
+
} finally {
|
|
137
|
+
await fse.remove(stageRoot);
|
|
138
|
+
}
|
|
103
139
|
}
|
|
104
140
|
|
|
105
141
|
async function copyApplication(projectRoot, appDir) {
|
|
@@ -188,43 +224,69 @@ async function installProductionDependencies(appDir, skipInstall, target) {
|
|
|
188
224
|
}
|
|
189
225
|
}
|
|
190
226
|
|
|
191
|
-
async function
|
|
192
|
-
const
|
|
193
|
-
await fse.ensureDir(work);
|
|
194
|
-
const launcherPath = path.join(work, 'launcher.cjs');
|
|
195
|
-
const blobPath = path.join(work, target === 'windows' ? 'sea-prep.blob.exe' : 'sea-prep.blob');
|
|
196
|
-
const configPath = path.join(work, 'sea-config.json');
|
|
227
|
+
async function createApplicationPayload(appDir, outputPath) {
|
|
228
|
+
const files = [];
|
|
197
229
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
230
|
+
async function addFile(source, relative, stat) {
|
|
231
|
+
files.push({
|
|
232
|
+
path: relative.split(path.sep).join('/'),
|
|
233
|
+
mode: stat.mode & 0o777,
|
|
234
|
+
data: (await fs.promises.readFile(source)).toString('base64')
|
|
235
|
+
});
|
|
236
|
+
}
|
|
203
237
|
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
238
|
+
async function visit(directory, relativePrefix = '', ancestors = new Set()) {
|
|
239
|
+
const realDirectory = await fs.promises.realpath(directory);
|
|
240
|
+
if (ancestors.has(realDirectory)) return;
|
|
241
|
+
const nextAncestors = new Set(ancestors);
|
|
242
|
+
nextAncestors.add(realDirectory);
|
|
243
|
+
|
|
244
|
+
const entries = await fs.promises.readdir(directory, { withFileTypes: true });
|
|
245
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
246
|
+
|
|
247
|
+
for (const entry of entries) {
|
|
248
|
+
const absolute = path.join(directory, entry.name);
|
|
249
|
+
const relative = relativePrefix ? path.join(relativePrefix, entry.name) : entry.name;
|
|
250
|
+
|
|
251
|
+
if (entry.isDirectory()) {
|
|
252
|
+
await visit(absolute, relative, nextAncestors);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (entry.isSymbolicLink()) {
|
|
257
|
+
const resolved = await fs.promises.realpath(absolute);
|
|
258
|
+
const stat = await fs.promises.stat(resolved);
|
|
259
|
+
if (stat.isDirectory()) {
|
|
260
|
+
await visit(resolved, relative, nextAncestors);
|
|
261
|
+
} else if (stat.isFile()) {
|
|
262
|
+
await addFile(resolved, relative, stat);
|
|
263
|
+
}
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (entry.isFile()) {
|
|
268
|
+
const stat = await fs.promises.stat(absolute);
|
|
269
|
+
await addFile(absolute, relative, stat);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
208
273
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
274
|
+
await visit(appDir);
|
|
275
|
+
const payload = Buffer.from(JSON.stringify({ format: 1, files }));
|
|
276
|
+
const compressed = require('node:zlib').gzipSync(payload, { level: 9 });
|
|
277
|
+
await fs.promises.writeFile(outputPath, compressed);
|
|
213
278
|
}
|
|
214
279
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
280
|
+
async function createSeaLauncher({ executablePath, appDir, target, productName, payloadPath = null }) {
|
|
281
|
+
const work = path.join(path.dirname(executablePath), '.sea-' + crypto.randomBytes(5).toString('hex'));
|
|
282
|
+
await fse.ensureDir(work);
|
|
283
|
+
const launcherPath = path.join(work, 'launcher.cjs');
|
|
284
|
+
const blobPath = path.join(work, target === 'windows' ? 'sea-prep.blob.exe' : 'sea-prep.blob');
|
|
285
|
+
const configPath = path.join(work, 'sea-config.json');
|
|
218
286
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
process.env.ATOM_NODE_EXECUTABLE = runtimeNode;
|
|
223
|
-
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
224
|
-
const mainPath = path.resolve(appDir, pkg.main || 'main.js');
|
|
225
|
-
const load = createRequire(packagePath);
|
|
226
|
-
load(mainPath);
|
|
227
|
-
`;
|
|
287
|
+
const launcher = payloadPath
|
|
288
|
+
? createEmbeddedLauncherSource(productName)
|
|
289
|
+
: createLooseLauncherSource();
|
|
228
290
|
await fs.promises.writeFile(launcherPath, launcher, 'utf8');
|
|
229
291
|
|
|
230
292
|
const seaConfig = {
|
|
@@ -232,7 +294,8 @@ load(mainPath);
|
|
|
232
294
|
output: blobPath,
|
|
233
295
|
disableExperimentalSEAWarning: true,
|
|
234
296
|
useSnapshot: false,
|
|
235
|
-
useCodeCache: false
|
|
297
|
+
useCodeCache: false,
|
|
298
|
+
...(payloadPath ? { assets: { 'atom-app': payloadPath } } : {})
|
|
236
299
|
};
|
|
237
300
|
await fs.promises.writeFile(configPath, JSON.stringify(seaConfig, null, 2));
|
|
238
301
|
|
|
@@ -250,11 +313,98 @@ load(mainPath);
|
|
|
250
313
|
|
|
251
314
|
if (target !== 'windows') await fs.promises.chmod(executablePath, 0o755);
|
|
252
315
|
if (target === 'macos' && commandExists('codesign', ['--version'])) {
|
|
253
|
-
await run('codesign', ['--sign', '-', executablePath]);
|
|
316
|
+
await run('codesign', ['--force', '--sign', '-', executablePath]);
|
|
254
317
|
}
|
|
255
318
|
await fse.remove(work);
|
|
256
319
|
}
|
|
257
320
|
|
|
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
|
+
function createEmbeddedLauncherSource(productName) {
|
|
349
|
+
return `
|
|
350
|
+
'use strict';
|
|
351
|
+
const path = require('node:path');
|
|
352
|
+
const fs = require('node:fs');
|
|
353
|
+
const os = require('node:os');
|
|
354
|
+
const crypto = require('node:crypto');
|
|
355
|
+
const zlib = require('node:zlib');
|
|
356
|
+
const { createRequire } = require('node:module');
|
|
357
|
+
const { getAsset } = require('node:sea');
|
|
358
|
+
|
|
359
|
+
const productName = ${JSON.stringify(productName)};
|
|
360
|
+
const payload = Buffer.from(getAsset('atom-app'));
|
|
361
|
+
const payloadHash = crypto.createHash('sha256').update(payload).digest('hex').slice(0, 24);
|
|
362
|
+
const dataRoot = process.platform === 'darwin'
|
|
363
|
+
? path.join(os.homedir(), 'Library', 'Application Support')
|
|
364
|
+
: process.platform === 'win32'
|
|
365
|
+
? (process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'))
|
|
366
|
+
: (process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share'));
|
|
367
|
+
const appDir = path.join(dataRoot, productName, 'AtomJS Runtime', payloadHash);
|
|
368
|
+
const marker = path.join(appDir, '.atom-ready');
|
|
369
|
+
|
|
370
|
+
if (!fs.existsSync(marker)) {
|
|
371
|
+
const temporary = appDir + '.tmp-' + process.pid;
|
|
372
|
+
fs.rmSync(temporary, { recursive: true, force: true });
|
|
373
|
+
fs.mkdirSync(temporary, { recursive: true });
|
|
374
|
+
const archive = JSON.parse(zlib.gunzipSync(payload).toString('utf8'));
|
|
375
|
+
if (!archive || archive.format !== 1 || !Array.isArray(archive.files)) {
|
|
376
|
+
throw new Error('AtomJS embedded application payload is invalid.');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
for (const entry of archive.files) {
|
|
380
|
+
const destination = path.resolve(temporary, String(entry.path));
|
|
381
|
+
const root = path.resolve(temporary) + path.sep;
|
|
382
|
+
if (!destination.startsWith(root)) throw new Error('Unsafe path in AtomJS application payload.');
|
|
383
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
384
|
+
fs.writeFileSync(destination, Buffer.from(entry.data, 'base64'));
|
|
385
|
+
if (process.platform !== 'win32' && Number.isInteger(entry.mode)) fs.chmodSync(destination, entry.mode);
|
|
386
|
+
}
|
|
387
|
+
fs.writeFileSync(path.join(temporary, '.atom-ready'), payloadHash);
|
|
388
|
+
fs.mkdirSync(path.dirname(appDir), { recursive: true });
|
|
389
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
390
|
+
fs.renameSync(temporary, appDir);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const packagePath = path.join(appDir, 'package.json');
|
|
394
|
+
if (!fs.existsSync(packagePath)) throw new Error('AtomJS could not materialize the embedded application.');
|
|
395
|
+
|
|
396
|
+
const executableDir = path.dirname(process.execPath);
|
|
397
|
+
process.chdir(appDir);
|
|
398
|
+
process.env.ATOM_PROJECT_ROOT = appDir;
|
|
399
|
+
process.env.ATOM_BUILD = '1';
|
|
400
|
+
process.env.ATOM_MACOS_HOST_EXECUTABLE = path.join(executableDir, 'AtomJSWindowHost');
|
|
401
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
402
|
+
const mainPath = path.resolve(appDir, pkg.main || 'main.js');
|
|
403
|
+
const load = createRequire(packagePath);
|
|
404
|
+
load(mainPath);
|
|
405
|
+
`;
|
|
406
|
+
}
|
|
407
|
+
|
|
258
408
|
async function packageWindows({ project, buildRoot, unpacked, executableName, productName }) {
|
|
259
409
|
const outputs = [];
|
|
260
410
|
const zipPath = path.join(buildRoot, `${productName}-windows.zip`);
|
|
@@ -305,19 +455,49 @@ SectionEnd
|
|
|
305
455
|
return outputs;
|
|
306
456
|
}
|
|
307
457
|
|
|
308
|
-
async function packageMacOS({ project, buildRoot, unpacked, executableName, productName }) {
|
|
458
|
+
async function packageMacOS({ project, buildRoot, unpacked, executableName, productName, hostSource }) {
|
|
309
459
|
const outputs = [];
|
|
310
460
|
const appBundle = path.join(buildRoot, `${productName}.app`);
|
|
311
461
|
const contents = path.join(appBundle, 'Contents');
|
|
312
462
|
const macosDir = path.join(contents, 'MacOS');
|
|
313
463
|
const resources = path.join(contents, 'Resources');
|
|
464
|
+
const mainExecutable = path.join(macosDir, productName);
|
|
465
|
+
const nativeHost = path.join(macosDir, 'AtomJSWindowHost');
|
|
466
|
+
|
|
314
467
|
await fse.ensureDir(macosDir);
|
|
315
468
|
await fse.ensureDir(resources);
|
|
316
|
-
await fse.copy(path.join(unpacked, executableName),
|
|
317
|
-
await fse.copy(path.join(unpacked, 'app'), path.join(resources, 'app'));
|
|
318
|
-
await fse.copy(path.join(unpacked, 'runtime'), path.join(resources, 'runtime'));
|
|
469
|
+
await fse.copy(path.join(unpacked, executableName), mainExecutable);
|
|
319
470
|
await fse.copy(path.join(unpacked, 'ATOMJS-CREDIT.txt'), path.join(resources, 'ATOMJS-CREDIT.txt'));
|
|
471
|
+
await fs.promises.chmod(mainExecutable, 0o755);
|
|
320
472
|
|
|
473
|
+
if (!fs.existsSync(hostSource)) {
|
|
474
|
+
throw new Error(`AtomJS macOS native host source was not found: ${hostSource}`);
|
|
475
|
+
}
|
|
476
|
+
if (!commandExists('/usr/bin/xcrun', ['--version'])) {
|
|
477
|
+
throw new Error('macOS builds require the Xcode Command Line Tools. Run `xcode-select --install`.');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
await run('/usr/bin/xcrun', [
|
|
481
|
+
'clang',
|
|
482
|
+
'-fobjc-arc',
|
|
483
|
+
'-fmodules',
|
|
484
|
+
'-mmacosx-version-min=12.0',
|
|
485
|
+
'-framework', 'Cocoa',
|
|
486
|
+
'-framework', 'WebKit',
|
|
487
|
+
hostSource,
|
|
488
|
+
'-o', nativeHost
|
|
489
|
+
]);
|
|
490
|
+
await fs.promises.chmod(nativeHost, 0o755);
|
|
491
|
+
|
|
492
|
+
let iconEntry = '';
|
|
493
|
+
const iconSource = project.config.icon ? path.resolve(project.root, project.config.icon) : null;
|
|
494
|
+
if (iconSource && fs.existsSync(iconSource) && path.extname(iconSource).toLowerCase() === '.icns') {
|
|
495
|
+
await fse.copy(iconSource, path.join(resources, 'AppIcon.icns'));
|
|
496
|
+
iconEntry = '<key>CFBundleIconFile</key><string>AppIcon</string>';
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
const version = String(project.packageJson.version || '0.0.0');
|
|
500
|
+
const bundleVersion = (version.match(/\d+/g) || ['1']).slice(0, 3).join('.');
|
|
321
501
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
322
502
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
323
503
|
<plist version="1.0"><dict>
|
|
@@ -326,13 +506,25 @@ async function packageMacOS({ project, buildRoot, unpacked, executableName, prod
|
|
|
326
506
|
<key>CFBundleName</key><string>${xml(productName)}</string>
|
|
327
507
|
<key>CFBundleDisplayName</key><string>${xml(productName)}</string>
|
|
328
508
|
<key>CFBundlePackageType</key><string>APPL</string>
|
|
329
|
-
<key>CFBundleShortVersionString</key><string>${xml(
|
|
509
|
+
<key>CFBundleShortVersionString</key><string>${xml(version)}</string>
|
|
510
|
+
<key>CFBundleVersion</key><string>${xml(bundleVersion)}</string>
|
|
511
|
+
<key>LSMinimumSystemVersion</key><string>12.0</string>
|
|
330
512
|
<key>NSHighResolutionCapable</key><true/>
|
|
513
|
+
${iconEntry}
|
|
331
514
|
</dict></plist>`;
|
|
332
|
-
|
|
333
|
-
await fs.promises.
|
|
515
|
+
const plistPath = path.join(contents, 'Info.plist');
|
|
516
|
+
await fs.promises.writeFile(plistPath, plist, 'utf8');
|
|
517
|
+
|
|
518
|
+
if (commandExists('/usr/bin/plutil', ['-help'])) {
|
|
519
|
+
await run('/usr/bin/plutil', ['-lint', plistPath]);
|
|
520
|
+
}
|
|
334
521
|
|
|
335
|
-
if (commandExists('codesign', ['--version']))
|
|
522
|
+
if (commandExists('/usr/bin/codesign', ['--version'])) {
|
|
523
|
+
await run('/usr/bin/codesign', ['--force', '--sign', '-', nativeHost]);
|
|
524
|
+
await run('/usr/bin/codesign', ['--force', '--sign', '-', mainExecutable]);
|
|
525
|
+
await run('/usr/bin/codesign', ['--force', '--deep', '--sign', '-', appBundle]);
|
|
526
|
+
await run('/usr/bin/codesign', ['--verify', '--deep', '--strict', appBundle]);
|
|
527
|
+
}
|
|
336
528
|
|
|
337
529
|
const zipPath = path.join(buildRoot, `${productName}-macos.zip`);
|
|
338
530
|
if (commandExists('ditto', ['-h'])) {
|
|
@@ -347,7 +539,8 @@ async function packageMacOS({ project, buildRoot, unpacked, executableName, prod
|
|
|
347
539
|
await run('hdiutil', ['create', '-volname', productName, '-srcfolder', appBundle, '-ov', '-format', 'UDZO', dmgPath]);
|
|
348
540
|
outputs.push(dmgPath);
|
|
349
541
|
}
|
|
350
|
-
|
|
542
|
+
|
|
543
|
+
return { outputs, appBundle };
|
|
351
544
|
}
|
|
352
545
|
|
|
353
546
|
async function packageLinux({ project, buildRoot, unpacked, executableName, productName }) {
|
|
@@ -502,4 +695,4 @@ function xml(value) {
|
|
|
502
695
|
return String(value).replace(/[<>&'\"]/g, (char) => ({ '<': '<', '>': '>', '&': '&', "'": ''', '"': '"' })[char]);
|
|
503
696
|
}
|
|
504
697
|
|
|
505
|
-
module.exports = { buildCommand, localBuild };
|
|
698
|
+
module.exports = { buildCommand, localBuild, createApplicationPayload };
|
package/src/doctor.cjs
CHANGED
|
@@ -15,9 +15,10 @@ async function doctorCommand(options = {}) {
|
|
|
15
15
|
rows.push(check('WebView2 Runtime', checkWindowsWebView2(), 'required by the native WebView'));
|
|
16
16
|
rows.push(check('NSIS (optional installer)', commandExists('makensis', ['/VERSION'])));
|
|
17
17
|
} else if (process.platform === 'darwin') {
|
|
18
|
-
rows.push(check('
|
|
18
|
+
rows.push(check('Xcode Command Line Tools', commandExists('/usr/bin/xcrun', ['--version']), 'required to compile the native Cocoa host'));
|
|
19
|
+
rows.push(check('Clang', commandExists('/usr/bin/xcrun', ['clang', '--version'])));
|
|
19
20
|
rows.push(check('WebKit framework', fs.existsSync('/System/Library/Frameworks/WebKit.framework')));
|
|
20
|
-
rows.push(check('codesign', commandExists('codesign', ['--version'])));
|
|
21
|
+
rows.push(check('codesign', commandExists('/usr/bin/codesign', ['--version'])));
|
|
21
22
|
rows.push(check('hdiutil', commandExists('hdiutil', ['help'])));
|
|
22
23
|
} else {
|
|
23
24
|
rows.push(check('pkg-config', commandExists('pkg-config', ['--version'])));
|
|
@@ -28,7 +29,7 @@ async function doctorCommand(options = {}) {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
if (process.platform === 'darwin') {
|
|
31
|
-
rows.push(check('macOS WKWebView backend', true, '
|
|
32
|
+
rows.push(check('macOS WKWebView backend', true, 'shared native Cocoa host; no osascript process'));
|
|
32
33
|
} else {
|
|
33
34
|
try {
|
|
34
35
|
const project = loadProject(options.project);
|
package/src/init.cjs
CHANGED
|
@@ -30,14 +30,14 @@ async function initCommand(directory, options = {}) {
|
|
|
30
30
|
start: 'atom run build'
|
|
31
31
|
},
|
|
32
32
|
dependencies: {
|
|
33
|
-
'@atom-js-org/runtime': '0.
|
|
34
|
-
electron: 'npm:@atom-js-org/electron@0.
|
|
33
|
+
'@atom-js-org/runtime': '0.3.0-alpha.0',
|
|
34
|
+
electron: 'npm:@atom-js-org/electron@0.3.0-alpha.0'
|
|
35
35
|
},
|
|
36
36
|
optionalDependencies: {
|
|
37
37
|
'webview-nodejs': '0.5.0'
|
|
38
38
|
},
|
|
39
39
|
devDependencies: {
|
|
40
|
-
'@atom-js-org/cli': '0.
|
|
40
|
+
'@atom-js-org/cli': '0.3.0-alpha.0'
|
|
41
41
|
},
|
|
42
42
|
overrides: {
|
|
43
43
|
tar: '7.5.20'
|
package/src/run.cjs
CHANGED
|
@@ -54,7 +54,9 @@ async function runBuild(options) {
|
|
|
54
54
|
if (!fs.existsSync(executable)) throw new Error(`Built executable not found: ${executable}`);
|
|
55
55
|
|
|
56
56
|
console.log(`Running ${path.basename(executable)}`);
|
|
57
|
-
const
|
|
57
|
+
const command = target === 'macos' && executable.endsWith('.app') ? 'open' : executable;
|
|
58
|
+
const args = command === 'open' ? ['-W', executable] : [];
|
|
59
|
+
const child = spawn(command, args, {
|
|
58
60
|
cwd: path.dirname(executable),
|
|
59
61
|
stdio: 'inherit'
|
|
60
62
|
});
|