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
100 changes: 97 additions & 3 deletions src/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,24 @@ describe('StarbaseDB Middleware & Request Handling', () => {
})

describe('StarbaseDB Query Execution', () => {
it('should reject query requests without JSON content type', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
body: 'SELECT * FROM users',
headers: { 'Content-Type': 'text/plain' },
})

const response = await instance.queryRoute(request, false)

expect(createResponse).toHaveBeenCalledWith(
undefined,
'Content-Type must be application/json.',
400
)
expect(response.status).toBe(400)
expect(executeQuery).not.toHaveBeenCalled()
})

it('should execute a valid SQL query', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
Expand Down Expand Up @@ -154,20 +172,96 @@ describe('StarbaseDB Query Execution', () => {
expect(response.status).toBe(400)
})

it('should execute a SQL transaction', async () => {
it('should reject invalid query params', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
body: JSON.stringify({
transaction: [{ sql: "INSERT INTO users VALUES (1, 'Alice')" }],
sql: 'SELECT * FROM users WHERE id = ?',
params: '1',
}),
headers: { 'Content-Type': 'application/json' },
})

const response = await instance.queryRoute(request, false)

expect(executeTransaction).toHaveBeenCalled()
expect(createResponse).toHaveBeenCalledWith(
undefined,
'Invalid "params" field. Must be an array or object.',
400
)
expect(response.status).toBe(400)
expect(executeQuery).not.toHaveBeenCalled()
})

it('should execute a SQL transaction', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
body: JSON.stringify({
transaction: [
{
sql: "INSERT INTO users VALUES (?, 'Alice')",
params: [1],
},
],
}),
headers: { 'Content-Type': 'application/json' },
})

const response = await instance.queryRoute(request, true)

expect(executeTransaction).toHaveBeenCalledWith({
queries: [
{
sql: "INSERT INTO users VALUES (?, 'Alice')",
params: [1],
},
],
isRaw: true,
dataSource: mockDataSource,
config: mockConfig,
})
expect(response.status).toBe(200)
})

it('should reject transactions with an empty SQL statement', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
body: JSON.stringify({
transaction: [{ sql: ' ' }],
}),
headers: { 'Content-Type': 'application/json' },
})

const response = await instance.queryRoute(request, false)

expect(createResponse).toHaveBeenCalledWith(
undefined,
'Invalid or empty "sql" field in transaction.',
400
)
expect(response.status).toBe(400)
expect(executeTransaction).not.toHaveBeenCalled()
})

it('should reject transactions with invalid params', async () => {
const request = new Request('https://example.com/query', {
method: 'POST',
body: JSON.stringify({
transaction: [{ sql: 'SELECT * FROM users', params: 'bad' }],
}),
headers: { 'Content-Type': 'application/json' },
})

const response = await instance.queryRoute(request, false)

expect(createResponse).toHaveBeenCalledWith(
undefined,
'Invalid "params" field in transaction. Must be an array or object.',
400
)
expect(response.status).toBe(400)
expect(executeTransaction).not.toHaveBeenCalled()
})
})

describe('StarbaseDB Cache Expiry', () => {
Expand Down
20 changes: 13 additions & 7 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,25 +316,31 @@ export class StarbaseDB {
(await request.json()) as QueryRequest & QueryTransactionRequest

if (Array.isArray(transaction) && transaction.length) {
const queries = transaction.map((queryObj: any) => {
const queries = []

for (const queryObj of transaction) {
const { sql, params } = queryObj

if (typeof sql !== 'string' || !sql.trim()) {
throw new Error(
'Invalid or empty "sql" field in transaction.'
return createResponse(
undefined,
'Invalid or empty "sql" field in transaction.',
400
)
} else if (
params !== undefined &&
!Array.isArray(params) &&
typeof params !== 'object'
) {
throw new Error(
'Invalid "params" field in transaction. Must be an array or object.'
return createResponse(
undefined,
'Invalid "params" field in transaction. Must be an array or object.',
400
)
}

return { sql, params }
})
queries.push({ sql, params })
}

const response = await executeTransaction({
queries,
Expand Down