diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..66dbbb0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +on: + pull_request: + branches: + - master + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x, 22.x] + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm test + + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm ci + - run: npm run lint diff --git a/.github/workflows/npm-publlish.yml b/.github/workflows/npm-publish.yml similarity index 100% rename from .github/workflows/npm-publlish.yml rename to .github/workflows/npm-publish.yml diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..5426959 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,333 @@ +# Migration Guide + +This guide helps you migrate between major versions of `@loke/http-rpc-client`. + +## Table of Contents + +- [v4 to v5](#migrating-from-v4-to-v5) +- [v3 to v4](#migrating-from-v3-to-v4) +- [v2 to v3](#migrating-from-v2-to-v3) +- [v1 to v2](#migrating-from-v1-to-v2) + +--- + +## Migrating from v4 to v5 + +### Breaking Changes + +#### 1. Node.js Version Requirement + +**v4:** Node.js >= 8 +**v5:** Node.js >= 20 + +**Action Required:** Upgrade to Node.js 20 or later. + +```bash +# Check your Node.js version +node --version +``` + +#### 2. Removed Legacy `load()` Function + +The legacy `load()` function and IPC manifest support have been completely removed. + +**v4:** + +```typescript +import { load } from "@loke/http-rpc-client"; + +const client = load("http://example.com", "my-service", { + /* options */ +}); +``` + +**v5:** + +```typescript +import { RPCClient } from "@loke/http-rpc-client"; + +const client = new RPCClient("http://example.com/", "my-service"); +``` + +**Migration Steps:** + +1. Remove all `ipc_manifests/*.json` files (no longer used) +2. Replace `load()` calls with direct instantiation of `RPCClient` or `RPCContextClient` +3. Update method calls to use the new client API + +#### 3. `@loke/context` is now a Peer Dependency + +**v4:** `@loke/context` was a regular dependency +**v5:** `@loke/context` is a peer dependency + +**Action Required:** Add `@loke/context` to your `package.json`: + +```bash +npm install @loke/context +``` + +```json +{ + "dependencies": { + "@loke/context": ">=0.0.1 <1" + } +} +``` + +#### 4. Network Errors Now Use `RpcHTTPError` + +Network-level errors (connection failures, DNS errors, etc.) are now wrapped in `RpcHTTPError` for better error handling. + +**v5:** + +```typescript +import { + RPCClient, + RpcHTTPError, + RpcResponseError, +} from "@loke/http-rpc-client"; + +try { + const result = await client.request("myMethod", params); +} catch (err) { + if (err instanceof RpcHTTPError) { + // Network-level error (connection failed, DNS error, etc.) + console.error("Network error:", err.message); + console.error("Cause:", err.cause); + } else if (err instanceof RpcResponseError) { + // Application-level error from the remote service + console.error("RPC error:", err.message); + } +} +``` + +#### 5. Native Fetch Instead of node-fetch + +The package now uses Node.js native `fetch` API instead of `node-fetch`. + +**Action Required:** None if using Node.js 20+. The native fetch is available globally. + +#### 6. Module System Changes + +The package now provides both ESM and CommonJS builds with proper exports. + +**ESM:** + +```typescript +import { RPCClient, RPCContextClient } from "@loke/http-rpc-client"; +``` + +**CommonJS:** + +```javascript +const { RPCClient, RPCContextClient } = require("@loke/http-rpc-client"); +``` + +#### 7. prom-client Peer Dependency Updated + +**v4:** `prom-client: ">=12 <=14"` +**v5:** `prom-client: ">=12 <=15"` + +**Action Required:** Update prom-client if using v15: + +```bash +npm install prom-client@^15 +``` + +--- + +## Migrating from v3 to v4 + +### Breaking Changes + +#### 1. Context Support Required + +v4 introduced `@loke/context` for request context management. + +**New Classes:** + +- `RPCContextClient` - Uses `@loke/context` for request lifecycle management +- `RPCClient` - Maintains backward compatibility with timeout options + +**v3:** + +```javascript +const client = new RPCClient(baseURL, serviceName); +await client.request("method", params); +``` + +**v4 (Recommended):** + +```typescript +import * as context from "@loke/context"; +import { RPCContextClient } from "@loke/http-rpc-client"; + +const client = new RPCContextClient(baseURL, serviceName); +const ctx = context.background; +await client.request(ctx, "method", params); +``` + +**v4 (Legacy compatibility):** + +```typescript +import { RPCClient } from "@loke/http-rpc-client"; + +const client = new RPCClient(baseURL, serviceName); +await client.request("method", params, { timeout: 5000 }); +``` + +#### 2. Request Timeout Handling + +**v3:** No built-in timeout support +**v4:** Timeout support via `RequestOptions` or context deadlines + +```typescript +// Using RPCClient with timeout option +await client.request("method", params, { timeout: 5000 }); + +// Using RPCContextClient with context deadline +const { ctx, abort } = context.withTimeout(context.background, 5000); +try { + await client.request(ctx, "method", params); +} finally { + abort(); +} +``` + +#### 3. Empty Response Handling + +v4 properly handles empty responses (HTTP 204 or Content-Length: 0). + +```typescript +// Returns undefined for empty responses +const result = await client.request("methodWithNoResponse", {}); +// result === undefined +``` + +#### 4. Improved Error Content-Type Handling + +Error responses now properly handle `application/json; charset=utf-8` and other content-type variations. + +--- + +## Migrating from v2 to v3 + +### Breaking Changes + +#### 1. Package Name Change + +**v2:** `loke-http-rpc-client` +**v3:** `@loke/http-rpc-client` + +**Action Required:** Update your package.json and imports: + +```bash +npm uninstall loke-http-rpc-client +npm install @loke/http-rpc-client +``` + +```diff +- import { load } from "loke-http-rpc-client"; ++ import { load } from "@loke/http-rpc-client"; +``` + +#### 2. Node.js Version Requirement + +**v2:** Node.js >= 6 +**v3:** Node.js >= 8 + +**Action Required:** Upgrade to Node.js 8 or later. + +#### 3. Enhanced Error Handling + +v3 improved error handling with better error types and stack traces. + +**Error properties now include:** + +- `type` - Error type from the remote service +- `code` - Error code +- `expose` - Whether error should be exposed to clients +- `source` - Array tracking error propagation through services +- `instance` - Error instance identifier + +```typescript +try { + await client.request("method", params); +} catch (err) { + console.log(err.type); // Error type + console.log(err.code); // Error code + console.log(err.source); // Error source chain + console.log(err.instance); // Error instance +} +``` + +#### 4. prom-client Peer Dependency Updated + +**v2:** `prom-client: "7.x"` +**v3:** `prom-client: ">=12"` + +**Action Required:** Update prom-client: + +```bash +npm install prom-client@^14 +``` + +--- + +## Migrating from v1 to v2 + +### Breaking Changes + +#### 1. Node.js Version Requirement + +**v1:** Node.js >= 4 +**v2:** Node.js >= 6 + +**Action Required:** Upgrade to Node.js 6 or later. + +#### 2. Prometheus Metrics Added + +v2 introduces Prometheus metrics support via `prom-client`. + +**New peer dependency required:** + +```bash +npm install prom-client +``` + +**Metrics exposed:** + +- `http_rpc_client_request_duration_seconds` - Histogram of request durations +- `http_rpc_client_requests_total` - Counter of total requests +- `http_rpc_client_failures_total` - Counter of failed requests + +Labels: `service`, `method`, `status_code`, `type` + +```typescript +import { register } from "prom-client"; + +// Expose metrics endpoint in your application +app.get("/metrics", (req, res) => { + res.set("Content-Type", register.contentType); + res.end(register.metrics()); +}); +``` + +#### 3. POST Request Retry Behavior + +**v1:** POST requests may have been retried on failure +**v2:** POST requests are never retried (to prevent duplicate operations) + +**Action Required:** Implement retry logic in your application if needed, being careful about idempotency. + +--- + +## Version Compatibility Matrix + +| Version | Node.js | prom-client | @loke/context | TypeScript | +| ------- | ------- | ----------- | ------------- | ---------- | +| v5.x | ≥ 20 | 12-15 | ≥0.0.1 (peer) | ✅ Full | +| v4.x | ≥ 8 | 12-14 | ≥0.0.1 | ✅ Full | +| v3.x | ≥ 8 | ≥12 | ❌ | ⚠️ Partial | +| v2.x | ≥ 6 | 7.x | ❌ | ❌ | +| v1.x | ≥ 4 | ❌ | ❌ | ❌ | diff --git a/package-lock.json b/package-lock.json index 04850b2..4c01594 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,6 @@ "name": "@loke/http-rpc-client", "version": "5.1.1", "license": "ISC", - "dependencies": { - "@loke/context": "^0.1.0" - }, "devDependencies": { "@eslint/js": "^9.18.0", "@tsconfig/node20": "^20.1.4", @@ -28,6 +25,7 @@ "node": ">=20" }, "peerDependencies": { + "@loke/context": ">=0.0.1 <1", "prom-client": ">=12 <=15" } }, @@ -674,7 +672,8 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/@loke/context/-/context-0.1.0.tgz", "integrity": "sha512-4Ka1z4rSkxChkSZBteH24awWCb0/Rth9zUOHyLtVQOHYT6Xk9Dfk3+17eSGC5ACFBZ/lElCDOhKNy8lCy9Xr1Q==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", diff --git a/package.json b/package.json index dec2e93..65abb7c 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,8 @@ "typescript": "^5.7.3", "typescript-eslint": "^8.21.0" }, - "dependencies": { - "@loke/context": "^0.1.0" - }, "peerDependencies": { + "@loke/context": ">=0.0.1 <1", "prom-client": ">=12 <=15" } }