Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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: 31 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
{
"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",
"happy-dom": "^19.0.2",
"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"
}
"tap": "^16.3.4",
"typescript": "^5.9.3",
"vitest": "^3.2.4"
},
"packageManager": "[email protected]+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