Skip to content
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
2 changes: 1 addition & 1 deletion .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
npx --no-install commitlint --edit $1 || {
./node_modules/.bin/commitlint --edit "$1" || {
echo ""
echo "πŸ’‘ Tip: Use 'npm run commit' for guided commits!"
echo ""
Expand Down
2 changes: 1 addition & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Check code formatting
echo "πŸ” Checking code formatting..."
npx nx format:check --verbose
./node_modules/.bin/nx format:check --verbose

echo "βœ… Code formatting check passed"

Expand Down
21 changes: 19 additions & 2 deletions packages/core/postgrest-js/src/PostgrestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,27 @@ export default abstract class PostgrestBuilder<
// NOTE: Invoke w/o `this` to avoid illegal invocation error.
// https://github.com/supabase/postgrest-js/pull/247
const _fetch = this.fetch

const headers: Record<string, string> = {}
this.headers.forEach((value, key) => {
headers[key] = value
})

let body
if (
(this.body === undefined || this.body === null) &&
this.method !== 'GET' &&
this.method !== 'HEAD'
) {
body = '{}'
} else {
body = JSON.stringify(this.body)
}

let res = _fetch(this.url.toString(), {
method: this.method,
headers: this.headers,
body: JSON.stringify(this.body),
headers,
body,
signal: this.signal,
}).then(async (res) => {
let error = null
Expand Down
52 changes: 52 additions & 0 deletions packages/core/postgrest-js/test/headers_serialization.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { PostgrestClient } from '../src/index'

const REST_URL = 'http://localhost:3000'

test('fetch receives headers as plain object', async () => {
const mockFetch = jest.fn().mockResolvedValue({
ok: true,
status: 200,
statusText: 'OK',
text: async () => '{}',
headers: new Headers(),
})

const client = new PostgrestClient(REST_URL, {
fetch: mockFetch as any,
headers: { 'X-Custom-Header': 'CustomValue' },
})

await client.rpc('test_func')

expect(mockFetch).toHaveBeenCalledTimes(1)
const args = mockFetch.mock.calls[0]
const options = args[1]

// Verify headers is a plain object and contains expected values
expect(options.headers).not.toBeInstanceOf(Headers)
expect(Object.getPrototypeOf(options.headers)).toBe(Object.prototype)
expect(options.headers['x-custom-header']).toBe('CustomValue')
expect(options.headers['content-type']).toBe('application/json')
})

test('rpc without params sends empty json body', async () => {
const mockFetch = jest.fn().mockResolvedValue({
ok: true,
status: 200,
statusText: 'OK',
text: async () => '{}',
headers: new Headers(),
})

const client = new PostgrestClient(REST_URL, {
fetch: mockFetch as any,
})

await client.rpc('test_func')

expect(mockFetch).toHaveBeenCalledTimes(1)
const args = mockFetch.mock.calls[0]
const options = args[1]

expect(options.body).toBe('{}')
})