Skip to content

Fix Node.js 17.5+ JSON import compatibility issue #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
36 changes: 36 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Test

on:
pull_request:
branches: [main]
push:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build
run: yarn build

- name: Run tests
run: yarn test

- name: Test JSON import fix specifically
run: node -e "import('./dist/src/index.js').then(() => console.log('✅ JSON import fix works on Node.js ${{ matrix.node-version }}'))"
71 changes: 71 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Important Rule
**ALWAYS UPDATE CLAUDE.md**: Whenever you make meaningful changes to the codebase, build process, architecture, dependencies, or fix issues, you MUST update this CLAUDE.md file to reflect those changes. This ensures future Claude sessions have accurate context about the project state.

## Project Overview

This is the JavaScript SDK for RunPod, a serverless computing platform. The SDK provides a client interface for interacting with RunPod endpoints, allowing users to run inference tasks, check status, stream results, and manage requests.

## Build and Development Commands

- **Build**: `npm run build` - Compiles TypeScript to JavaScript in `dist/` directory
- **Testing**: No test scripts are defined in package.json. Check examples in `examples/` directory for testing patterns
- **Development**: Use `tsc` directly for TypeScript compilation during development

## Architecture

### Core Structure

- **Single File SDK**: The entire SDK is contained in `src/index.ts` - a monolithic approach with all functionality in one file
- **Functional + Class-based**: Mix of curried functional programming (using Ramda) and traditional class-based architecture
- **HTTP Client**: Uses `xior` (axios-like library) for HTTP requests

### Key Components

1. **RunpodSdk Class**: Main entry point that accepts API key and creates endpoint instances
2. **Endpoint Class**: Wraps all endpoint-specific operations (run, status, stream, cancel, health, purge)
3. **Functional Wrappers**: Each API operation has both a curried functional version and class method

### API Operations

- `run()` - Async execution (returns immediately with request ID)
- `runSync()` - Synchronous execution (waits for completion with polling)
- `status()` - Check single request status
- `statusSync()` - Long-polling status check with configurable wait time
- `stream()` - Async generator for streaming results
- `cancel()` - Cancel pending requests
- `health()` - Check endpoint worker health
- `purgeQueue()` - Clear pending requests

### Environment Configuration

- **Production**: `https://api.runpod.ai/v2` (default)
- **Development**: `https://dev-api.runpod.ai/v2`
- Configurable via `SdkOptions.baseUrl`

### TypeScript Configuration

- Target: ES2020 with DOM lib support for Node.js compatibility
- Strict mode enabled
- Outputs to `dist/` with declarations and source maps
- Uses ES modules (`"type": "module"` in package.json)
- Includes Node.js types for `createRequire` usage

## Key Dependencies

- `xior`: HTTP client (axios alternative)
- `ramda`: Functional programming utilities (curry, clamp, isNil)
- `@types/ramda`: TypeScript definitions
- `@types/node`: Node.js TypeScript definitions (dev dependency)

## Development Notes

- JSON imports use `createRequire` pattern to avoid Node.js 17.5+ ESM import assertion errors
- All timeout parameters use milliseconds
- Status polling uses exponential backoff with configurable wait times
- Error handling returns status objects rather than throwing exceptions
- User agent automatically includes SDK version and environment info
- Version 1.1.2 fixes Node.js 17.5+ compatibility issues with JSON imports
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "runpod-sdk",
"version": "1.0.7",
"version": "1.1.2",
"description": "JavaScript SDK for Runpod",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand All @@ -11,11 +11,14 @@
"xior": "^0.1.4"
},
"devDependencies": {
"@types/node": "^20.0.0",
"@types/ramda": "^0.29.7",
"dotenv": "^16.3.1",
"typescript": "^5.2.2"
"typescript": "^5.2.2",
"vitest": "^1.0.0"
},
"scripts": {
"build": "tsc"
"build": "tsc",
"test": "vitest run"
}
}
5 changes: 4 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import xior, { XiorResponse as AxiosResponse } from "xior"
import { curry, clamp, isNil } from "ramda"
import pkg from "../package.json"
import { createRequire } from "module"

const require = createRequire(import.meta.url)
const pkg = require("../../package.json")

const axios = xior.create();

Expand Down
31 changes: 31 additions & 0 deletions test/json-import.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, it, expect } from "vitest"
import runpodSdk from "../dist/src/index.js"

describe("JSON import fix (Node.js 17.5+ compatibility)", () => {
it("should import SDK without ERR_IMPORT_ATTRIBUTE_MISSING error", () => {
// This test validates our fix for the Discord issue:
// TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module needs an import attribute of "type: json"
//
// Before fix: import pkg from "../package.json" -> FAILS in Node.js 17.5+
// After fix: createRequire pattern -> WORKS in all Node.js versions
//
// If this test passes, the createRequire fix is working.
// If it fails, it means the JSON import is broken again.

expect(() => {
const sdk = runpodSdk("test-api-key")
expect(sdk).toBeDefined()
}).not.toThrow()
})

it("should successfully load package.json version for User-Agent", () => {
// The SDK loads package.json to get version
// This was the specific line that caused the JSON import error
const sdk = runpodSdk("test-api-key")
const endpoint = sdk.endpoint("test-endpoint")

// If package.json loading failed, endpoint creation would fail
expect(endpoint).toBeDefined()
expect(endpoint?.endpointId).toBe("test-endpoint")
})
})
9 changes: 5 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
{
"compilerOptions": {
"target": "es5",
"module": "ES6",
"target": "ES2020",
"module": "ES2020",
"outDir": "./dist",
"rootDir": ".",
"moduleResolution": "node",
"lib": ["ES2022", "DOM"],
"lib": ["ES2020", "DOM"],
"strict": true,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
"resolveJsonModule": true
"resolveJsonModule": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}
Loading