diff --git a/frontend/src/lib/components/triggers.ts b/frontend/src/lib/components/triggers.ts
index 4d5a70e9a0..ad3ded6b1d 100644
--- a/frontend/src/lib/components/triggers.ts
+++ b/frontend/src/lib/components/triggers.ts
@@ -54,6 +54,7 @@ export type TriggerKind =
| 'postgres'
| 'mqtt'
| 'sqs'
+ | 'gcp'
export function captureTriggerKindToTriggerKind(kind: CaptureTriggerKind): TriggerKind {
switch (kind) {
case 'webhook':
@@ -74,6 +75,8 @@ export function captureTriggerKindToTriggerKind(kind: CaptureTriggerKind): Trigg
return 'sqs'
case 'postgres':
return 'postgres'
+ case 'gcp':
+ return 'gcp'
default:
throw new Error(`Unknown CaptureTriggerKind: ${kind}`)
}
diff --git a/frontend/src/lib/components/triggers/CaptureButton.svelte b/frontend/src/lib/components/triggers/CaptureButton.svelte
index bfa34cf908..a5d89792ab 100644
--- a/frontend/src/lib/components/triggers/CaptureButton.svelte
+++ b/frontend/src/lib/components/triggers/CaptureButton.svelte
@@ -11,6 +11,7 @@
import AwsIcon from '../icons/AwsIcon.svelte'
import DropdownV2 from '$lib/components/DropdownV2.svelte'
import MqttIcon from '../icons/MqttIcon.svelte'
+ import GoogleCloudIcon from '../icons/GoogleCloudIcon.svelte'
export let small = false
@@ -45,6 +46,12 @@
action: () => handleClick('sqs'),
disabled: !$enterpriseLicense
},
+ {
+ icon: GoogleCloudIcon,
+ displayName: 'GCP Pub/Sub',
+ action: () => handleClick('gcp'),
+ disabled: !$enterpriseLicense
+ },
{
icon: MqttIcon,
displayName: 'MQTT',
diff --git a/frontend/src/lib/components/triggers/CaptureSection.svelte b/frontend/src/lib/components/triggers/CaptureSection.svelte
index ad483181e9..1237683dcc 100644
--- a/frontend/src/lib/components/triggers/CaptureSection.svelte
+++ b/frontend/src/lib/components/triggers/CaptureSection.svelte
@@ -6,6 +6,7 @@
isFlow: boolean
path: string
connectionInfo: ConnectionInfo | undefined
+ loading?: boolean
}
@@ -70,7 +71,11 @@
-
+
diff --git a/frontend/src/lib/components/triggers/CaptureTable.svelte b/frontend/src/lib/components/triggers/CaptureTable.svelte
index 1865ec4fbd..71df4c2991 100644
--- a/frontend/src/lib/components/triggers/CaptureTable.svelte
+++ b/frontend/src/lib/components/triggers/CaptureTable.svelte
@@ -1,6 +1,6 @@
-
+
{#if !collapsed || alwaysOpened}
diff --git a/frontend/src/lib/components/triggers/TriggersWrapper.svelte b/frontend/src/lib/components/triggers/TriggersWrapper.svelte
index e9a17c10dc..06decadd5e 100644
--- a/frontend/src/lib/components/triggers/TriggersWrapper.svelte
+++ b/frontend/src/lib/components/triggers/TriggersWrapper.svelte
@@ -11,6 +11,7 @@
import MqttEditorConfigSection from './mqtt/MqttEditorConfigSection.svelte'
import SqsTriggerEditorConfigSection from './sqs/SqsTriggerEditorConfigSection.svelte'
import PostgresEditorConfigSection from './postgres/PostgresEditorConfigSection.svelte'
+ import GcpTriggerEditorConfigSection from './gcp/GcpTriggerEditorConfigSection.svelte'
export let triggerType: CaptureTriggerKind = 'webhook'
export let cloudDisabled: boolean = false
@@ -96,5 +97,20 @@
can_write={true}
showCapture={false}
/>
+ {:else if triggerType === 'gcp'}
+
{/if}
diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditor.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditor.svelte
new file mode 100644
index 0000000000..1b2f8cf389
--- /dev/null
+++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditor.svelte
@@ -0,0 +1,27 @@
+
+
+{#if open}
+
+{/if}
diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte
new file mode 100644
index 0000000000..d359085122
--- /dev/null
+++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte
@@ -0,0 +1,342 @@
+
+
+
+
+
+ {#if showCapture && captureInfo}
+ {@const captureURL = `${base_endpoint}/${path}`}
+
+ {#if delivery_type === 'push'}
+
+ {/if}
+
+ {/if}
+
+
+
+
+ {
+ loadAllPubSubTopicsFromProject()
+ }}
+ resourceType="gcloud"
+ bind:value={gcp_resource_path}
+ />
+ {#if !emptyStringTrimmed(gcp_resource_path)}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+ {#if !emptyStringTrimmed(gcp_resource_path) && !emptyStringTrimmed(topic_id)}
+
+
+
{
+ if (e.detail === 'existing' && subscription_items.length === 0) {
+ loadAllSubscriptionFromGooglePubSubTopic()
+ }
+ }}
+ let:item
+ >
+
+
+
+
+ {#if subscription_mode === 'create_update'}
+
+
+ {
+ subscription_id = event?.currentTarget.value
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ {#if delivery_type === 'push' && delivery_config}
+
+
+
+
+
+
+
+
+
+
+
+
+ Enable Google Cloud authentication for push delivery using a verified token.
+
+
+
+
+ {/if}
+
+ {:else if subscription_mode === 'existing'}
+
+
+
+
+ If the subscription uses push delivery, its endpoint URL must
+ match the following format: {base_endpoint}/*, meaning it must
+ start with
+ {base_endpoint} followed by any path segment.
+
+
+ {/if}
+
+
+ {/if}
+
+
+
diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte
new file mode 100644
index 0000000000..45a74ec93d
--- /dev/null
+++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte
@@ -0,0 +1,293 @@
+
+
+
+
+
+ {#if !drawerLoading && can_write}
+ {#if edit}
+
+ {
+ sendUserToast(
+ `${e.detail ? 'enabled' : 'disabled'} GCP Pub/Sub trigger ${initialPath}`
+ )
+ }}
+ />
+
+ {/if}
+
+ {/if}
+
+ {#if drawerLoading}
+
+ {:else}
+
+
+ {#if edit}
+ Changes can take up to 30 seconds to take effect.
+ {:else}
+ New GCP Pub/Sub trigger can take up to 30 seconds to start listening.
+ {/if}
+
+
+
+
+
+
+
+ Pick a script or flow to be triggered
+
+
+
+ {#if emptyString(script_path)}
+
+ {/if}
+
+
+
+
+
+ {/if}
+
+
diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerPanel.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerPanel.svelte
new file mode 100644
index 0000000000..fe9c587c1b
--- /dev/null
+++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerPanel.svelte
@@ -0,0 +1,131 @@
+
+
+ {
+ loadTriggers()
+ }}
+ bind:this={gcpTriggerEditor}
+/>
+
+{#if !$enterpriseLicense}
+
+ GCP Pub/Sub triggers are an enterprise only feature.
+
+{:else if isCloudHosted()}
+
+ GCP Pub/Sub triggers are disabled in the multi-tenant cloud.
+
+{:else}
+
+
+ GCP Pub/Sub triggers allow your scripts or flows to process messages from Google Cloud
+ Pub/Sub in real time. Each trigger listens to a Pub/Sub subscription and executes a script or
+ a flow when new messages are published to the corresponding topic.
+
+
+ {#if !newItem && gcpTriggers && gcpTriggers.length > 0}
+
+
+
+ {#each gcpTriggers as gcpTrigger (gcpTrigger.path)}
+
+
{gcpTrigger.path}
+
+
+
+
+
+ {/each}
+
+
+
+ {/if}
+
+
{
+ gcpTriggerEditor?.openNew(isFlow, path, e.detail.config)
+ }}
+ on:addPreprocessor
+ on:updateSchema
+ on:testWithArgs
+ cloudDisabled={false}
+ triggerType="gcp"
+ {isFlow}
+ {path}
+ {isEditor}
+ {canHavePreprocessor}
+ {hasPreprocessor}
+ {newItem}
+ {openForm}
+ bind:showCapture={dontCloseOnLoad}
+ />
+
+{/if}
diff --git a/frontend/src/lib/components/triggers/http/RouteBodyTransformerOption.svelte b/frontend/src/lib/components/triggers/http/RouteBodyTransformerOption.svelte
index 4d11c07df1..62d54a5a35 100644
--- a/frontend/src/lib/components/triggers/http/RouteBodyTransformerOption.svelte
+++ b/frontend/src/lib/components/triggers/http/RouteBodyTransformerOption.svelte
@@ -4,12 +4,14 @@
import Tooltip from '$lib/components/Tooltip.svelte'
export let raw_string: boolean
- export let wrap_body: boolean
+ export let wrap_body: boolean
diff --git a/frontend/src/lib/components/triggers/http/utils.ts b/frontend/src/lib/components/triggers/http/utils.ts
index c6b7263227..319c24a309 100644
--- a/frontend/src/lib/components/triggers/http/utils.ts
+++ b/frontend/src/lib/components/triggers/http/utils.ts
@@ -7,11 +7,12 @@ export const SIGNATURE_TEMPLATE_SCRIPT_HUB_PATH: string = `hub/${HUB_SCRIPT_ID}`
export const SIGNATURE_TEMPLATE_FLOW_HUB_ID = '67'
export function getHttpRoute(
+ route_prefix: string,
route_path: string | undefined,
workspaced_route: boolean,
- workspace_id: string
+ workspace_id: string,
) {
- return `${location.origin}${base}/api/r/${
+ return `${location.origin}${base}/api/${route_prefix}/${
isCloudHosted() || workspaced_route ? workspace_id + '/' : ''
}${route_path ?? ''}`
}
diff --git a/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorConfigSection.svelte b/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorConfigSection.svelte
index 3732346888..48f89730ab 100644
--- a/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorConfigSection.svelte
+++ b/frontend/src/lib/components/triggers/sqs/SqsTriggerEditorConfigSection.svelte
@@ -8,9 +8,15 @@
import MultiSelect from 'svelte-multiselect'
import TestTriggerConnection from '../TestTriggerConnection.svelte'
import Subsection from '$lib/components/Subsection.svelte'
- import { X } from 'lucide-svelte'
+ import { Plus, X } from 'lucide-svelte'
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
+ import ArgInput from '$lib/components/ArgInput.svelte'
+ import ItemPicker from '$lib/components/ItemPicker.svelte'
+ import VariableEditor from '$lib/components/VariableEditor.svelte'
+ import { Button } from '$lib/components/common'
+ import { VariableService } from '$lib/gen'
+ import { workspaceStore } from '$lib/stores'
export let can_write: boolean = false
export let headless: boolean = false
@@ -21,29 +27,17 @@
export let queue_url = ''
export let aws_resource_path = ''
export let message_attributes: string[] = []
+
+ async function loadVariables() {
+ return await VariableService.listVariable({ workspace: $workspaceStore ?? '' })
+ }
+ let itemPicker: ItemPicker
+ let variableEditor: VariableEditor
let cached: string[] = []
- let dirtyUrl: boolean = false
- let urlError: string = ''
- let validateTimeout: NodeJS.Timeout | undefined = undefined
let all_attributes = message_attributes.includes('All')
let tab: 'specific' | 'all' = all_attributes ? 'all' : 'specific'
- function validateUrl(queue_url: string | undefined) {
- if (validateTimeout) {
- clearTimeout(validateTimeout)
- }
- validateTimeout = setTimeout(() => {
- if (!queue_url || /^(https:)\/\/[^\s]+$/.test(queue_url) === false) {
- urlError = 'Queue url must start with https://'
- } else {
- urlError = ''
- }
- validateTimeout = undefined
- }, 500)
- }
- $: validateUrl(queue_url)
- $: isValid =
- urlError === '' && !emptyStringTrimmed(aws_resource_path) && !emptyStringTrimmed(queue_url)
+ $: isValid = !emptyStringTrimmed(aws_resource_path) && !emptyStringTrimmed(queue_url)