diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 000000000..3cf1f22c2 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,111 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json + +language: en-US + +reviews: + # Review draft PRs so we get early feedback + drafts: true + + # Enable high-level summary of changes + high_level_summary: true + + # Add a poem... just kidding, disable it + poem: false + + # Collapse walkthrough to keep PR comments clean + collapse_walkthrough: true + + # Auto-review on every push + auto_review: + enabled: true + drafts: true + + # Path-based review instructions + path_instructions: + - path: "src/core/**" + instructions: | + This is the core SDK module. Pay close attention to: + - Backward compatibility of public API changes + - Proper TypeScript typing (strict mode is enabled) + - No platform-specific code (Node.js, Web, React Native specifics belong in their respective platform directories) + - Thread safety considerations for shared state + - path: "src/core/endpoints/**" + instructions: | + These are REST API endpoint implementations. Review for: + - Correct request/response type definitions + - Proper error handling and status code mapping + - Consistent parameter validation + - Adherence to PubNub REST API contracts + - path: "src/core/types/**" + instructions: | + TypeScript type definitions. Ensure: + - Types are precise and not overly permissive (avoid `any`) + - Exported types maintain backward compatibility + - Proper use of generics and utility types + - path: "src/event-engine/**" + instructions: | + State-machine-based subscription management. Review for: + - Correct state transitions and edge cases + - No leaked subscriptions or event listeners + - Proper cleanup on state exit + - path: "src/entities/**" + instructions: | + High-level subscription API (Channel, ChannelGroup, etc.). Review for: + - Proper event handler lifecycle management + - Memory leak prevention (listener cleanup) + - path: "src/transport/**" + instructions: | + Platform-specific HTTP transport implementations. Review for: + - Proper timeout and cancellation handling + - Correct header management + - Error propagation consistency across platforms + - path: "src/node/**" + instructions: "Node.js platform implementation. Ensure no browser/DOM APIs are used." + - path: "src/web/**" + instructions: "Browser platform implementation. Ensure no Node.js-specific APIs (fs, crypto, etc.) are used." + - path: "src/react_native/**" + instructions: "React Native platform implementation. Verify compatibility with RN runtime." + - path: "test/**" + instructions: | + Test files. Review for: + - Adequate coverage of edge cases + - Proper use of mocks/stubs (Sinon + Nock) + - No flaky patterns (hardcoded timeouts, race conditions) + - Tests that actually assert meaningful behavior + + # Tools configuration + tools: + # Enable GitHub checks integration + github-checks: + enabled: true + timeout_ms: 120000 + +chat: + auto_reply: true + +# Path filters - ignore generated/vendored/build output +path_filters: + # Build outputs + - "!dist/**" + - "!lib/**" + - "!upload/**" + + # Dependencies + - "!node_modules/**" + + # Unrelated working directories (not part of the SDK source) + - "!dataSync/**" + - "!new-dataSync/**" + - "!demo-app/**" + - "!loan_quote/**" + - "!docs/**" + + # Lock files - too noisy, low review value + - "!package-lock.json" + + # Config/metadata that rarely needs review + - "!.pubnub.yml" + - "!.vscode/**" + + # Generated type bundles + - "!lib/types/**" diff --git a/src/core/components/request.ts b/src/core/components/request.ts index 8d7ef34cd..17c8d577c 100644 --- a/src/core/components/request.ts +++ b/src/core/components/request.ts @@ -123,7 +123,11 @@ export abstract class AbstractRequest 0 + ) { + // Handle DataSync-style structured error responses: + // { errors: [{ errorCode: "SYN-0008", message: "...", path: "/id" }] } + errorData = errorResponse; + + const errors = errorResponse.errors as Array<{ + errorCode?: string; + message?: string; + path?: string; + }>; + + message = errors + .map((e) => { + const parts: string[] = []; + if (e.errorCode) parts.push(e.errorCode); + if (e.message) parts.push(e.message); + return parts.join(': '); + }) + .join('; '); } else errorData = errorResponse; if ('error' in errorResponse && errorResponse.error instanceof Error) errorData = errorResponse.error; @@ -229,6 +252,35 @@ export class PubNubAPIError extends Error { }; } + /** + * Format a user-facing error message for this API error. + * + * When the error contains structured details extracted from the service response + * (e.g., DataSync `errors` array), those details are included in the message. + * Otherwise, falls back to a generic description. + * + * @param operation - Request operation during which error happened. + * + * @returns Formatted error message string. + */ + public toFormattedMessage(operation: RequestOperation): string { + const fallback = 'REST API request processing error, check status for details'; + + // When errorData contains a structured `errors` array, `this.message` was already + // constructed from it in `createFromServiceResponse` — prefer it over the generic fallback. + if ( + this.errorData && + typeof this.errorData === 'object' && + !('name' in this.errorData && 'message' in this.errorData && 'stack' in this.errorData) && + 'errors' in this.errorData && + Array.isArray((this.errorData as Record).errors) + ) { + return `${operation}: ${this.message}`; + } + + return fallback; + } + /** * Convert API error object to PubNub client error object. *