Skip to content

Commit 7226571

Browse files
authored
build: convert Forge and Webpack config to TypeScript (#1406)
* build: convert Forge and Webpack config to TypeScript * fix: yarn electron-releases on Windows
1 parent 7cf08bf commit 7226571

File tree

12 files changed

+202
-95
lines changed

12 files changed

+202
-95
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ jobs:
111111
shell: bash.exe
112112
steps:
113113
- install
114-
- run: export WINDOWS_CODESIGN_FILE=$(node ./tools/add-windows-cert.js)
114+
- run: export WINDOWS_CODESIGN_FILE=$(ts-node ./tools/add-windows-cert.ts)
115115
- run: npx yarn run publish --arch=<< parameters.arch >> --dry-run
116116
- store_artifacts:
117117
path: out

forge.config.js renamed to forge.config.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
const fs = require('fs');
2-
const path = require('path');
1+
import * as fs from 'node:fs';
2+
import * as path from 'node:path';
33

4-
const packageJson = require('./package.json');
5-
const { maybeFetchContributors } = require('./tools/contributors');
6-
const { populateReleases } = require('./tools/fetch-releases');
4+
import type { ForgeConfig } from '@electron-forge/shared-types';
5+
6+
import packageJson from './package.json';
7+
import { maybeFetchContributors } from './tools/contributors';
8+
import { populateReleases } from './tools/fetch-releases';
9+
import { mainConfig } from './tools/webpack/webpack.main.config';
10+
import { rendererConfig } from './tools/webpack/webpack.renderer.config';
711

812
const { version } = packageJson;
913
const iconDir = path.resolve(__dirname, 'assets', 'icons');
@@ -27,7 +31,7 @@ const commonLinuxConfig = {
2731
mimeType: ['x-scheme-handler/electron-fiddle'],
2832
};
2933

30-
const config = {
34+
const config: ForgeConfig = {
3135
hooks: {
3236
generateAssets: async () => {
3337
await Promise.all([populateReleases(), maybeFetchContributors(true)]);
@@ -45,10 +49,10 @@ const config = {
4549
liveReload: false,
4650
hot: 'only',
4751
},
48-
mainConfig: path.join(root, 'tools/webpack/webpack.main.config.js'),
52+
mainConfig: mainConfig,
4953
renderer: {
5054
nodeIntegration: true,
51-
config: path.join(root, 'tools/webpack/webpack.renderer.config.js'),
55+
config: rendererConfig,
5256
entryPoints: [
5357
{
5458
html: path.join(root, './static/index.html'),
@@ -108,7 +112,7 @@ const config = {
108112
{
109113
name: '@electron-forge/maker-squirrel',
110114
platforms: ['win32'],
111-
config: (arch) => ({
115+
config: (arch: string) => ({
112116
name: 'electron-fiddle',
113117
authors: 'Electron Community',
114118
exe: 'electron-fiddle.exe',
@@ -125,6 +129,7 @@ const config = {
125129
{
126130
name: '@electron-forge/maker-zip',
127131
platforms: ['darwin'],
132+
config: {},
128133
},
129134
{
130135
name: '@electron-forge/maker-deb',
@@ -178,7 +183,8 @@ function notarizeMaybe() {
178183
return;
179184
}
180185

181-
config.packagerConfig.osxNotarize = {
186+
// TODO: appBundleId is not being accepted for typing
187+
(config.packagerConfig!.osxNotarize as any) = {
182188
appBundleId: 'com.electron.fiddle',
183189
appleId: process.env.APPLE_ID,
184190
appleIdPassword: process.env.APPLE_ID_PASSWORD,
@@ -189,4 +195,4 @@ function notarizeMaybe() {
189195
notarizeMaybe();
190196

191197
// Finally, export it
192-
module.exports = config;
198+
export default config;

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"homepage": "https://electronjs.org/fiddle",
88
"main": "./.webpack/main",
99
"scripts": {
10-
"contributors": "node ./tools/contributors.js",
10+
"contributors": "ts-node ./tools/contributors.ts",
1111
"lint:style": "stylelint \"./src/less/*.less\"",
1212
"lint:ts": "eslint \"./**/*.{ts,tsx}\"",
1313
"lint:js": "eslint \"./**/*.js\"",
@@ -24,7 +24,7 @@
2424
"test:ci": "jest --ci --config=jest.json --coverage --runInBand --reporters=jest-junit",
2525
"test:report": "jest --config=jest.json --json --bail=false --outputFile=report.json | true",
2626
"tsc": "tsc --noEmit -p .",
27-
"electron-releases": "node --unhandled-rejections=strict ./tools/fetch-releases.js",
27+
"electron-releases": "node --unhandled-rejections=strict -r ts-node/register ./tools/fetch-releases.ts",
2828
"postinstall": "husky install && npm run electron-releases"
2929
},
3030
"keywords": [
@@ -35,7 +35,7 @@
3535
"author": "Felix Rieseberg <[email protected]>",
3636
"license": "MIT",
3737
"config": {
38-
"forge": "./forge.config.js"
38+
"forge": "./forge.config.ts"
3939
},
4040
"dependencies": {
4141
"@blueprintjs/core": "^3.36.0",
@@ -144,6 +144,7 @@
144144
"terser-webpack-plugin": "^5.3.3",
145145
"ts-jest": "^29.1.1",
146146
"ts-loader": "^9.4.4",
147+
"ts-node": "^10.9.1",
147148
"typescript": "^5.1.6",
148149
"webpack": "^5.69.1"
149150
},

tools/add-windows-cert.js renamed to tools/add-windows-cert.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as os from 'os';
2-
import * as path from 'path';
1+
import * as os from 'node:os';
2+
import * as path from 'node:path';
33

44
import * as fs from 'fs-extra';
55

tools/contributors.js renamed to tools/contributors.ts

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
const path = require('path');
2-
const util = require('util');
1+
import * as path from 'node:path';
2+
import * as util from 'node:util';
33

4-
const fetch = require('cross-fetch');
5-
const fs = require('fs-extra');
6-
const logSymbols = require('log-symbols');
4+
import fetch from 'cross-fetch';
5+
import fs from 'fs-extra';
6+
import logSymbols from 'log-symbols';
77

88
const { GITHUB_TOKEN, GH_TOKEN } = process.env;
99
const CONTRIBUTORS_FILE_PATH = path.join(
@@ -12,14 +12,33 @@ const CONTRIBUTORS_FILE_PATH = path.join(
1212
);
1313
const CONTRIBUTORS_URL =
1414
'https://api.github.com/repos/electron/fiddle/contributors?per_page=100';
15-
const HEADERS =
15+
const HEADERS: Record<string, string> =
1616
GITHUB_TOKEN || GH_TOKEN
1717
? {
1818
Authorization: `Bearer ${GITHUB_TOKEN || GH_TOKEN}`,
1919
}
2020
: {};
2121

22-
async function maybeFetchContributors(silent) {
22+
interface GitHubContributorInfo {
23+
html_url: string;
24+
url: string;
25+
login: string;
26+
avatar_url: string;
27+
type: string;
28+
contributions: number;
29+
}
30+
31+
interface ContributorInfo {
32+
url: string;
33+
api: string;
34+
login: string;
35+
avatar: string;
36+
name: string;
37+
bio: string;
38+
location: string;
39+
}
40+
41+
export async function maybeFetchContributors(silent?: boolean): Promise<void> {
2342
try {
2443
const stats = fs.statSync(CONTRIBUTORS_FILE_PATH);
2544
const mtime = new Date(util.inspect(stats.mtime));
@@ -66,9 +85,10 @@ async function maybeFetchContributors(silent) {
6685
* Fetch the name for a contributor
6786
*
6887
* @param contributor - Contributor object
69-
* @returns {Promise}
7088
*/
71-
function fetchDetailsContributor(contributor) {
89+
function fetchDetailsContributor(contributor: {
90+
api: string;
91+
}): Promise<ContributorInfo> {
7292
return fetch(contributor.api, { headers: HEADERS }).then((response) =>
7393
response.json(),
7494
);
@@ -78,41 +98,38 @@ function fetchDetailsContributor(contributor) {
7898
* Fetch the names for an array of contributors
7999
*
80100
* @param contributors - Array of contributor
81-
* @returns {Promise}
82101
*/
83-
function fetchDetailsContributors(contributors) {
84-
return new Promise((resolve) => {
85-
const withDetails = contributors;
86-
const promises = [];
87-
88-
contributors.forEach((contributor, i) => {
89-
const detailFetcher = fetchDetailsContributor(contributor).then(
90-
({ name, bio, location }) => {
91-
withDetails[i].name = name;
92-
withDetails[i].bio = bio;
93-
withDetails[i].location = location;
94-
},
95-
);
96-
97-
promises.push(detailFetcher);
98-
});
102+
async function fetchDetailsContributors(
103+
contributors: Pick<ContributorInfo, 'api'>[],
104+
) {
105+
const withDetails = contributors as ContributorInfo[];
106+
const promises: Promise<void>[] = [];
107+
108+
contributors.forEach((contributor, i) => {
109+
const detailFetcher = fetchDetailsContributor(contributor).then(
110+
({ name, bio, location }) => {
111+
withDetails[i].name = name;
112+
withDetails[i].bio = bio;
113+
withDetails[i].location = location;
114+
},
115+
);
99116

100-
Promise.all(promises).then(() => resolve(withDetails));
117+
promises.push(detailFetcher);
101118
});
119+
120+
await Promise.all(promises);
121+
return withDetails;
102122
}
103123

104-
/**
105-
* (description)
106-
*
107-
* @export
108-
* @returns {Promise}
109-
*/
110124
function fetchContributors() {
111-
const contributors = [];
125+
const contributors: Pick<
126+
ContributorInfo,
127+
'url' | 'api' | 'login' | 'avatar'
128+
>[] = [];
112129

113130
return fetch(CONTRIBUTORS_URL, { headers: HEADERS })
114131
.then((response) => response.json())
115-
.then(async (data) => {
132+
.then(async (data: GitHubContributorInfo[]) => {
116133
if (data && data.forEach) {
117134
data.forEach(
118135
({ html_url, url, login, avatar_url, type, contributions }) => {
@@ -140,7 +157,7 @@ function fetchContributors() {
140157
* Fetch the contributors and write the result to disk
141158
*/
142159
async function fetchAndWriteContributorsFile() {
143-
await new Promise((resolve) => {
160+
await new Promise<void>((resolve) => {
144161
fs.access(
145162
CONTRIBUTORS_FILE_PATH,
146163
fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK,
@@ -151,7 +168,7 @@ async function fetchAndWriteContributorsFile() {
151168
}
152169

153170
console.log(logSymbols.info, 'Fetching contributors');
154-
let data;
171+
let data: ContributorInfo[];
155172

156173
try {
157174
data = await fetchContributors();
@@ -178,10 +195,6 @@ async function fetchAndWriteContributorsFile() {
178195
});
179196
}
180197

181-
module.exports = {
182-
maybeFetchContributors,
183-
};
184-
185198
if (require.main === module) {
186199
(async () => {
187200
await maybeFetchContributors();

tools/fetch-releases.js renamed to tools/fetch-releases.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
const path = require('path');
1+
import * as path from 'node:path';
22

3-
const { ElectronVersions } = require('@electron/fiddle-core');
4-
const fs = require('fs-extra');
3+
import { ElectronVersions } from '@electron/fiddle-core';
4+
import fs from 'fs-extra';
55

66
const file = path.join(__dirname, '..', 'static', 'releases.json');
77

8-
async function populateReleases() {
8+
export async function populateReleases() {
99
const elves = await ElectronVersions.create(undefined, { ignoreCache: true });
1010
const releases = elves.versions.map(({ version }) =>
1111
elves.getReleaseInfo(version),
@@ -26,10 +26,6 @@ async function populateReleases() {
2626
}
2727
}
2828

29-
module.exports = {
30-
populateReleases,
31-
};
32-
3329
if (require.main === module) {
3430
(async () => {
3531
await populateReleases();

tools/webpack/common/webpack.plugins.js

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type IForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
2+
import { ProvidePlugin } from 'webpack';
3+
4+
// eslint-disable-next-line @typescript-eslint/no-var-requires
5+
const ForkTsCheckerWebpackPlugin: typeof IForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
6+
7+
export const plugins = [
8+
new ForkTsCheckerWebpackPlugin({
9+
logger: 'webpack-infrastructure',
10+
}),
11+
new ProvidePlugin({
12+
__importStar: ['tslib', '__importStar'],
13+
}),
14+
];

tools/webpack/common/webpack.rules.js renamed to tools/webpack/common/webpack.rules.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
module.exports = [
1+
import type { ModuleOptions } from 'webpack';
2+
3+
export const rules: Required<ModuleOptions>['rules'] = [
24
// Add support for native node modules
35
{
46
// We're specifying native_modules in the test because the asset relocator loader generates a

tools/webpack/webpack.main.config.js renamed to tools/webpack/webpack.main.config.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
const CopyPlugin = require('copy-webpack-plugin');
2-
const TerserPlugin = require('terser-webpack-plugin');
1+
import CopyPlugin from 'copy-webpack-plugin';
2+
import TerserPlugin from 'terser-webpack-plugin';
3+
import type { Configuration } from 'webpack';
34

4-
const plugins = require('./common/webpack.plugins');
5-
const rules = require('./common/webpack.rules');
5+
import { plugins } from './common/webpack.plugins';
6+
import { rules } from './common/webpack.rules';
67

7-
module.exports = {
8+
export const mainConfig: Configuration = {
89
/**
910
* This is the main entry point for your application, it's the first file
1011
* that runs in the main process.

0 commit comments

Comments
 (0)