Skip to content
Merged
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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ node_modules
example/dist
example/node_modules
dump.rdb
.yarn/install-state.gz
dist
coverage
*.log
.DS_Store
.vscode
*.tsbuildinfo
.claude
942 changes: 942 additions & 0 deletions .yarn/releases/yarn-4.10.3.cjs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.10.3.cjs
8 changes: 0 additions & 8 deletions bin/test-update-server.js

This file was deleted.

10 changes: 10 additions & 0 deletions bin/test-update-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node

import { createServer } from "../test/helpers/create-server.js";

async function main() {
const { address } = await createServer();
console.log(`Server running at ${address}`);
}

main();
46 changes: 23 additions & 23 deletions bin/update-server.js → bin/update-server.ts
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
#!/usr/bin/env node

"use strict";
import { config } from "dotenv-safe";
import assert from "node:assert";
import redis from "redis";
import ms, { StringValue } from "ms";
import Redlock, { CompatibleRedisClient } from "redlock";
import Updates from "../src/updates.js";

require("dotenv-safe").config();
config();

process.title = "update-server";

const Updates = require("../src/updates");
const redis = require("redis");
const ms = require("ms");
const assert = require("assert");
const Redlock = require("redlock");

//
// Args
//

const {
GH_TOKEN: token,
REDIS_URL: redisUrl = "redis://localhost:6379",
PORT: port = 3000,
PORT: port = "3000",
CACHE_TTL: cacheTTL = "15m",
} = process.env;
assert(token, "GH_TOKEN required");
Expand All @@ -31,10 +30,6 @@ async function getCache() {
const fixedRedisUrl = redisUrl.replace("redis://h:", "redis://:");
const client = redis.createClient({
url: fixedRedisUrl,
// Needed for compatibility with Redlock. However, it also requires all "modern" commands
// to be prefixed with `client.v4`.
// See also: https://github.com/redis/node-redis/blob/master/docs/v3-to-v4.md#legacy-mode
legacyMode: true,
socket: {
tls: true,
rejectUnauthorized: false,
Expand All @@ -46,24 +41,29 @@ async function getCache() {

client.on("error", (err) => console.log("Redis Client Error", err));

const redlock = new Redlock([client], {
const redlock = new Redlock([client.legacy() as CompatibleRedisClient], {
retryDelay: ms("10s"),
});

const cache = {
async get(key) {
const json = await client.v4.get(key);
return json && JSON.parse(json);
async get(key: string) {
const json = await client.get(key);
return json && typeof json === "string" && JSON.parse(json);
},
async set(key, value) {
async set(key: string, value: any) {
const json = JSON.stringify(value);

await client.v4.set(key, json, {
EX: ms(cacheTTL) / 1000,
await client.set(key, json, {
EX: Math.floor(ms(cacheTTL as StringValue) / 1000),
});
},
async lock(resource) {
return redlock.lock(`locks:${resource}`, ms("1m"));
async lock(resource: string) {
const result = await redlock.lock([`locks:${resource}`], ms("1m"));
return {
async unlock() {
await result.unlock();
},
};
},
};

Expand All @@ -76,7 +76,7 @@ async function getCache() {
async function main() {
const cache = await getCache();
const updates = new Updates({ token, cache });
updates.listen(port, () => {
updates.listen(Number(port), () => {
console.log(`http://localhost:${port}`);
});
}
Expand Down
41 changes: 29 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
{
"name": "update.electronjs.org",
"private": true,
"type": "module",
"scripts": {
"start": "nodemon bin/update-server.js",
"start-test-server": "cross-env NODE_ENV=test nodemon bin/test-update-server.js",
"lint": "prettier --check '**/*.js'",
"prettier": "prettier --write '**/*.js'",
"test": "npm run lint && cross-env NODE_ENV=test nyc tap test/*.js"
"build": "tsc",
"start": "node dist/bin/update-server.js",
"start-test-server": "cross-env NODE_ENV=test node dist/bin/test-update-server.js",
"lint": "prettier --check '**/*.{js,ts}' --ignore-path .gitignore",
"prettier": "prettier --write '**/*.{js,ts}' --ignore-path .gitignore",
"typecheck": "tsc --noEmit",
"test": "npm run lint && npm run typecheck && cross-env NODE_ENV=test vitest run",
"test:watch": "cross-env NODE_ENV=test vitest watch",
"test:ui": "cross-env NODE_ENV=test vitest --ui",
"test:coverage": "cross-env NODE_ENV=test vitest run --coverage"
},
"dependencies": {
"dotenv-safe": "^8.2.0",
"dotenv": "^17.2.3",
"dotenv-safe": "^9.1.0",
"ms": "^2.1.3",
"pino": "^8.12.1",
"redis": "^4.6.6",
"redlock": "^3.1.2",
"redis": "^5.8.3",
"redlock": "^4.2.0",
"request-ip": "^3.3.0",
"semver": "^7.5.2"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.2",
"@types/dotenv-safe": "^9.1.0",
"@types/ms": "^2.1.0",
"@types/node": "^24.6.2",
"@types/node-fetch": "^2.6.13",
"@types/redlock": "^4.0.7",
"@types/request-ip": "^0.0.41",
"@types/semver": "^7.7.1",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"cross-env": "^7.0.3",
"nock": "^13.3.1",
"node-fetch": "2.6.9",
"nodemon": "^3.0.1",
"nyc": "^15.1.0",
"prettier": "^2.8.8",
"tap": "^16.3.4"
}
"typescript": "^5.9.3",
"vitest": "^3.2.4"
},
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f"
}
8 changes: 2 additions & 6 deletions src/asset-platform.js → src/asset-platform.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { PLATFORM_ARCH } = require("./constants");
import { PLATFORM_ARCH, type PlatformArch } from "./constants.js";

const assetPlatform = (fileName) => {
export const assetPlatform = (fileName: string): PlatformArch | false => {
if (/.*-(mac|darwin|osx).*\.zip$/i.test(fileName)) {
if (/-arm64/.test(fileName)) return PLATFORM_ARCH.DARWIN_ARM64;
if (/-universal/.test(fileName)) return PLATFORM_ARCH.DARWIN_UNIVERSAL;
Expand Down Expand Up @@ -28,7 +28,3 @@ const assetPlatform = (fileName) => {

return false;
};

module.exports = {
assetPlatform,
};
24 changes: 0 additions & 24 deletions src/constants.js

This file was deleted.

21 changes: 21 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const PLATFORM = {
WIN32: "win32",
DARWIN: "darwin",
} as const;

export const PLATFORM_ARCH = {
DARWIN_X64: "darwin-x64",
DARWIN_ARM64: "darwin-arm64",
DARWIN_UNIVERSAL: "darwin-universal",
WIN_X64: "win32-x64",
WIN_IA32: "win32-ia32",
WIN_ARM64: "win32-arm64",
} as const;

export type Platform = (typeof PLATFORM)[keyof typeof PLATFORM];
export type PlatformArch = (typeof PLATFORM_ARCH)[keyof typeof PLATFORM_ARCH];

export const ENV = process.env.NODE_ENV || "development";

export const PLATFORM_ARCHS: readonly PlatformArch[] =
Object.values(PLATFORM_ARCH);
Loading