Skip to content

Commit c791fab

Browse files
feat: add ASAR packaging support and update tests
1 parent e8cd144 commit c791fab

File tree

5 files changed

+100
-10
lines changed

5 files changed

+100
-10
lines changed

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"test:ci": "jest --runInBand --coverage"
3535
},
3636
"dependencies": {
37+
"@electron/asar": "^3.3.1",
3738
"@electron/get": "^2.0.0",
3839
"debug": "^4.3.3",
3940
"env-paths": "^2.2.1",

Diff for: src/fiddle.ts

+41-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as fs from 'fs-extra';
22
import * as path from 'path';
3+
import * as asar from '@electron/asar';
34
import debug from 'debug';
45
import simpleGit from 'simple-git';
56
import { createHash } from 'crypto';
@@ -95,16 +96,48 @@ export class FiddleFactory {
9596
return new Fiddle(path.join(folder, 'main.js'), 'entries');
9697
}
9798

98-
public async create(src: FiddleSource): Promise<Fiddle | undefined> {
99-
if (src instanceof Fiddle) return src;
99+
public async create(
100+
src: FiddleSource,
101+
options?: { packAsAsar?: boolean },
102+
): Promise<Fiddle | undefined> {
103+
let fiddle: Fiddle;
104+
if (src instanceof Fiddle) {
105+
fiddle = src;
106+
} else if (typeof src === 'string') {
107+
if (fs.existsSync(src)) {
108+
fiddle = await this.fromFolder(src);
109+
} else if (/^[0-9A-Fa-f]{32}$/.test(src)) {
110+
fiddle = await this.fromGist(src);
111+
} else if (/^https:/.test(src) || /\.git$/.test(src)) {
112+
fiddle = await this.fromRepo(src);
113+
} else {
114+
return;
115+
}
116+
} else {
117+
fiddle = await this.fromEntries(src as Iterable<[string, string]>);
118+
}
100119

101-
if (typeof src === 'string') {
102-
if (fs.existsSync(src)) return this.fromFolder(src);
103-
if (/^[0-9A-Fa-f]{32}$/.test(src)) return this.fromGist(src);
104-
if (/^https:/.test(src) || /\.git$/.test(src)) return this.fromRepo(src);
105-
return;
120+
const { packAsAsar } = options || {};
121+
if (packAsAsar) {
122+
fiddle = await this.packageFiddleAsAsar(fiddle);
106123
}
124+
return fiddle;
125+
}
126+
127+
private async packageFiddleAsAsar(fiddle: Fiddle): Promise<Fiddle> {
128+
const mainJsPath = fiddle.mainPath;
129+
const sourceDir = path.dirname(mainJsPath);
130+
const asarOutputDir = path.join(this.fiddles, hashString(sourceDir));
131+
const asarFilePath = path.join(asarOutputDir, 'app.asar');
107132

108-
return this.fromEntries(src);
133+
await asar.createPackage(sourceDir, asarFilePath);
134+
fiddle = new Fiddle(asarFilePath, fiddle.source);
135+
136+
try {
137+
await fs.remove(sourceDir);
138+
} catch (err) {
139+
console.log('Error deleting unpacked folder:', err);
140+
}
141+
return fiddle;
109142
}
110143
}

Diff for: src/runner.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ export class Runner {
142142
// process the input parameters
143143
opts = { ...DefaultRunnerOpts, ...opts };
144144
const version = versionIn instanceof SemVer ? versionIn.version : versionIn;
145-
const fiddle = await this.fiddleFactory.create(fiddleIn);
145+
const isRunFromAsar = opts.args?.includes('runFromAsar');
146+
const fiddle = await this.fiddleFactory.create(fiddleIn, {
147+
packAsAsar: isRunFromAsar,
148+
});
146149
if (!fiddle) throw new Error(`Invalid fiddle: "${inspect(fiddleIn)}"`);
147150

148151
// set up the electron binary and the fiddle

Diff for: tests/fiddle.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as fs from 'fs-extra';
22
import * as os from 'os';
33
import * as path from 'path';
4+
import asar from '@electron/asar';
45

56
import { Fiddle, FiddleFactory } from '../src/index';
67

@@ -35,6 +36,9 @@ describe('FiddleFactory', () => {
3536
const dirname = path.dirname(fiddle!.mainPath);
3637
expect(dirname).not.toEqual(sourceDir);
3738

39+
// test that main.js file is created (not app.asar)
40+
expect(path.basename(fiddle!.mainPath)).toBe('main.js');
41+
3842
// test that the fiddle is kept in the fiddle cache
3943
expect(path.dirname(dirname)).toBe(fiddleDir);
4044

@@ -93,6 +97,41 @@ describe('FiddleFactory', () => {
9397
expect(fiddle).toBe(fiddleIn);
9498
});
9599

100+
it('packages fiddle into ASAR archive', async () => {
101+
const sourceDir = fiddleFixture('642fa8daaebea6044c9079e3f8a46390');
102+
const fiddle = await fiddleFactory.create(sourceDir, {
103+
packAsAsar: true,
104+
});
105+
106+
function normalizeAsarFiles(files: string[]): string[] {
107+
return files.map(
108+
(f) => f.replace(/^\//, ''), // Remove leading slash
109+
);
110+
}
111+
112+
// test that app.asar file is created
113+
expect(fiddle).toBeTruthy();
114+
expect(path.basename(fiddle!.mainPath)).toBe('app.asar');
115+
116+
// test that the file list is identical
117+
const dirname: string = fiddle!.mainPath;
118+
const sourceFiles = fs.readdirSync(sourceDir);
119+
const asarFiles = normalizeAsarFiles(
120+
asar.listPackage(dirname, { isPack: false }),
121+
);
122+
expect(asarFiles).toStrictEqual(sourceFiles);
123+
124+
// test that the files' contents are identical
125+
for (const file of sourceFiles) {
126+
const sourceFileContent = fs.readFileSync(
127+
path.join(sourceDir, file),
128+
'utf-8',
129+
);
130+
const asarFileContent = asar.extractFile(dirname, file).toString();
131+
expect(asarFileContent).toStrictEqual(sourceFileContent);
132+
}
133+
});
134+
96135
it.todo('reads fiddles from git repositories');
97136
it.todo('refreshes the cache if given a previously-cached git repository');
98137

Diff for: yarn.lock

+15-1
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,15 @@
575575
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
576576
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
577577

578+
"@electron/asar@^3.3.1":
579+
version "3.3.1"
580+
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea"
581+
integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg==
582+
dependencies:
583+
commander "^5.0.0"
584+
glob "^7.1.6"
585+
minimatch "^3.0.4"
586+
578587
"@electron/get@^2.0.0":
579588
version "2.0.0"
580589
resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91"
@@ -1733,6 +1742,11 @@ commander@^2.7.1:
17331742
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
17341743
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
17351744

1745+
commander@^5.0.0:
1746+
version "5.1.0"
1747+
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
1748+
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
1749+
17361750
compress-brotli@^1.3.8:
17371751
version "1.3.8"
17381752
resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db"
@@ -2362,7 +2376,7 @@ glob-parent@^6.0.2:
23622376
dependencies:
23632377
is-glob "^4.0.3"
23642378

2365-
glob@^7.1.3:
2379+
glob@^7.1.3, glob@^7.1.6:
23662380
version "7.2.3"
23672381
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
23682382
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==

0 commit comments

Comments
 (0)