Skip to content

Commit

Permalink
Clean up build scripts (#12305)
Browse files Browse the repository at this point in the history
* move from `ts-node` to `node --experimental-strip-types`, create `build.ts`

* remove `engines` field, specify `devEngines`

* adjust node version for CI

* fix up some more syntax

* prettier

* adjust precheck, bump minimal lockfile version to 3

* convert jest config to esm

* move `entryPoints` to TS, make it work in mjs and jest

* run rollup with ts config

* update a few more node calls

* some more typings

* move all scripts to function invocation

* migrate `prepareChangestsRelease` too

* remove scripts that are not called manually

* convert `prepareDist` to TS

* migrate `precheck.js`

* `version.js->ts`

* use jest ts config

* prettier

* dirname.cjs->cts

* dirname-related import fixes

* fix up new knip issues

* delete `devEngines` instead of `engines` field

* require node 23.6 instead of 22.6
  • Loading branch information
phryneas authored Jan 31, 2025
1 parent 2a62324 commit 6585f99
Show file tree
Hide file tree
Showing 51 changed files with 56,304 additions and 5,841 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/api-extractor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/arethetypeswrong.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"
- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/change-prerelease-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ jobs:
# with the correct commits
fetch-depth: 0

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Write latest version to package.json and package-lock.json
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cleanup-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/compare-build-output.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
with:
# Fetch entire git history so we have the parent commit to compare against
fetch-depth: 0
- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"
- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/exit-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ jobs:
# with the correct commits
fetch-depth: 0

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Write latest version to package.json and package-lock.json
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ jobs:
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies with cache
uses: bahmutov/npm-install@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-pr-releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies with cache
uses: bahmutov/npm-install@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ jobs:
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/size-limit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"
- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1
- name: Run size-limit
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/snapshot-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ jobs:
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Setup Node.js 20.x
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: ">=23.6.0"

- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"${workspaceRoot}/node_modules/.bin/jest",
"${relativeFile}",
"--config",
"./config/jest.config.js",
"./config/jest.config.ts",
"--runInBand",
"--watch"
],
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"files.insertFinalNewline": true,
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.enableFiletypes": ["mdx"],
"jest.jestCommandLine": "node --expose-gc node_modules/.bin/jest --config ./config/jest.config.js --ignoreProjects 'ReactDOM 17' --runInBand"
"jest.jestCommandLine": "node --expose-gc node_modules/.bin/jest --config ./config/jest.config.ts --ignoreProjects 'ReactDOM 17' --runInBand"
}
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ npm run test:watch
Call jest directly making sure to pass in the jest config, and use its `testRegex` option:

```
jest --config ./config/jest.config.js --testRegex __tests__/useQuery.test.tsx
jest --config ./config/jest.config.ts --testRegex __tests__/useQuery.test.tsx
```

### Wiring a checkout into an application
Expand Down
14 changes: 10 additions & 4 deletions config/apiExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as path from "path";
import type { IConfigFile } from "@microsoft/api-extractor";
import {
Extractor,
ExtractorConfig,
ExtractorLogLevel,
IConfigFile,
} from "@microsoft/api-extractor";
import { parseArgs } from "node:util";
import fs from "node:fs";

// @ts-ignore
import { map, buildDocEntryPoints } from "./entryPoints.js";
import { map, buildDocEntryPoints } from "./entryPoints.ts";
import { readFileSync } from "fs";

const parsed = parseArgs({
Expand All @@ -35,9 +35,15 @@ if (
}

// Load and parse the api-extractor.json file
const configObjectFullPath = path.resolve(__dirname, "../api-extractor.json");
const configObjectFullPath = path.resolve(
import.meta.dirname,
"../api-extractor.json"
);
const baseConfig = ExtractorConfig.loadFile(configObjectFullPath);
const packageJsonFullPath = path.resolve(__dirname, "../package.json");
const packageJsonFullPath = path.resolve(
import.meta.dirname,
"../package.json"
);

process.exitCode = 0;

Expand Down
63 changes: 63 additions & 0 deletions config/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { $ } from "zx";
import { join } from "node:path";
import { parseArgs } from "node:util";

import { inlineInheritDoc } from "./inlineInheritDoc.ts";
import { updateVersion, verifyVersion } from "./version.ts";
import { processInvariants } from "./processInvariants.ts";
import { rewriteSourceMaps } from "./rewriteSourceMaps.ts";
import { rollup } from "./rollup.ts";
import { prepareDist } from "./prepareDist.ts";
import { postprocessDist } from "./postprocessDist.ts";
import { prepareChangesetsRelease } from "./prepareChangesetsRelease.ts";

$.cwd = join(import.meta.dirname, "..");
$.verbose = true;

const buildSteps = {
typescript: () => $`npx tsc`,
updateVersion,
inlineInheritDoc,
processInvariants,
rewriteSourceMaps,
rollup,
prepareDist,
postprocessDist,
verifyVersion,
};
const additionalSteps = {
prepareChangesetsRelease,
};

const args = parseArgs({
options: {
step: {
type: "string",
multiple: true,
default: ["build"],
},
},
});

const allSteps = Object.assign({}, buildSteps, additionalSteps);

const runSteps = args.values.step.flatMap((step) =>
step === "build" ? Object.keys(buildSteps) : [step]
);

const wrongSteps = runSteps.filter((step) => !(step in allSteps));
if (wrongSteps.length) {
throw new Error(
`Unknown steps: ${wrongSteps.join(", ")}. Valid steps are ${Object.keys(
allSteps
).join(", ")}`
);
}

console.log("Running build steps: %s", runSteps.join(", "));

for (const step of runSteps) {
console.log("--- Step %s: running ---", step);
await allSteps[step]();
console.log("--- Step %s: done ---", step);
}
2 changes: 1 addition & 1 deletion config/bundlesize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import bytes from "bytes";

const gzipBundleByteLengthLimit = bytes("35.25KB");
const minFile = join("dist", "apollo-client.min.cjs");
const minPath = join(__dirname, "..", minFile);
const minPath = join(import.meta.dirname, "..", minFile);
const gzipByteLen = gzipSync(readFileSync(minPath)).byteLength;
const overLimit = gzipByteLen > gzipBundleByteLengthLimit;

Expand Down
4 changes: 4 additions & 0 deletions config/dirname.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// workaround for `entryPoints.ts` that needs access to the current directory,
// but cannot use `import.meta` as the file is required by Jest, which transpiles
// the file to CommonJS - ending up with "SyntaxError: Cannot use 'import.meta' outside a module"
module.exports.__dirname = __dirname;
43 changes: 26 additions & 17 deletions config/entryPoints.js → config/entryPoints.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import path from "path";
// @ts-expect-error An import path can only end with a '.cts' extension when 'allowImportingTsExtensions' is enabled.
import { __dirname } from "./dirname.cts";

type EntryPoint = {
dirs: string[];
bundleName?: string;
extensions?: string[];
sideEffects?: boolean;
};
const entryPoints = [
{ dirs: [], bundleName: "main" },
{ dirs: ["cache"] },
Expand Down Expand Up @@ -32,7 +42,7 @@ const entryPoints = [
{ dirs: ["utilities", "subscriptions", "relay"] },
{ dirs: ["utilities", "subscriptions", "urql"] },
{ dirs: ["utilities", "globals"], sideEffects: true },
];
] satisfies EntryPoint[];

const lookupTrie = Object.create(null);
entryPoints.forEach((info) => {
Expand All @@ -44,17 +54,21 @@ entryPoints.forEach((info) => {
node.isEntry = true;
});

exports.forEach = function (callback, context) {
export const forEach = function (
callback: (value: EntryPoint, index: number, array: EntryPoint[]) => void,
context?: any
) {
entryPoints.forEach(callback, context);
};

exports.map = function map(callback, context) {
export const map = function map<U>(
callback: (value: EntryPoint, index: number, array: EntryPoint[]) => U,
context?: any
) {
return entryPoints.map(callback, context);
};

const path = require("path").posix;

exports.check = function (id, parentId) {
export const check = function (id: string, parentId: string) {
const resolved = path.resolve(path.dirname(parentId), id);
const importedParts = partsAfterDist(resolved);

Expand Down Expand Up @@ -91,7 +105,7 @@ exports.check = function (id, parentId) {
return false;
};

function partsAfterDist(id) {
function partsAfterDist(id: string): string[] {
const parts = id.split(path.sep);
const distIndex = parts.lastIndexOf("dist");
if (/^index.jsx?$/.test(parts[parts.length - 1])) {
Expand All @@ -100,15 +114,10 @@ function partsAfterDist(id) {
if (distIndex >= 0) {
return parts.slice(distIndex + 1);
}
return [];
}

exports.getEntryPointDirectory = function (file) {
const parts = partsAfterDist(file) || file.split(path.sep);
const len = lengthOfLongestEntryPoint(parts);
if (len >= 0) return parts.slice(0, len).join(path.sep);
};

function lengthOfLongestEntryPoint(parts) {
function lengthOfLongestEntryPoint(parts: string[]) {
let node = lookupTrie;
let longest = -1;
for (let i = 0; node && i < parts.length; ++i) {
Expand All @@ -121,16 +130,16 @@ function lengthOfLongestEntryPoint(parts) {
return longest;
}

function arraysEqualUpTo(a, b, end) {
function arraysEqualUpTo(a: unknown[], b: unknown[], end: number) {
for (let i = 0; i < end; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}

exports.buildDocEntryPoints = () => {
export const buildDocEntryPoints = () => {
const dist = path.resolve(__dirname, "../dist");
const entryPoints = exports.map((entryPoint) => {
const entryPoints = map((entryPoint) => {
return `export * from "${dist}/${entryPoint.dirs.join("/")}/index.d.ts";`;
});
entryPoints.push(
Expand Down
6 changes: 3 additions & 3 deletions config/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as path from "path";
import * as recast from "recast";
import * as parser from "recast/parsers/babel";
import glob = require("glob");
import * as parser from "recast/parsers/babel.js";
import glob from "glob";

export const distDir = path.resolve(__dirname, "..", "dist");
export const distDir = path.resolve(import.meta.dirname, "..", "dist");

export function eachFile(
dir: string,
Expand Down
Loading

0 comments on commit 6585f99

Please sign in to comment.