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
15 changes: 15 additions & 0 deletions .github/workflows/ecosystem.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: ecosystem
on:
push:
branches: [main, ci/hpm]
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

Suggested change
branches: [main, ci/hpm]
branches: [main]

workflow_dispatch:
jobs:
http-proxy-middleware:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: npm i -fg corepack && corepack enable
- uses: actions/setup-node@v6
with: { node-version: lts/*, cache: "pnpm" }
Comment thread
pi0 marked this conversation as resolved.
- run: pnpm install
- run: pnpm test:ecosystem http-proxy-middleware
17 changes: 9 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,15 @@ pnpm test # Lint + typecheck + tests with coverage

## Tooling

| Tool | Command | Notes |
| --------- | ---------------- | --------------------------------------------- |
| Build | `pnpm build` | Uses `unbuild` → CJS + ESM + types in `dist/` |
| Dev | `pnpm dev` | Vitest watch mode |
| Lint | `pnpm lint` | `oxlint` + `oxfmt --check` |
| Format | `pnpm fmt` | `oxlint --fix` + `oxfmt` |
| Typecheck | `pnpm typecheck` | `tsgo --noEmit` (native TS preview) |
| Test | `pnpm test` | Full: lint + typecheck + vitest with coverage |
| Tool | Command | Notes |
| --------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Build | `pnpm build` | Uses `unbuild` → CJS + ESM + types in `dist/` |
Comment thread
pi0 marked this conversation as resolved.
| Dev | `pnpm dev` | Vitest watch mode |
| Lint | `pnpm lint` | `oxlint` + `oxfmt --check` |
| Format | `pnpm fmt` | `oxlint --fix` + `oxfmt` |
| Typecheck | `pnpm typecheck` | `tsgo --noEmit` (native TS preview) |
| Test | `pnpm test` | Full: lint + typecheck + vitest with coverage |
| Ecosystem | `pnpm test:ecosystem [target]` | Builds + `npm pack`s httpxy, clones an upstream consumer in a temp dir, overrides its httpxy dep with the local tarball, and runs its tests. Default target: `http-proxy-middleware`. Env: `KEEP=1` retains temp dirs; `REF=<git-ref>` pins the upstream checkout. Script: [scripts/ecosystem-test.mjs](scripts/ecosystem-test.mjs). |

## Key Types

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"scripts": {
"build": "obuild",
"dev": "vitest",
"test:ecosystem": "node scripts/ecosystem-test.mjs",
"lint": "oxlint . && oxfmt --check",
"fmt": "oxlint . --fix && oxfmt",
"prepack": "pnpm run build",
Expand Down
99 changes: 99 additions & 0 deletions scripts/ecosystem-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env node
// Ecosystem test runner: builds & packs httpxy, clones an upstream consumer
// in a temp dir, installs deps with the local tarball overriding the published
// httpxy version, and runs the consumer's test suite.
//
// Usage:
// node scripts/ecosystem-test.mjs [target]
//
// Targets:
// http-proxy-middleware (default)
//
// Env:
// KEEP=1 Keep temp dirs after run for debugging.
// REF=<ref> Git ref to check out from the upstream repo (branch/tag/sha).

import { execSync } from "node:child_process";
import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");

const TARGETS = {
"http-proxy-middleware": {
repo: "https://github.com/chimurai/http-proxy-middleware.git",
// TODO: revert to default branch once `httpxy-0.5.2` is merged upstream.
ref: "master",
install: "yarn install --ignore-scripts",
steps: ["yarn build", "yarn test"],
},
};

const targetName = process.argv[2] || "http-proxy-middleware";
const target = TARGETS[targetName];
if (!target) {
console.error(`Unknown target: ${targetName}`);
console.error(`Available: ${Object.keys(TARGETS).join(", ")}`);
process.exit(1);
}

const KEEP = process.env.KEEP === "1";
const REF = process.env.REF;

const packDir = mkdtempSync(join(tmpdir(), "httpxy-pack-"));
const workDir = mkdtempSync(join(tmpdir(), `httpxy-eco-${targetName}-`));
const upstreamDir = join(workDir, targetName);

const cleanup = () => {
if (KEEP) {
console.log(`\n(KEEP=1) Leaving artifacts:`);
console.log(` pack: ${packDir}`);
console.log(` upstream: ${upstreamDir}`);
return;
}
rmSync(packDir, { recursive: true, force: true });
rmSync(workDir, { recursive: true, force: true });
};

process.on("exit", cleanup);
process.on("SIGINT", () => process.exit(130));

const run = (cmd, cwd = ROOT) => {
console.log(`\n$ (${cwd === ROOT ? "httpxy" : targetName}) ${cmd}`);
execSync(cmd, { stdio: "inherit", cwd });
};
Comment thread
pi0 marked this conversation as resolved.

// 1. Build httpxy and pack into a tarball
run("pnpm build");
run(`npm pack --pack-destination ${packDir}`);
const tarball = readdirSync(packDir).find((f) => f.endsWith(".tgz"));
if (!tarball) {
throw new Error(`No tarball produced in ${packDir}`);
}
const tarballPath = join(packDir, tarball);
console.log(`\nPacked: ${tarballPath}`);

// 2. Clone upstream consumer at a shallow depth
const ref = REF || target.ref;
const branchArg = ref ? `--branch ${ref} ` : "";
run(`git clone --depth 1 ${branchArg}${target.repo} ${upstreamDir}`);

// 3. Pin httpxy to the local tarball via deps + yarn `resolutions`
const pkgPath = join(upstreamDir, "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
const fileSpec = `file:${tarballPath}`;
if (pkg.dependencies?.httpxy) pkg.dependencies.httpxy = fileSpec;
if (pkg.devDependencies?.httpxy) pkg.devDependencies.httpxy = fileSpec;
pkg.resolutions = { ...pkg.resolutions, httpxy: fileSpec };
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
console.log(`\nPatched ${pkgPath} to use ${fileSpec}`);

// 4. Install deps and run upstream tests
run(target.install, upstreamDir);
for (const step of target.steps) {
run(step, upstreamDir);
}

console.log(`\n✓ ${targetName} tests passed against local httpxy build`);
Loading