Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
- '18.20'
os:
- macos-latest
- ubuntu-latest
- windows-latest
runs-on: '${{ matrix.os }}'
steps:
Expand Down
6 changes: 0 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,9 @@
"publishConfig": {
"provenance": true
},
"dependencies": {
"github-url-to-object": "^4.0.4",
"ms": "^2.1.1"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@types/github-url-to-object": "^4.0.1",
"@types/jest": "^29.5.14",
"@types/ms": "^0.7.31",
"@types/node": "^22.10.1",
"electron": "^35.7.5",
"eslint": "^9.15.0",
Expand Down
35 changes: 19 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import ms from 'ms';
import gh from 'github-url-to-object';

import assert from 'node:assert';
import fs from 'node:fs';
import os from 'node:os';
Expand Down Expand Up @@ -91,10 +88,11 @@ export interface IUpdateElectronAppOptions<L = ILogger> {
readonly host?: string;
readonly updateSource?: IUpdateSource;
/**
* @param {String} updateInterval How frequently to check for updates. Defaults to `10 minutes`.
* Minimum allowed interval is `5 minutes`.
* @param {Number} updateInterval How frequently to check for updates, in milliseconds.
* Defaults to `600000` (10 minutes).
* Minimum allowed interval is `300000` (5 minutes).
*/
readonly updateInterval?: string;
readonly updateInterval?: number;
/**
* @param {Object} logger A custom logger object that defines a `log` function.
* Defaults to `console`. See electron-log, a module
Expand Down Expand Up @@ -245,7 +243,7 @@ function initUpdater(opts: ReturnType<typeof validateInput>) {
autoUpdater.checkForUpdates();
setInterval(() => {
autoUpdater.checkForUpdates();
}, ms(updateInterval));
}, updateInterval);
}

/**
Expand Down Expand Up @@ -286,16 +284,21 @@ export function makeUserNotifier(dialogProps?: IUpdateDialogStrings): (info: IUp
function guessRepo() {
const pkgBuf = fs.readFileSync(path.join(app.getAppPath(), 'package.json'));
const pkg = JSON.parse(pkgBuf.toString());
const repoString = pkg.repository?.url || pkg.repository;
const repoObject = gh(repoString);
assert(repoObject, "repo not found. Add repository string to your app's package.json file");
return `${repoObject.user}/${repoObject.repo}`;
const repoString: string = pkg.repository?.url || pkg.repository;
assert(repoString, "repo not found. Add repository string to your app's package.json file");

// Matches owner/repo from GitHub URLs, git@ SSH URLs, or shorthand notation
const match = repoString.match(
/(?:github\.com[/:]|^github:|^)([\w-]+)\/([\w-.]+?)(?:\.git)?(?:[/#]|$)/,
);
assert(match, "repo not found. Add repository string to your app's package.json file");
return `${match[1]}/${match[2]}`;
}

function validateInput(opts: IUpdateElectronAppOptions) {
const defaults = {
host: 'https://update.electronjs.org',
updateInterval: '10 minutes',
updateInterval: 10 * 60 * 1000,
logger: console,
notifyUser: true,
};
Expand Down Expand Up @@ -340,12 +343,12 @@ function validateInput(opts: IUpdateElectronAppOptions) {
}

assert(
typeof updateInterval === 'string' && updateInterval.match(/^\d+/),
'updateInterval must be a human-friendly string interval like `20 minutes`',
typeof updateInterval === 'number' && updateInterval > 0,
'updateInterval must be a positive number of milliseconds',
);

assert(ms(updateInterval) >= 5 * 60 * 1000, 'updateInterval must be `5 minutes` or more');
assert(ms(updateInterval) < 2 ** 31, 'updateInterval must fit in a signed 32-bit integer');
assert(updateInterval >= 5 * 60 * 1000, 'updateInterval must be `5 minutes` or more');
assert(updateInterval < 2 ** 31, 'updateInterval must fit in a signed 32-bit integer');

assert(logger && typeof logger.log, 'function');

Expand Down
30 changes: 29 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,34 @@ describe('updateElectronApp', () => {
updateElectronApp();
});

it.each([
['owner/repo', 'owner/repo'],
['https://github.com/owner/repo', 'owner/repo'],
['https://github.com/owner/repo.git', 'owner/repo'],
['git+https://github.com/owner/repo.git', 'owner/repo'],
['git@github.com:owner/repo.git', 'owner/repo'],
['github:owner/repo', 'owner/repo'],
['https://github.com/owner/my-repo.js', 'owner/my-repo.js'],
['https://github.com/owner/my_repo', 'owner/my_repo'],
])('parses repo from %s', (repository, expected) => {
fs.writeFileSync(packageJson, JSON.stringify({ repository }));
const logSpy = jest.spyOn(console, 'log').mockImplementation();
updateElectronApp();
expect(logSpy).toHaveBeenCalledWith('feedURL', expect.stringContaining(`/${expected}/`));
logSpy.mockRestore();
});

it.each([['https://github.com/owner/repo'], ['https://github.com/owner/repo.git']])(
'parses repo from repository.url: %s',
(url) => {
fs.writeFileSync(packageJson, JSON.stringify({ repository: { url } }));
const logSpy = jest.spyOn(console, 'log').mockImplementation();
updateElectronApp();
expect(logSpy).toHaveBeenCalledWith('feedURL', expect.stringContaining('/owner/repo/'));
logSpy.mockRestore();
},
);

afterAll(() => {
fs.rmSync(packageJson);
});
Expand All @@ -69,7 +97,7 @@ describe('updateElectronApp', () => {
describe('updateInterval', () => {
it('must be 5 minutes or more', () => {
expect(() => {
updateElectronApp({ repo, updateInterval: '20 seconds' });
updateElectronApp({ repo, updateInterval: 20_000 });
}).toThrow('updateInterval must be `5 minutes` or more');
});
});
Expand Down
36 changes: 1 addition & 35 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1238,13 +1238,6 @@ __metadata:
languageName: node
linkType: hard

"@types/github-url-to-object@npm:^4.0.1":
version: 4.0.1
resolution: "@types/github-url-to-object@npm:4.0.1"
checksum: 10c0/ee883cae1fac4594e6809e2c4220ce9d28103fcdc93176183e074b40e68dba4f265a95af738bd161fd7457926a173d5604dcf8398c7bdaa3ae663f2b38710fc0
languageName: node
linkType: hard

"@types/graceful-fs@npm:^4.1.3":
version: 4.1.5
resolution: "@types/graceful-fs@npm:4.1.5"
Expand Down Expand Up @@ -1312,13 +1305,6 @@ __metadata:
languageName: node
linkType: hard

"@types/ms@npm:^0.7.31":
version: 0.7.31
resolution: "@types/ms@npm:0.7.31"
checksum: 10c0/19fae4f587651e8761c76a0c72ba8af1700d37054476878d164b758edcc926f4420ed06037a1a7fdddc1dbea25265895d743c8b2ea44f3f3f7ac06c449b9221e
languageName: node
linkType: hard

"@types/node@npm:*, @types/node@npm:^22.10.1, @types/node@npm:^22.7.7":
version: 22.18.0
resolution: "@types/node@npm:22.18.0"
Expand Down Expand Up @@ -2805,15 +2791,6 @@ __metadata:
languageName: node
linkType: hard

"github-url-to-object@npm:^4.0.4":
version: 4.0.4
resolution: "github-url-to-object@npm:4.0.4"
dependencies:
is-url: "npm:^1.1.0"
checksum: 10c0/1987e52dbc75e5d34dbf8e19104640d375b0dbf91e205aee95302256fe9c0ff4615e3b9ce3b6e7439bb1feb0463fd7605e5303b45f1c0e8c5faf2e5e5dab1393
languageName: node
linkType: hard

"glob-parent@npm:^5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
Expand Down Expand Up @@ -3190,13 +3167,6 @@ __metadata:
languageName: node
linkType: hard

"is-url@npm:^1.1.0":
version: 1.2.4
resolution: "is-url@npm:1.2.4"
checksum: 10c0/0157a79874f8f95fdd63540e3f38c8583c2ef572661cd0693cda80ae3e42dfe8e9a4a972ec1b827f861d9a9acf75b37f7d58a37f94a8a053259642912c252bc3
languageName: node
linkType: hard

"isexe@npm:^2.0.0":
version: 2.0.0
resolution: "isexe@npm:2.0.0"
Expand Down Expand Up @@ -4235,7 +4205,7 @@ __metadata:
languageName: node
linkType: hard

"ms@npm:2.1.2, ms@npm:^2.1.1":
"ms@npm:2.1.2":
version: 2.1.2
resolution: "ms@npm:2.1.2"
checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc
Expand Down Expand Up @@ -5389,19 +5359,15 @@ __metadata:
resolution: "update-electron-app@workspace:."
dependencies:
"@eslint/js": "npm:^9.15.0"
"@types/github-url-to-object": "npm:^4.0.1"
"@types/jest": "npm:^29.5.14"
"@types/ms": "npm:^0.7.31"
"@types/node": "npm:^22.10.1"
electron: "npm:^35.7.5"
eslint: "npm:^9.15.0"
eslint-config-prettier: "npm:^9.1.0"
github-url-to-object: "npm:^4.0.4"
globals: "npm:^15.13.0"
husky: "npm:^9.1.7"
jest: "npm:^29.0.0"
lint-staged: "npm:^16.4.0"
ms: "npm:^2.1.1"
prettier: "npm:^3.0.3"
ts-jest: "npm:^29.2.5"
typescript: "npm:^5.7.2"
Expand Down