Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
3 changes: 0 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ jobs:
matrix:
node-version:
- '22.11'
- '20.18'
- '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