fix(workflow-engine-*): q text search (#12435)
This commit is contained in:
@@ -0,0 +1,94 @@
|
|||||||
|
import {
|
||||||
|
createStep,
|
||||||
|
createWorkflow,
|
||||||
|
StepResponse,
|
||||||
|
WorkflowData,
|
||||||
|
WorkflowResponse,
|
||||||
|
} from "@medusajs/framework/workflows-sdk"
|
||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { Modules } from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
adminHeaders,
|
||||||
|
createAdminUser,
|
||||||
|
} from "../../../../helpers/create-admin-user"
|
||||||
|
|
||||||
|
jest.setTimeout(300000)
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||||
|
let container
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
container = getContainer()
|
||||||
|
await createAdminUser(dbConnection, adminHeaders, container)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /admin/workflow-executions", () => {
|
||||||
|
it("should filter using q", async () => {
|
||||||
|
const step1 = createStep(
|
||||||
|
{
|
||||||
|
name: "my-step",
|
||||||
|
},
|
||||||
|
async (_) => {
|
||||||
|
return new StepResponse({ result: "success" })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const workflowName = "workflow-admin/workflow-executions"
|
||||||
|
createWorkflow(
|
||||||
|
{
|
||||||
|
name: workflowName,
|
||||||
|
retentionTime: 50,
|
||||||
|
},
|
||||||
|
function (input: WorkflowData<{ initial: string }>) {
|
||||||
|
const stepRes = step1()
|
||||||
|
|
||||||
|
return new WorkflowResponse(stepRes)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const engine = container.resolve(Modules.WORKFLOW_ENGINE)
|
||||||
|
|
||||||
|
const transactionId = "test-transaction-id"
|
||||||
|
await engine.run(workflowName, {
|
||||||
|
transactionId,
|
||||||
|
input: {
|
||||||
|
initial: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const transactionId2 = "unknown"
|
||||||
|
await engine.run(workflowName, {
|
||||||
|
transactionId: transactionId2,
|
||||||
|
input: {
|
||||||
|
initial: "test",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const q = "transaction-id"
|
||||||
|
const response = await api.get(
|
||||||
|
`/admin/workflows-executions?q=${q}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.workflow_executions.length).toEqual(1)
|
||||||
|
expect(response.data.workflow_executions[0].transaction_id).toEqual(
|
||||||
|
transactionId
|
||||||
|
)
|
||||||
|
|
||||||
|
const q2 = "known"
|
||||||
|
const response2 = await api.get(
|
||||||
|
`/admin/workflows-executions?q=${q2}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response2.status).toEqual(200)
|
||||||
|
expect(response2.data.workflow_executions.length).toEqual(1)
|
||||||
|
expect(response2.data.workflow_executions[0].transaction_id).toEqual(
|
||||||
|
transactionId2
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { FindParams } from "../../common"
|
import { FindParams } from "../../common"
|
||||||
|
|
||||||
export interface AdminGetWorkflowExecutionsParams extends FindParams {
|
export interface AdminGetWorkflowExecutionsParams extends FindParams {
|
||||||
|
/**
|
||||||
|
* Filter using a search query.
|
||||||
|
*/
|
||||||
|
q?: string
|
||||||
/**
|
/**
|
||||||
* Filter by the ID of the transaction to retrieve workflow executions for a specific transaction.
|
* Filter by the ID of the transaction to retrieve workflow executions for a specific transaction.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import { BaseFilterable, OperatorMap } from "../dal"
|
import { BaseFilterable, OperatorMap } from "../dal"
|
||||||
|
import { TransactionState } from "../http"
|
||||||
export interface WorkflowExecutionDTO {
|
export interface WorkflowExecutionDTO {
|
||||||
id: string
|
id: string
|
||||||
workflow_id: string
|
workflow_id: string
|
||||||
transaction_id: string
|
transaction_id: string
|
||||||
execution: string
|
execution: Record<string, any> | null
|
||||||
context: string
|
context: Record<string, any> | null
|
||||||
state: any
|
state: TransactionState
|
||||||
created_at: Date
|
created_at: Date
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
deleted_at: Date
|
deleted_at: Date | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FilterableWorkflowExecutionProps
|
export interface FilterableWorkflowExecutionProps
|
||||||
extends BaseFilterable<FilterableWorkflowExecutionProps> {
|
extends BaseFilterable<FilterableWorkflowExecutionProps> {
|
||||||
|
q?: string
|
||||||
id?: string | string[] | OperatorMap<string>
|
id?: string | string[] | OperatorMap<string>
|
||||||
workflow_id?: string | string[] | OperatorMap<string>
|
workflow_id?: string | string[] | OperatorMap<string>
|
||||||
transaction_id?: string | string[] | OperatorMap<string>
|
transaction_id?: string | string[] | OperatorMap<string>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const AdminGetWorkflowExecutionsParams = createFindParams({
|
|||||||
limit: 100,
|
limit: 100,
|
||||||
}).merge(
|
}).merge(
|
||||||
z.object({
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
transaction_id: z.union([z.string(), z.array(z.string())]).optional(),
|
transaction_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
workflow_id: z.union([z.string(), z.array(z.string())]).optional(),
|
workflow_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
Context,
|
Context,
|
||||||
DAL,
|
DAL,
|
||||||
|
FilterableWorkflowExecutionProps,
|
||||||
|
FindConfig,
|
||||||
InferEntityType,
|
InferEntityType,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
ModulesSdkTypes,
|
ModulesSdkTypes,
|
||||||
|
WorkflowExecutionDTO,
|
||||||
WorkflowsSdkTypes,
|
WorkflowsSdkTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
InjectManager,
|
||||||
InjectSharedContext,
|
InjectSharedContext,
|
||||||
isDefined,
|
isDefined,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
@@ -74,6 +78,68 @@ export class WorkflowsModuleService<
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static prepareFilters<T>(filters: T & { q?: string }) {
|
||||||
|
const filters_ = { ...filters } // shallow copy
|
||||||
|
if (filters_?.q) {
|
||||||
|
const q = filters_.q
|
||||||
|
delete filters_.q
|
||||||
|
|
||||||
|
const textSearch = { $ilike: `%${q}%` }
|
||||||
|
const textSearchFilters = {
|
||||||
|
$or: [
|
||||||
|
{
|
||||||
|
transaction_id: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workflow_id: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
execution: {
|
||||||
|
runId: textSearch,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(filters_).length) {
|
||||||
|
return textSearchFilters
|
||||||
|
} else {
|
||||||
|
return { $and: [filters, textSearchFilters] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager()
|
||||||
|
// @ts-expect-error
|
||||||
|
async listWorkflowExecutions(
|
||||||
|
filters: FilterableWorkflowExecutionProps = {},
|
||||||
|
config?: FindConfig<WorkflowExecutionDTO>,
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
) {
|
||||||
|
const filters_ = WorkflowsModuleService.prepareFilters(filters)
|
||||||
|
return await super.listWorkflowExecutions(filters_, config, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager()
|
||||||
|
// @ts-expect-error
|
||||||
|
async listAndCountWorkflowExecutions(
|
||||||
|
filters: FilterableWorkflowExecutionProps = {},
|
||||||
|
config?: FindConfig<WorkflowExecutionDTO>,
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
) {
|
||||||
|
const filters_ = WorkflowsModuleService.prepareFilters(filters)
|
||||||
|
return await super.listAndCountWorkflowExecutions(
|
||||||
|
filters_,
|
||||||
|
config,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@InjectSharedContext()
|
@InjectSharedContext()
|
||||||
async run<TWorkflow extends string | ReturnWorkflow<any, any, any>>(
|
async run<TWorkflow extends string | ReturnWorkflow<any, any, any>>(
|
||||||
workflowIdOrWorkflow: TWorkflow,
|
workflowIdOrWorkflow: TWorkflow,
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
Context,
|
Context,
|
||||||
DAL,
|
DAL,
|
||||||
|
FilterableWorkflowExecutionProps,
|
||||||
|
FindConfig,
|
||||||
InferEntityType,
|
InferEntityType,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
ModulesSdkTypes,
|
ModulesSdkTypes,
|
||||||
|
WorkflowExecutionDTO,
|
||||||
WorkflowsSdkTypes,
|
WorkflowsSdkTypes,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
|
InjectManager,
|
||||||
InjectSharedContext,
|
InjectSharedContext,
|
||||||
isDefined,
|
isDefined,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
@@ -86,6 +90,68 @@ export class WorkflowsModuleService<
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static prepareFilters<T>(filters: T & { q?: string }) {
|
||||||
|
const filters_ = { ...filters } // shallow copy
|
||||||
|
if (filters_?.q) {
|
||||||
|
const q = filters_.q
|
||||||
|
delete filters_.q
|
||||||
|
|
||||||
|
const textSearch = { $ilike: `%${q}%` }
|
||||||
|
const textSearchFilters = {
|
||||||
|
$or: [
|
||||||
|
{
|
||||||
|
transaction_id: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workflow_id: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: textSearch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
execution: {
|
||||||
|
runId: textSearch,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(filters_).length) {
|
||||||
|
return textSearchFilters
|
||||||
|
} else {
|
||||||
|
return { $and: [filters, textSearchFilters] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager()
|
||||||
|
// @ts-expect-error
|
||||||
|
async listWorkflowExecutions(
|
||||||
|
filters: FilterableWorkflowExecutionProps = {},
|
||||||
|
config?: FindConfig<WorkflowExecutionDTO>,
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
) {
|
||||||
|
const filters_ = WorkflowsModuleService.prepareFilters(filters)
|
||||||
|
return await super.listWorkflowExecutions(filters_, config, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager()
|
||||||
|
// @ts-expect-error
|
||||||
|
async listAndCountWorkflowExecutions(
|
||||||
|
filters: FilterableWorkflowExecutionProps = {},
|
||||||
|
config?: FindConfig<WorkflowExecutionDTO>,
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
) {
|
||||||
|
const filters_ = WorkflowsModuleService.prepareFilters(filters)
|
||||||
|
return await super.listAndCountWorkflowExecutions(
|
||||||
|
filters_,
|
||||||
|
config,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@InjectSharedContext()
|
@InjectSharedContext()
|
||||||
async run<TWorkflow extends string | ReturnWorkflow<any, any, any>>(
|
async run<TWorkflow extends string | ReturnWorkflow<any, any, any>>(
|
||||||
workflowIdOrWorkflow: TWorkflow,
|
workflowIdOrWorkflow: TWorkflow,
|
||||||
|
|||||||
Reference in New Issue
Block a user