Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/nine-monkeys-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@codee-sh/medusa-plugin-automations": patch
---

feat: Add throttle support for event triggers
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ yarn-error.log*
.env
.env.local

# Temporary docs (internal)
docs-temp/

Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function AutomationsCreateForm() {
description: "",
trigger_type: "event",
event_name: "",
interval_minutes: null,
interval_seconds: null,
active: false,
},
rules: {
Expand All @@ -104,8 +104,8 @@ export function AutomationsCreateForm() {
// description: trigger.description || "",
// trigger_type: trigger.trigger_type || "event",
// event_name: trigger.event_name || "",
// interval_minutes:
// trigger.interval_minutes || null,
// interval_seconds:
// trigger.interval_seconds || null,
// active: trigger.active || false,
// },
// rules: {
Expand All @@ -126,7 +126,7 @@ export function AutomationsCreateForm() {
description: "",
trigger_type: "event",
event_name: "",
interval_minutes: null,
interval_seconds: null,
active: false,
},
rules: {
Expand All @@ -146,7 +146,7 @@ export function AutomationsCreateForm() {
description: data.general.description,
trigger_type: data.general.trigger_type,
event_name: data.general.event_name,
interval_minutes: data.general.interval_minutes,
interval_seconds: data.general.interval_seconds,
active: data.general.active,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export function AutomationsEditForm({
description: "",
trigger_type: "event",
event_name: "",
interval_minutes: null,
interval_seconds: null,
active: false,
},
rules: {
Expand Down Expand Up @@ -154,8 +154,8 @@ export function AutomationsEditForm({
description: trigger.description || "",
trigger_type: trigger.trigger_type || "event",
event_name: trigger.event_name || "",
interval_minutes:
trigger.interval_minutes || null,
interval_seconds:
trigger.interval_seconds || null,
active: trigger.active || false,
},
rules: {
Expand Down Expand Up @@ -202,7 +202,7 @@ export function AutomationsEditForm({
description: "",
trigger_type: "event",
event_name: "",
interval_minutes: null,
interval_seconds: null,
active: false,
},
rules: {
Expand All @@ -223,7 +223,7 @@ export function AutomationsEditForm({
description: data.general.description,
trigger_type: data.general.trigger_type,
event_name: data.general.event_name,
interval_minutes: data.general.interval_minutes,
interval_seconds: data.general.interval_seconds,
active: data.general.active,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import {
Label,
Select,
Checkbox,
Text,
} from "@medusajs/ui"
import { useAvailableEvents } from "../../../../hooks/api/available-events"
import { useAvailableTriggers } from "../../../../hooks/api/available-triggers"
import { useAvailableActions } from "../../../../hooks/api/available-actions"
import { Controller } from "react-hook-form"
import { Controller, useWatch } from "react-hook-form"
import { useMemo } from "react"

export function AutomationsGeneralForm({
Expand Down Expand Up @@ -52,6 +53,16 @@ export function AutomationsGeneralForm({
return availableActionsData?.actions || []
}, [availableActionsData])

// Watch trigger_type to show/hide interval_seconds field
const triggerType = useWatch({
control: form.control,
name: "general.trigger_type",
})

// Show interval field for event and schedule types
const showIntervalField =
triggerType === "event" || triggerType === "schedule"

return (
<div className="w-full">
<div className="p-6 max-w-2xl mx-auto">
Expand Down Expand Up @@ -223,6 +234,58 @@ export function AutomationsGeneralForm({
)}
/>
</div>
{showIntervalField && (
<div className="flex flex-col gap-2">
<Label
htmlFor="interval_seconds"
className="block"
>
{triggerType === "schedule"
? "Interval (seconds)"
: "Throttle (seconds)"}
</Label>
<Controller
name="general.interval_seconds"
control={form.control}
render={({ field, fieldState }) => (
<>
<Input
{...field}
type="number"
min={0}
placeholder={
triggerType === "schedule"
? "Run every X seconds"
: "Minimum seconds between executions"
}
value={field.value ?? ""}
onChange={(e) => {
const value = e.target.value
field.onChange(
value === ""
? null
: Number(value)
)
}}
/>
<Text
size="small"
className="text-ui-fg-subtle"
>
{triggerType === "schedule"
? "How often to run this automation"
: "Optional: Limit how often this automation can run for the same target (e.g., 3600 = max once per hour)"}
</Text>
{fieldState.error && (
<span className="text-red-500 text-sm">
{fieldState.error.message}
</span>
)}
</>
)}
/>
</div>
)}
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/admin/automations/automations-form/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const baseAutomationFormSchema = z.object({
.min(3, "Description must be at least 3 characters"),
trigger_type: z.enum(["event", "schedule", "manual"]),
event_name: z.string().min(1, "Event name is required"),
interval_minutes: z.number().nullable(),
interval_seconds: z.number().nullable(),
active: z.boolean(),
}),
rules: z
Expand Down
2 changes: 1 addition & 1 deletion src/api/middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export default defineMiddlewares({
"trigger_id",
"trigger_type",
"event_name",
"interval_minutes",
"interval_seconds",
"channels",
"metadata",
"active",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
"nullable": true,
"mappedType": "text"
},
"interval_minutes": {
"name": "interval_minutes",
"interval_seconds": {
"name": "interval_seconds",
"type": "integer",
"unsigned": false,
"autoincrement": false,
Expand Down
15 changes: 15 additions & 0 deletions src/modules/mpn-automation/migrations/Migration20251222121805.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Migration } from "@mikro-orm/migrations"

export class Migration20251222121805 extends Migration {
override async up(): Promise<void> {
this.addSql(
`alter table if exists "mpn_automation_trigger" rename column "interval_minutes" to "interval_seconds";`
)
}

override async down(): Promise<void> {
this.addSql(
`alter table if exists "mpn_automation_trigger" rename column "interval_seconds" to "interval_minutes";`
)
}
}
4 changes: 2 additions & 2 deletions src/modules/mpn-automation/models/mpn_automation_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export const MpnAutomationTrigger = model
// Event name — only when trigger_type = "event"
event_name: model.text().nullable(),

// Interval in minutes — only when trigger_type = "schedule"
interval_minutes: model.number().nullable(),
// Interval in seconds — only when trigger_type = "schedule"
interval_seconds: model.number().nullable(),

// Whether the trigger is enabled
active: model.boolean().default(true),
Expand Down
2 changes: 1 addition & 1 deletion src/modules/mpn-automation/types/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface AutomationTrigger {
description: string | null
trigger_type: TriggerType
event_name: string | null
interval_minutes: number | null
interval_seconds: number | null
active: boolean
channels: Record<string, boolean> | null
metadata: Record<string, any> | null
Expand Down
2 changes: 1 addition & 1 deletion src/workflows/mpn-automation/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from "./validate-automation-triggers-by-event"
export * from "./validate-triggers-by-event"
export * from "./run-automation"
export * from "./run-email-action"
export * from "./run-slack-action"
Expand Down
Loading