mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
feat: deploy triggers to prod/staging workspace (#5429)
* add deploy to staging prod option to trigger * remove unused import * handle schedule trigger, fix update fn * Update frontend/src/lib/utils_deployable.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update backend/windmill-common/src/workspaces.rs Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update frontend/src/lib/components/DeployWorkspace.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * update kind name and handle script kind flow for websocket * nits: english wording --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
Vendored
-1
@@ -12,5 +12,4 @@
|
||||
"conventionalCommits.scopes": [
|
||||
"restructring triggers, decoding trigger message on work"
|
||||
],
|
||||
"rust-analyzer.cargo.features": ["mqtt_trigger"]
|
||||
}
|
||||
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "backend",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
@@ -15275,6 +15275,7 @@ components:
|
||||
- resource
|
||||
- variable
|
||||
- secret
|
||||
- trigger
|
||||
|
||||
WorkspaceDefaultScripts:
|
||||
type: object
|
||||
|
||||
@@ -459,7 +459,6 @@ async fn get_settings(
|
||||
.fetch_one(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("getting settings: {e:#}")))?;
|
||||
|
||||
tx.commit().await?;
|
||||
Ok(Json(settings))
|
||||
}
|
||||
@@ -926,7 +925,7 @@ async fn edit_git_sync_config(
|
||||
Ok(format!("Edit git sync config for workspace {}", &w_id))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct EditDeployUIConfig {
|
||||
#[cfg(feature = "enterprise")]
|
||||
deploy_ui_settings: Option<WorkspaceDeploymentUISettings>,
|
||||
@@ -954,7 +953,6 @@ async fn edit_deploy_ui_config(
|
||||
require_admin(is_admin, &username)?;
|
||||
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
let args_for_audit = format!("{:?}", new_config.deploy_ui_settings);
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
|
||||
@@ -27,6 +27,7 @@ pub enum ObjectType {
|
||||
ResourceType,
|
||||
User,
|
||||
Group,
|
||||
Trigger
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import Toggle from './Toggle.svelte'
|
||||
import { emptyString } from '$lib/utils'
|
||||
|
||||
|
||||
$: deployableWorkspaces = $usersWorkspaceStore?.workspaces
|
||||
.map((w) => w.id)
|
||||
.filter((w) => w != $workspaceStore)
|
||||
@@ -21,8 +20,9 @@
|
||||
resources: boolean
|
||||
variables: boolean
|
||||
secrets: boolean
|
||||
triggers: boolean
|
||||
}
|
||||
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret'
|
||||
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret' | 'trigger'
|
||||
|
||||
const all_ok: DeployUITypeMap = {
|
||||
scripts: true,
|
||||
@@ -30,7 +30,8 @@
|
||||
apps: true,
|
||||
resources: true,
|
||||
variables: true,
|
||||
secrets: true
|
||||
secrets: true,
|
||||
triggers: true
|
||||
}
|
||||
|
||||
export let workspaceToDeployTo: string | undefined
|
||||
@@ -41,8 +42,6 @@
|
||||
include_path: [],
|
||||
include_type: all_ok
|
||||
}
|
||||
|
||||
|
||||
function deployUITypeMapToArray(
|
||||
typesMap: DeployUITypeMap,
|
||||
expectedValue: boolean
|
||||
@@ -66,6 +65,9 @@
|
||||
if (typesMap.secrets == expectedValue) {
|
||||
result.push('secret')
|
||||
}
|
||||
if (typesMap.triggers == expectedValue) {
|
||||
result.push('trigger')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -165,18 +167,9 @@
|
||||
</Tooltip></h4
|
||||
>
|
||||
<div class="flex flex-col gap-2 mt-1">
|
||||
<Toggle
|
||||
bind:checked={deployUiSettings.include_type.scripts}
|
||||
options={{ right: 'Scripts' }}
|
||||
/>
|
||||
<Toggle
|
||||
bind:checked={deployUiSettings.include_type.flows}
|
||||
options={{ right: 'Flows' }}
|
||||
/>
|
||||
<Toggle
|
||||
bind:checked={deployUiSettings.include_type.apps}
|
||||
options={{ right: 'Apps' }}
|
||||
/>
|
||||
<Toggle bind:checked={deployUiSettings.include_type.scripts} options={{ right: 'Scripts' }} />
|
||||
<Toggle bind:checked={deployUiSettings.include_type.flows} options={{ right: 'Flows' }} />
|
||||
<Toggle bind:checked={deployUiSettings.include_type.apps} options={{ right: 'Apps' }} />
|
||||
<Toggle
|
||||
bind:checked={deployUiSettings.include_type.resources}
|
||||
options={{ right: 'Resources' }}
|
||||
@@ -198,6 +191,10 @@
|
||||
options={{ left: 'Include secrets' }}
|
||||
/>
|
||||
</div>
|
||||
<Toggle
|
||||
bind:checked={deployUiSettings.include_type.triggers}
|
||||
options={{ right: 'Trigger' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,22 +22,21 @@
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import Badge from './common/badge/Badge.svelte'
|
||||
import DiffDrawer from './DiffDrawer.svelte'
|
||||
import {
|
||||
existsTrigger,
|
||||
getTriggerDependency,
|
||||
getTriggersDeployData,
|
||||
getTriggerValue,
|
||||
type AdditionalInformation,
|
||||
type Kind
|
||||
} from '$lib/utils_deployable'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
type Kind =
|
||||
| 'script'
|
||||
| 'resource'
|
||||
| 'schedule'
|
||||
| 'variable'
|
||||
| 'flow'
|
||||
| 'app'
|
||||
| 'raw_app'
|
||||
| 'resource_type'
|
||||
| 'folder'
|
||||
|
||||
export let kind: Kind
|
||||
export let initialPath: string = ''
|
||||
export let additionalInformation: AdditionalInformation | undefined = undefined
|
||||
export let workspaceToDeployTo: string | undefined = undefined
|
||||
export let hideButton: boolean = false
|
||||
|
||||
@@ -148,6 +147,11 @@
|
||||
}
|
||||
|
||||
return [...recObj(res.value), { kind: 'resource_type', path: res.resource_type }]
|
||||
} else if (kind == 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
return getTriggerDependency(additionalInformation.triggers.kind, path, $workspaceStore!)
|
||||
}
|
||||
throw new Error('Missing trigger information')
|
||||
}
|
||||
return []
|
||||
}
|
||||
@@ -171,60 +175,70 @@
|
||||
}
|
||||
|
||||
async function checkAlreadyExists(kind: Kind, path: string): Promise<boolean> {
|
||||
if (kind == 'flow') {
|
||||
return await FlowService.existsFlowByPath({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'script') {
|
||||
return await ScriptService.existsScriptByPath({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'app') {
|
||||
return await AppService.existsApp({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'raw_app') {
|
||||
return await RawAppService.existsRawApp({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'variable') {
|
||||
return await VariableService.existsVariable({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'resource') {
|
||||
return await ResourceService.existsResource({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'schedule') {
|
||||
return await ScheduleService.existsSchedule({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'resource_type') {
|
||||
return await ResourceService.existsResourceType({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'folder') {
|
||||
let exists = true
|
||||
try {
|
||||
let exists = true
|
||||
try {
|
||||
if (kind == 'flow') {
|
||||
exists = await FlowService.existsFlowByPath({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'script') {
|
||||
exists = await ScriptService.existsScriptByPath({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'app') {
|
||||
exists = await AppService.existsApp({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'raw_app') {
|
||||
exists = await RawAppService.existsRawApp({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'variable') {
|
||||
exists = await VariableService.existsVariable({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'resource') {
|
||||
exists = await ResourceService.existsResource({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'schedule') {
|
||||
exists = await ScheduleService.existsSchedule({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'resource_type') {
|
||||
exists = await ResourceService.existsResourceType({
|
||||
workspace: workspaceToDeployTo!,
|
||||
path: path
|
||||
})
|
||||
} else if (kind == 'folder') {
|
||||
await FolderService.getFolder({
|
||||
workspace: workspaceToDeployTo!,
|
||||
name: path
|
||||
})
|
||||
} catch (e) {
|
||||
exists = false
|
||||
} else if (kind === 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
exists = await existsTrigger(
|
||||
{ workspace: workspaceToDeployTo!, path },
|
||||
additionalInformation.triggers.kind
|
||||
)
|
||||
} else {
|
||||
throw new Error('Missing triggers kind')
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unknown kind ${kind}`)
|
||||
}
|
||||
return exists
|
||||
} else {
|
||||
throw new Error(`Unknown kind ${kind}`)
|
||||
} catch (error) {
|
||||
sendUserToast(error.body ? error.body : error instanceof Error ? error.message : error, true)
|
||||
exists = false
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
const deploymentStatus: Record<
|
||||
@@ -405,6 +419,28 @@
|
||||
name: path
|
||||
}
|
||||
})
|
||||
} else if (kind === 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
const { data, createFn, updateFn } = await getTriggersDeployData(
|
||||
additionalInformation.triggers.kind,
|
||||
path,
|
||||
$workspaceStore!
|
||||
)
|
||||
if (alreadyExists) {
|
||||
await updateFn({
|
||||
path,
|
||||
workspace: workspaceToDeployTo!,
|
||||
requestBody: data
|
||||
} as any)
|
||||
} else {
|
||||
await createFn({
|
||||
workspace: workspaceToDeployTo!,
|
||||
requestBody: data
|
||||
} as any)
|
||||
}
|
||||
} else {
|
||||
throw new Error('Missing triggers kind')
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unknown kind ${kind}`)
|
||||
}
|
||||
@@ -502,6 +538,12 @@
|
||||
return {
|
||||
name: folder.name
|
||||
}
|
||||
} else if (kind == 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
return await getTriggerValue(additionalInformation.triggers.kind, path, workspace)
|
||||
} else {
|
||||
throw new Error(`Missing trigger information`)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unknown kind ${kind}`)
|
||||
}
|
||||
|
||||
@@ -2,16 +2,21 @@
|
||||
import { Button, Drawer } from './common'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import DeployWorkspace from './DeployWorkspace.svelte'
|
||||
|
||||
type Kind = 'script' | 'resource' | 'schedule' | 'variable' | 'flow' | 'app' | 'raw_app'
|
||||
import { type AdditionalInformation, type Kind } from '$lib/utils_deployable'
|
||||
|
||||
let initialPath: string | undefined = undefined
|
||||
let kind: Kind | undefined = undefined
|
||||
|
||||
let drawer: Drawer | undefined = undefined
|
||||
let workspaceToDeployTo: string | undefined = undefined
|
||||
let deployWorkspace: DeployWorkspace | undefined = undefined
|
||||
export async function openDrawer(initialPath_l: string, kind_l: Kind) {
|
||||
let additionalInformation: AdditionalInformation | undefined = undefined
|
||||
|
||||
export async function openDrawer(
|
||||
initialPath_l: string,
|
||||
kind_l: Kind,
|
||||
additionalInformation_l?: AdditionalInformation
|
||||
) {
|
||||
additionalInformation = additionalInformation_l
|
||||
initialPath = initialPath_l
|
||||
kind = kind_l
|
||||
drawer?.openDrawer()
|
||||
@@ -20,11 +25,12 @@
|
||||
|
||||
<Drawer bind:this={drawer} size="900px">
|
||||
<DrawerContent title="Deploy {initialPath}" on:close={drawer.closeDrawer}>
|
||||
{#if kind != undefined && initialPath != undefined}
|
||||
{#if (kind != 'trigger' && kind != undefined && initialPath != undefined) || (kind === 'trigger' && initialPath != undefined && additionalInformation?.triggers != undefined)}
|
||||
<DeployWorkspace
|
||||
hideButton
|
||||
{initialPath}
|
||||
{kind}
|
||||
{additionalInformation}
|
||||
bind:workspaceToDeployTo
|
||||
bind:this={deployWorkspace}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
import { minimatch } from 'minimatch'
|
||||
import type { WorkspaceDeployUISettings } from './gen'
|
||||
import {
|
||||
HttpTriggerService,
|
||||
KafkaTriggerService,
|
||||
MqttTriggerService,
|
||||
NatsTriggerService,
|
||||
PostgresTriggerService,
|
||||
ScheduleService,
|
||||
SqsTriggerService,
|
||||
WebsocketTriggerService,
|
||||
type WorkspaceDeployUISettings
|
||||
} from './gen'
|
||||
import type { TriggerKind } from './components/triggers'
|
||||
|
||||
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret'
|
||||
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret' | 'trigger'
|
||||
|
||||
export type Kind =
|
||||
| 'script'
|
||||
| 'resource'
|
||||
| 'schedule'
|
||||
| 'variable'
|
||||
| 'flow'
|
||||
| 'app'
|
||||
| 'raw_app'
|
||||
| 'resource_type'
|
||||
| 'folder'
|
||||
| 'trigger'
|
||||
|
||||
export const ALL_DEPLOYABLE: WorkspaceDeployUISettings = {
|
||||
include_path: [],
|
||||
include_type: ['script', 'flow', 'app', 'resource', 'variable', 'secret', 'trigger']
|
||||
}
|
||||
|
||||
export type AdditionalInformation = {
|
||||
triggers?: {
|
||||
kind: TriggerKind
|
||||
}
|
||||
}
|
||||
|
||||
export function isDeployable(
|
||||
type: DeployUIType,
|
||||
@@ -27,7 +61,439 @@ export function isDeployable(
|
||||
return true
|
||||
}
|
||||
|
||||
export const ALL_DEPLOYABLE: WorkspaceDeployUISettings = {
|
||||
include_path: [],
|
||||
include_type: ['script', 'flow', 'app', 'resource', 'variable', 'secret']
|
||||
export async function existsTrigger(
|
||||
data: { workspace: string; path: string },
|
||||
triggerKind: TriggerKind
|
||||
) {
|
||||
if (triggerKind === 'routes') {
|
||||
return await HttpTriggerService.existsHttpTrigger(data)
|
||||
} else if (triggerKind === 'kafka') {
|
||||
return await KafkaTriggerService.existsKafkaTrigger(data)
|
||||
} else if (triggerKind === 'mqtt') {
|
||||
return await MqttTriggerService.existsMqttTrigger(data)
|
||||
} else if (triggerKind === 'postgres') {
|
||||
return await PostgresTriggerService.existsPostgresTrigger(data)
|
||||
} else if (triggerKind === 'sqs') {
|
||||
return await SqsTriggerService.existsSqsTrigger(data)
|
||||
} else if (triggerKind === 'websockets') {
|
||||
return await WebsocketTriggerService.existsWebsocketTrigger(data)
|
||||
} else if (triggerKind === 'nats') {
|
||||
return await NatsTriggerService.existsNatsTrigger(data)
|
||||
} else if (triggerKind === 'schedules') {
|
||||
return await ScheduleService.existsSchedule(data)
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unexpected trigger kind ${triggerKind}. Allowed kinds are: routes, kafka, mqtt, postgres, sqs, websockets, nats, schedules.`
|
||||
)
|
||||
}
|
||||
|
||||
export async function getTriggersDeployData(kind: TriggerKind, path: string, workspace: string) {
|
||||
if (kind === 'sqs') {
|
||||
const sqsTrigger = await SqsTriggerService.getSqsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: sqsTrigger,
|
||||
createFn: SqsTriggerService.createSqsTrigger,
|
||||
updateFn: SqsTriggerService.updateSqsTrigger
|
||||
}
|
||||
} else if (kind === 'kafka') {
|
||||
const kafkaTrigger = await KafkaTriggerService.getKafkaTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: kafkaTrigger,
|
||||
createFn: KafkaTriggerService.createKafkaTrigger,
|
||||
updateFn: KafkaTriggerService.updateKafkaTrigger
|
||||
}
|
||||
} else if (kind === 'mqtt') {
|
||||
const mqttTrigger = await MqttTriggerService.getMqttTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: mqttTrigger,
|
||||
createFn: MqttTriggerService.createMqttTrigger,
|
||||
updateFn: MqttTriggerService.updateMqttTrigger
|
||||
}
|
||||
} else if (kind === 'nats') {
|
||||
const natsTrigger = await NatsTriggerService.getNatsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: natsTrigger,
|
||||
createFn: NatsTriggerService.createNatsTrigger,
|
||||
updateFn: NatsTriggerService.updateNatsTrigger
|
||||
}
|
||||
} else if (kind === 'postgres') {
|
||||
const postgresTrigger = await PostgresTriggerService.getPostgresTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: postgresTrigger,
|
||||
createFn: PostgresTriggerService.createPostgresTrigger,
|
||||
updateFn: PostgresTriggerService.updatePostgresTrigger
|
||||
}
|
||||
} else if (kind === 'websockets') {
|
||||
const websocketTrigger = await WebsocketTriggerService.getWebsocketTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: websocketTrigger,
|
||||
createFn: WebsocketTriggerService.createWebsocketTrigger,
|
||||
updateFn: WebsocketTriggerService.updateWebsocketTrigger
|
||||
}
|
||||
} else if (kind === 'routes') {
|
||||
const httpTrigger = await HttpTriggerService.getHttpTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
data: httpTrigger,
|
||||
createFn: HttpTriggerService.createHttpTrigger,
|
||||
updateFn: HttpTriggerService.updateHttpTrigger
|
||||
}
|
||||
} else if (kind === 'schedules') {
|
||||
const schedulesTrigger = await ScheduleService.getSchedule({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
return {
|
||||
data: schedulesTrigger,
|
||||
createFn: ScheduleService.createSchedule,
|
||||
updateFn: ScheduleService.updateSchedule
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected trigger kind got: ${kind}`)
|
||||
}
|
||||
|
||||
export async function getTriggerValue(kind: TriggerKind, path: string, workspace: string) {
|
||||
if (kind === 'sqs') {
|
||||
const { enabled, script_path, is_flow, queue_url, aws_resource_path, message_attributes } =
|
||||
await SqsTriggerService.getSqsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
queue_url,
|
||||
aws_resource_path,
|
||||
message_attributes
|
||||
}
|
||||
} else if (kind === 'kafka') {
|
||||
const { enabled, script_path, is_flow, kafka_resource_path, topics, group_id } =
|
||||
await KafkaTriggerService.getKafkaTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
kafka_resource_path,
|
||||
topics,
|
||||
group_id
|
||||
}
|
||||
} else if (kind === 'mqtt') {
|
||||
const {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
mqtt_resource_path,
|
||||
v3_config,
|
||||
v5_config,
|
||||
client_id,
|
||||
subscribe_topics,
|
||||
client_version
|
||||
} = await MqttTriggerService.getMqttTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
mqtt_resource_path,
|
||||
v3_config,
|
||||
v5_config,
|
||||
client_id,
|
||||
subscribe_topics,
|
||||
client_version
|
||||
}
|
||||
} else if (kind === 'nats') {
|
||||
const {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
nats_resource_path,
|
||||
use_jetstream,
|
||||
stream_name,
|
||||
consumer_name,
|
||||
subjects
|
||||
} = await NatsTriggerService.getNatsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
nats_resource_path,
|
||||
use_jetstream,
|
||||
stream_name,
|
||||
consumer_name,
|
||||
subjects
|
||||
}
|
||||
} else if (kind === 'postgres') {
|
||||
const {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
postgres_resource_path,
|
||||
replication_slot_name,
|
||||
publication_name
|
||||
} = await PostgresTriggerService.getPostgresTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
postgres_resource_path,
|
||||
replication_slot_name,
|
||||
publication_name
|
||||
}
|
||||
} else if (kind === 'websockets') {
|
||||
const {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
url,
|
||||
url_runnable_args,
|
||||
can_return_message,
|
||||
filters,
|
||||
initial_messages
|
||||
} = await WebsocketTriggerService.getWebsocketTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
enabled,
|
||||
script_path,
|
||||
is_flow,
|
||||
url,
|
||||
url_runnable_args,
|
||||
can_return_message,
|
||||
filters,
|
||||
initial_messages
|
||||
}
|
||||
} else if (kind === 'routes') {
|
||||
const {
|
||||
script_path,
|
||||
is_flow,
|
||||
http_method,
|
||||
route_path,
|
||||
static_asset_config,
|
||||
is_async,
|
||||
requires_auth,
|
||||
is_static_website
|
||||
} = await HttpTriggerService.getHttpTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
script_path,
|
||||
is_flow,
|
||||
http_method,
|
||||
route_path,
|
||||
static_asset_config,
|
||||
is_async,
|
||||
requires_auth,
|
||||
is_static_website
|
||||
}
|
||||
} else if (kind === 'schedules') {
|
||||
const {
|
||||
script_path,
|
||||
is_flow,
|
||||
on_failure,
|
||||
schedule,
|
||||
timezone,
|
||||
on_failure_times,
|
||||
on_failure_exact,
|
||||
on_failure_extra_args,
|
||||
on_recovery,
|
||||
on_recovery_times,
|
||||
on_recovery_extra_args,
|
||||
on_success,
|
||||
on_success_extra_args,
|
||||
ws_error_handler_muted,
|
||||
retry,
|
||||
summary,
|
||||
no_flow_overlap,
|
||||
tag,
|
||||
paused_until,
|
||||
cron_version
|
||||
} = await ScheduleService.getSchedule({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
return {
|
||||
script_path,
|
||||
is_flow,
|
||||
on_failure,
|
||||
schedule,
|
||||
timezone,
|
||||
on_failure_times,
|
||||
on_failure_exact,
|
||||
on_failure_extra_args,
|
||||
on_recovery,
|
||||
on_recovery_times,
|
||||
on_recovery_extra_args,
|
||||
on_success,
|
||||
on_success_extra_args,
|
||||
ws_error_handler_muted,
|
||||
retry,
|
||||
summary,
|
||||
no_flow_overlap,
|
||||
tag,
|
||||
paused_until,
|
||||
cron_version
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected trigger kind got: ${kind}`)
|
||||
}
|
||||
|
||||
function retrieveScriptOrFlowKind(path: string, is_flow: boolean): { kind: Kind; path: string } {
|
||||
return {
|
||||
kind: is_flow ? 'flow' : 'script',
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
function retrieveKindsValues({
|
||||
resource_path,
|
||||
script_path,
|
||||
is_flow
|
||||
}: {
|
||||
resource_path?: string
|
||||
script_path: string
|
||||
is_flow: boolean
|
||||
}) {
|
||||
const result: { kind: Kind; path: string }[] = []
|
||||
|
||||
if (resource_path) {
|
||||
result.push({ kind: 'resource', path: resource_path })
|
||||
}
|
||||
result.push(retrieveScriptOrFlowKind(script_path, is_flow))
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getTriggerDependency(kind: TriggerKind, path: string, workspace: string) {
|
||||
let result: { kind: Kind; path: string }[]
|
||||
if (kind === 'sqs') {
|
||||
const { aws_resource_path, script_path, is_flow } = await SqsTriggerService.getSqsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ resource_path: aws_resource_path, script_path, is_flow })
|
||||
} else if (kind === 'kafka') {
|
||||
const { kafka_resource_path, script_path, is_flow } = await KafkaTriggerService.getKafkaTrigger(
|
||||
{
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
}
|
||||
)
|
||||
|
||||
result = retrieveKindsValues({ resource_path: kafka_resource_path, script_path, is_flow })
|
||||
} else if (kind === 'mqtt') {
|
||||
const { mqtt_resource_path, script_path, is_flow } = await MqttTriggerService.getMqttTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ resource_path: mqtt_resource_path, script_path, is_flow })
|
||||
} else if (kind === 'nats') {
|
||||
const { nats_resource_path, script_path, is_flow } = await NatsTriggerService.getNatsTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ resource_path: nats_resource_path, script_path, is_flow })
|
||||
} else if (kind === 'postgres') {
|
||||
const { postgres_resource_path, script_path, is_flow } =
|
||||
await PostgresTriggerService.getPostgresTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ resource_path: postgres_resource_path, script_path, is_flow })
|
||||
} else if (kind === 'websockets') {
|
||||
const { script_path, is_flow, url, initial_messages } =
|
||||
await WebsocketTriggerService.getWebsocketTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ script_path, is_flow })
|
||||
|
||||
const SCRIPT_PREFIX = '$script:'
|
||||
const FLOW_PREFIX = '$flow:'
|
||||
|
||||
if (url.startsWith(SCRIPT_PREFIX))
|
||||
result.push(retrieveScriptOrFlowKind(url.substring(SCRIPT_PREFIX.length), false))
|
||||
else if (url.startsWith(FLOW_PREFIX))
|
||||
result.push(retrieveScriptOrFlowKind(url.substring(FLOW_PREFIX.length), true))
|
||||
|
||||
initial_messages?.map((message) => {
|
||||
if ('runnable_result' in message) {
|
||||
result.push(
|
||||
retrieveScriptOrFlowKind(message.runnable_result.path, message.runnable_result.is_flow)
|
||||
)
|
||||
}
|
||||
})
|
||||
} else if (kind === 'routes') {
|
||||
const { script_path, is_flow } = await HttpTriggerService.getHttpTrigger({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ script_path, is_flow })
|
||||
} else if (kind === 'schedules') {
|
||||
const { script_path, is_flow } = await ScheduleService.getSchedule({
|
||||
workspace: workspace!,
|
||||
path: path
|
||||
})
|
||||
|
||||
result = retrieveKindsValues({ script_path, is_flow })
|
||||
} else {
|
||||
throw new Error(`Unexpected trigger kind got: ${kind}`)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { KafkaTriggerService, type KafkaTrigger } from '$lib/gen'
|
||||
import {
|
||||
KafkaTriggerService,
|
||||
WorkspaceService,
|
||||
type KafkaTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle } from 'lucide-svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces, enterpriseLicense } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -30,12 +35,26 @@
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import KafkaIcon from '$lib/components/icons/KafkaIcon.svelte'
|
||||
import KafkaTriggerEditor from '$lib/components/triggers/kafka/KafkaTriggerEditor.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
|
||||
type TriggerW = KafkaTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerW[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (await KafkaTriggerService.listKafkaTriggers({ workspace: $workspaceStore! })).map(
|
||||
@@ -199,6 +218,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<KafkaTriggerEditor on:update={loadTriggers} bind:this={kafkaTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -394,6 +414,21 @@
|
||||
kafkaTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'kafka'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { MqttTriggerService, type MqttTrigger } from '$lib/gen'
|
||||
import {
|
||||
MqttTriggerService,
|
||||
WorkspaceService,
|
||||
type MqttTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle } from 'lucide-svelte'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -30,12 +35,26 @@
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import MqttTriggerEditor from '$lib/components/triggers/mqtt/MqttTriggerEditor.svelte'
|
||||
import { MqttIcon } from '$lib/components/icons'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
|
||||
type TriggerM = MqttTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerM[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (await MqttTriggerService.listMqttTriggers({ workspace: $workspaceStore! })).map(
|
||||
@@ -199,6 +218,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<MqttTriggerEditor on:update={loadTriggers} bind:this={mqttTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -374,6 +394,21 @@
|
||||
mqttTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'mqtt'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { NatsTriggerService, type NatsTrigger } from '$lib/gen'
|
||||
import {
|
||||
NatsTriggerService,
|
||||
WorkspaceService,
|
||||
type NatsTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle } from 'lucide-svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces, enterpriseLicense } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -30,13 +35,26 @@
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import NatsIcon from '$lib/components/icons/NatsIcon.svelte'
|
||||
import NatsTriggerEditor from '$lib/components/triggers/nats/NatsTriggerEditor.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
|
||||
type TriggerW = NatsTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerW[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (await NatsTriggerService.listNatsTriggers({ workspace: $workspaceStore! })).map(
|
||||
(x) => {
|
||||
@@ -199,6 +217,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<NatsTriggerEditor on:update={loadTriggers} bind:this={natsTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -394,6 +413,21 @@
|
||||
natsTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'nats'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { PostgresTriggerService, type PostgresTrigger } from '$lib/gen'
|
||||
import {
|
||||
PostgresTriggerService,
|
||||
WorkspaceService,
|
||||
type PostgresTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, Database } from 'lucide-svelte'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, Database, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -29,13 +34,26 @@
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import PostgresTriggerEditor from '$lib/components/triggers/postgres/PostgresTriggerEditor.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
|
||||
type TriggerD = PostgresTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerD[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (
|
||||
await PostgresTriggerService.listPostgresTriggers({ workspace: $workspaceStore! })
|
||||
@@ -198,6 +216,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<PostgresTriggerEditor on:update={loadTriggers} bind:this={postgresTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -380,6 +399,21 @@
|
||||
postgresTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'postgres'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { HttpTriggerService, type HttpTrigger } from '$lib/gen'
|
||||
import {
|
||||
HttpTriggerService,
|
||||
WorkspaceService,
|
||||
type HttpTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import { canWrite, displayDate, getLocalSetting, storeLocalSetting } from '$lib/utils'
|
||||
import { base } from '$app/paths'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
@@ -9,8 +14,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces } from '$lib/stores'
|
||||
import { Route, Code, Eye, Pen, Plus, Share, Trash } from 'lucide-svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces, enterpriseLicense } from '$lib/stores'
|
||||
import { Route, Code, Eye, Pen, Plus, Share, Trash, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -21,13 +26,26 @@
|
||||
import { setQuery } from '$lib/navigation'
|
||||
import { onMount } from 'svelte'
|
||||
import RouteEditor from '$lib/components/triggers/http/RouteEditor.svelte'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
|
||||
type TriggerW = HttpTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerW[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (await HttpTriggerService.listHttpTriggers({ workspace: $workspaceStore! })).map(
|
||||
(x) => {
|
||||
@@ -151,6 +169,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<RouteEditor on:update={loadTriggers} bind:this={routeEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -293,6 +312,21 @@
|
||||
routeEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'routes'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { ScheduleService, JobService, type ScheduleWJobs } from '$lib/gen'
|
||||
import {
|
||||
ScheduleService,
|
||||
JobService,
|
||||
type ScheduleWJobs,
|
||||
type WorkspaceDeployUISettings,
|
||||
WorkspaceService
|
||||
} from '$lib/gen'
|
||||
import { canWrite, displayDate, getLocalSetting, storeLocalSetting } from '$lib/utils'
|
||||
import { base } from '$app/paths'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
@@ -11,12 +17,13 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore, userWorkspaces } from '$lib/stores'
|
||||
import { userStore, workspaceStore, userWorkspaces, enterpriseLicense } from '$lib/stores'
|
||||
import {
|
||||
Calendar,
|
||||
Circle,
|
||||
Code,
|
||||
Eye,
|
||||
FileUp,
|
||||
List,
|
||||
Loader2,
|
||||
Pen,
|
||||
@@ -36,6 +43,8 @@
|
||||
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
||||
import { setQuery } from '$lib/navigation'
|
||||
import { onMount } from 'svelte'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
|
||||
type ScheduleW = ScheduleWJobs & { canWrite: boolean }
|
||||
|
||||
@@ -43,7 +52,18 @@
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let loadingSchedulesWithJobStats = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadSchedules(): Promise<void> {
|
||||
schedules = (await ScheduleService.listSchedules({ workspace: $workspaceStore! })).map((x) => {
|
||||
return { canWrite: canWrite(x.path, x.extra_perms!, $userStore), ...x }
|
||||
@@ -243,6 +263,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders, filterEnabledDisabled)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<ScheduleEditor on:update={loadSchedules} bind:this={scheduleEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -429,6 +450,21 @@
|
||||
scheduleEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'schedules'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'View runs',
|
||||
icon: List,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { SqsTriggerService, type SqsTrigger } from '$lib/gen'
|
||||
import {
|
||||
SqsTriggerService,
|
||||
WorkspaceService,
|
||||
type SqsTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, Database } from 'lucide-svelte'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { Code, Eye, Pen, Plus, Share, Trash, Circle, Database, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -29,13 +34,26 @@
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import SqsTriggerEditor from '$lib/components/triggers/sqs/SqsTriggerEditor.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
|
||||
type TriggerD = SqsTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerD[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (await SqsTriggerService.listSqsTriggers({ workspace: $workspaceStore! })).map(
|
||||
(x) => {
|
||||
@@ -198,6 +216,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<SqsTriggerEditor on:update={loadTriggers} bind:this={sqsTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -375,6 +394,21 @@
|
||||
sqsTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'sqs'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { WebsocketTriggerService, type WebsocketTrigger } from '$lib/gen'
|
||||
import {
|
||||
WebsocketTriggerService,
|
||||
WorkspaceService,
|
||||
type WebsocketTrigger,
|
||||
type WorkspaceDeployUISettings
|
||||
} from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
displayDate,
|
||||
@@ -15,8 +20,8 @@
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Unplug, Code, Eye, Pen, Plus, Share, Trash, Circle } from 'lucide-svelte'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { Unplug, Code, Eye, Pen, Plus, Share, Trash, Circle, FileUp } from 'lucide-svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
@@ -29,13 +34,26 @@
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import WebsocketTriggerEditor from '$lib/components/triggers/websocket/WebsocketTriggerEditor.svelte'
|
||||
import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
import { ALL_DEPLOYABLE, isDeployable } from '$lib/utils_deployable'
|
||||
|
||||
type TriggerW = WebsocketTrigger & { canWrite: boolean }
|
||||
|
||||
let triggers: TriggerW[] = []
|
||||
let shareModal: ShareModal
|
||||
let loading = true
|
||||
let deploymentDrawer: DeployWorkspaceDrawer
|
||||
let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined
|
||||
|
||||
async function getDeployUiSettings() {
|
||||
if (!$enterpriseLicense) {
|
||||
deployUiSettings = ALL_DEPLOYABLE
|
||||
return
|
||||
}
|
||||
let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! })
|
||||
deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE
|
||||
}
|
||||
getDeployUiSettings()
|
||||
async function loadTriggers(): Promise<void> {
|
||||
triggers = (
|
||||
await WebsocketTriggerService.listWebsocketTriggers({ workspace: $workspaceStore! })
|
||||
@@ -198,6 +216,7 @@
|
||||
$: updateQueryFilters(selectedFilterKind, filterUserFolders)
|
||||
</script>
|
||||
|
||||
<DeployWorkspaceDrawer bind:this={deploymentDrawer} />
|
||||
<WebsocketTriggerEditor on:update={loadTriggers} bind:this={websocketTriggerEditor} />
|
||||
|
||||
<SearchItems
|
||||
@@ -385,6 +404,21 @@
|
||||
websocketTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
...(isDeployable('trigger', path, deployUiSettings)
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to prod/staging',
|
||||
icon: FileUp,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'trigger', {
|
||||
triggers: {
|
||||
kind: 'websockets'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
|
||||
@@ -539,7 +539,8 @@
|
||||
apps: (settings.deploy_ui.include_type?.indexOf('app') ?? -1) >= 0,
|
||||
resources: (settings.deploy_ui.include_type?.indexOf('resource') ?? -1) >= 0,
|
||||
variables: (settings.deploy_ui.include_type?.indexOf('variable') ?? -1) >= 0,
|
||||
secrets: (settings.deploy_ui.include_type?.indexOf('secret') ?? -1) >= 0
|
||||
secrets: (settings.deploy_ui.include_type?.indexOf('secret') ?? -1) >= 0,
|
||||
triggers: (settings.deploy_ui.include_type?.indexOf('trigger') ?? -1) >= 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,6 +563,7 @@
|
||||
resources: boolean
|
||||
variables: boolean
|
||||
secrets: boolean
|
||||
triggers: boolean
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user