Query API typing.

This commit is contained in:
mike12345567 2024-12-03 17:29:41 +00:00
parent 3446b1c678
commit 23d9808cb6
8 changed files with 104 additions and 55 deletions

View File

@ -4,26 +4,38 @@ import { save as saveDatasource } from "../datasource"
import { RestImporter } from "./import"
import { invalidateCachedVariable } from "../../../threads/utils"
import env from "../../../environment"
import { events, context, utils, constants } from "@budibase/backend-core"
import { constants, context, events, utils } from "@budibase/backend-core"
import sdk from "../../../sdk"
import { QueryEvent, QueryEventParameters } from "../../../threads/definitions"
import {
ConfigType,
Query,
UserCtx,
SessionCookie,
JsonFieldSubType,
QueryResponse,
QuerySchema,
FieldType,
CreateDatasourceRequest,
Datasource,
ExecuteQueryRequest,
ExecuteQueryResponse,
ExecuteV2QueryResponse,
ExecuteV1QueryResponse,
FetchQueriesResponse,
FieldType,
FindQueryResponse,
ImportRestQueryRequest,
ImportRestQueryResponse,
JsonFieldSubType,
PreviewQueryRequest,
PreviewQueryResponse,
Query,
QueryResponse,
QuerySchema,
SaveQueryRequest,
SaveQueryResponse,
SessionCookie,
SourceName,
UserCtx,
DeleteQueryResponse,
} from "@budibase/types"
import { ValidQueryNameRegex, utils as JsonUtils } from "@budibase/shared-core"
import { utils as JsonUtils, ValidQueryNameRegex } from "@budibase/shared-core"
import { findHBSBlocks } from "@budibase/string-templates"
import { ObjectId } from "mongodb"
import { merge } from "lodash"
const Runner = new Thread(ThreadType.QUERY, {
timeoutMs: env.QUERY_THREAD_TIMEOUT,
@ -43,11 +55,13 @@ function validateQueryInputs(parameters: QueryEventParameters) {
}
}
export async function fetch(ctx: UserCtx) {
export async function fetch(ctx: UserCtx<void, FetchQueriesResponse>) {
ctx.body = await sdk.queries.fetch()
}
const _import = async (ctx: UserCtx) => {
const _import = async (
ctx: UserCtx<ImportRestQueryRequest, ImportRestQueryResponse>
) => {
const body = ctx.request.body
const data = body.data
@ -58,9 +72,9 @@ const _import = async (ctx: UserCtx) => {
if (!body.datasourceId) {
// construct new datasource
const info: any = await importer.getInfo()
let datasource = {
let datasource: Datasource = {
type: "datasource",
source: "REST",
source: SourceName.REST,
config: {
url: info.url,
defaultHeaders: [],
@ -69,8 +83,14 @@ const _import = async (ctx: UserCtx) => {
name: info.name,
}
// save the datasource
const datasourceCtx = { ...ctx }
datasourceCtx.request.body.datasource = datasource
const datasourceCtx: UserCtx<CreateDatasourceRequest> = merge(ctx, {
request: {
body: {
datasource,
tablesFilter: [],
},
},
})
await saveDatasource(datasourceCtx)
datasourceId = datasourceCtx.body.datasource._id
} else {
@ -88,7 +108,7 @@ const _import = async (ctx: UserCtx) => {
}
export { _import as import }
export async function save(ctx: UserCtx<Query, Query>) {
export async function save(ctx: UserCtx<SaveQueryRequest, SaveQueryResponse>) {
const db = context.getAppDB()
const query: Query = ctx.request.body
@ -119,10 +139,9 @@ export async function save(ctx: UserCtx<Query, Query>) {
query._rev = response.rev
ctx.body = query
ctx.message = `Query ${query.name} saved successfully.`
}
export async function find(ctx: UserCtx) {
export async function find(ctx: UserCtx<void, FindQueryResponse>) {
const queryId = ctx.params.queryId
ctx.body = await sdk.queries.find(queryId)
}
@ -335,7 +354,7 @@ export async function preview(
async function execute(
ctx: UserCtx<
ExecuteQueryRequest,
ExecuteQueryResponse | Record<string, any>[]
ExecuteV2QueryResponse | ExecuteV1QueryResponse
>,
opts: any = { rowsOnly: false, isAutomation: false }
) {
@ -390,19 +409,21 @@ async function execute(
}
export async function executeV1(
ctx: UserCtx<ExecuteQueryRequest, Record<string, any>[]>
ctx: UserCtx<ExecuteQueryRequest, ExecuteV1QueryResponse>
) {
return execute(ctx, { rowsOnly: true, isAutomation: false })
}
export async function executeV2(
ctx: UserCtx<
ExecuteQueryRequest,
ExecuteQueryResponse | Record<string, any>[]
>,
{ isAutomation }: { isAutomation?: boolean } = {}
ctx: UserCtx<ExecuteQueryRequest, ExecuteV2QueryResponse>
) {
return execute(ctx, { rowsOnly: false, isAutomation })
return execute(ctx, { rowsOnly: false })
}
export async function executeV2AsAutomation(
ctx: UserCtx<ExecuteQueryRequest, ExecuteV2QueryResponse>
) {
return execute(ctx, { rowsOnly: false, isAutomation: true })
}
const removeDynamicVariables = async (queryId: string) => {
@ -426,14 +447,14 @@ const removeDynamicVariables = async (queryId: string) => {
}
}
export async function destroy(ctx: UserCtx) {
export async function destroy(ctx: UserCtx<void, DeleteQueryResponse>) {
const db = context.getAppDB()
const queryId = ctx.params.queryId as string
await removeDynamicVariables(queryId)
const query = await db.get<Query>(queryId)
const datasource = await sdk.datasources.get(query.datasourceId)
await db.remove(ctx.params.queryId, ctx.params.revId)
ctx.message = `Query deleted.`
ctx.body = { message: `Query deleted.` }
ctx.status = 200
await events.query.deleted(datasource, query)
}

View File

@ -56,7 +56,7 @@ router
"/api/v2/queries/:queryId",
paramResource("queryId"),
authorized(PermissionType.QUERY, PermissionLevel.WRITE),
queryController.executeV2 as any
queryController.executeV2
)
export default router

View File

@ -12,6 +12,7 @@ import {
ExecuteQueryStepInputs,
ExecuteQueryStepOutputs,
} from "@budibase/types"
import { executeV2AsAutomation } from "../../api/controllers/query"
export const definition: AutomationStepDefinition = {
name: "External Data Connector",
@ -94,7 +95,7 @@ export async function run({
})
try {
await queryController.executeV2(ctx, { isAutomation: true })
await queryController.executeV2AsAutomation(ctx)
const { data, ...rest } = ctx.body
return {

View File

@ -1,7 +1,7 @@
import {
Query,
ExecuteQueryRequest,
ExecuteQueryResponse,
ExecuteV2QueryResponse,
PreviewQueryRequest,
PreviewQueryResponse,
} from "@budibase/types"
@ -17,8 +17,8 @@ export class QueryAPI extends TestAPI {
queryId: string,
body?: ExecuteQueryRequest,
expectations?: Expectations
): Promise<ExecuteQueryResponse> => {
return await this._post<ExecuteQueryResponse>(
): Promise<ExecuteV2QueryResponse> => {
return await this._post<ExecuteV2QueryResponse>(
`/api/v2/queries/${queryId}`,
{
body,

View File

@ -12,3 +12,4 @@ export * from "./automation"
export * from "./component"
export * from "./integration"
export * from "./metadata"
export * from "./query"

View File

@ -0,0 +1,47 @@
import {
Datasource,
Query,
QueryPreview,
QuerySchema,
} from "../../../documents"
export type FetchQueriesResponse = Query[]
export interface SaveQueryRequest extends Query {}
export interface SaveQueryResponse extends Query {}
export interface ImportRestQueryRequest {
datasourceId: string
data: string
datasource: Datasource
}
export interface ImportRestQueryResponse {
errorQueries: Query[]
queries: Query[]
datasourceId: string
}
export interface FindQueryResponse extends Query {}
export interface PreviewQueryRequest extends QueryPreview {}
export interface PreviewQueryResponse {
rows: any[]
nestedSchemaFields: { [key: string]: { [key: string]: string | QuerySchema } }
schema: { [key: string]: string | QuerySchema }
info: any
extra: any
}
export interface ExecuteQueryRequest {
parameters?: Record<string, string>
pagination?: any
}
export type ExecuteV1QueryResponse = Record<string, any>[]
export interface ExecuteV2QueryResponse {
data: Record<string, any>[]
}
export interface DeleteQueryResponse {
message: string
}

View File

@ -13,7 +13,6 @@ export * from "./searchFilter"
export * from "./cookies"
export * from "./automation"
export * from "./layout"
export * from "./query"
export * from "./role"
export * from "./plugins"
export * from "./apikeys"

View File

@ -1,20 +0,0 @@
import { QueryPreview, QuerySchema } from "../../documents"
export interface PreviewQueryRequest extends QueryPreview {}
export interface PreviewQueryResponse {
rows: any[]
nestedSchemaFields: { [key: string]: { [key: string]: string | QuerySchema } }
schema: { [key: string]: string | QuerySchema }
info: any
extra: any
}
export interface ExecuteQueryRequest {
parameters?: Record<string, string>
pagination?: any
}
export interface ExecuteQueryResponse {
data: Record<string, any>[]
}