feat: webhook workflow action (#29258)

Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
This commit is contained in:
Ben Beckford 2026-06-26 07:08:45 -07:00 committed by GitHub
parent a876d4a9f1
commit 953ef5c047
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 159 additions and 99 deletions

View file

@ -233,12 +233,6 @@
}
}
},
{
"name": "assetTimeline",
"title": "Move to timeline",
"description": "Change visibility to timeline",
"types": ["AssetV1"]
},
{
"name": "assetVisibility",
"title": "Update visibility",
@ -301,100 +295,38 @@
}
},
{
"name": "noop1",
"title": "DEV: Nested properties",
"description": "Example configuration with nested properties",
"name": "webhook",
"title": "Trigger Webhook",
"description": "POST/PUT event data to any URL",
"types": ["AssetV1"],
"hostFunctions": true,
"allowedHosts": ["*"],
"schema": {
"type": "object",
"properties": {
"number1": {
"type": "number",
"title": "Number 1",
"description": "Basic number"
},
"number2": {
"type": "number",
"title": "Number 2",
"array": true,
"description": "List of numbers"
},
"string1": {
"url": {
"type": "string",
"title": "String 1",
"description": "Basic string"
"title": "URL",
"description": "Event data will be PUT/POSTed to this URL as a JSON object"
},
"string2": {
"headerName": {
"type": "string",
"title": "String 2",
"array": true,
"description": "List of strings"
"title": "Header name",
"description": "The name of an additional header to include with the request (e.g. authentication)"
},
"string3": {
"headerValue": {
"type": "string",
"title": "String 3",
"enum": ["choice-1", "choice-2"],
"description": "Select from a list"
"title": "Header value",
"description": "The value of the additional header"
},
"nested": {
"type": "object",
"title": "Nested",
"description": "Nested properties for nesting",
"properties": {
"nested1": {
"type": "string",
"title": "Nested 1",
"description": "Nested string"
},
"nested2": {
"type": "number",
"title": "Nested 2",
"description": "Nested number"
},
"nested3": {
"type": "object",
"title": "Nested 3",
"description": "Nested again",
"properties": {
"nested4": {
"type": "boolean",
"title": "Nested 4",
"description": "Nested, nested boolean"
}
}
}
}
"method": {
"type": "string",
"title": "Method",
"description": "The HTTP method to use in the request",
"enum": ["POST", "PUT"]
}
}
}
},
{
"name": "noop2",
"title": "DEV: Album pickers",
"description": "Example configuration with album pickers",
"types": ["AssetV1"],
"schema": {
"properties": {
"albumId": {
"type": "string",
"title": "Album ID",
"description": "Target album ID",
"uiHint": {
"type": "AlbumId",
"order": 1
}
},
"albumIds": {
"type": "string",
"title": "Album IDs",
"description": "Target album IDs",
"array": true,
"uiHint": {
"type": "AlbumId",
"order": 2
}
}
}
},
"required": ["url"]
}
}
]

View file

@ -155,3 +155,21 @@ export const assetAddToAlbums = wrapper<'assetAddToAlbums'>(({ config, data, fun
functions.addAssetsToAlbums({ albumIds: config.albumIds, assetIds: [assetId] });
return {};
});
export const webhook = wrapper<'webhook'>(({ config, data, functions }) => {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (config.headerName && config.headerValue) {
headers[config.headerName] = config.headerValue;
}
functions.httpRequest(config.url, {
method: config.method ?? 'POST',
body: JSON.stringify(data.asset),
headers,
});
return {};
});

View file

@ -4,7 +4,7 @@
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, // Enables compatibility with Babel-style module imports
"lib": ["es2020"], // Specify a list of library files to be included in the compilation
"lib": ["es2020", "DOM"], // Specify a list of library files to be included in the compilation
"module": "nodenext", // Specify module code generation
"moduleResolution": "nodenext",
"noEmit": true, // Do not emit outputs (no .js or .d.ts files)

View file

@ -30,12 +30,23 @@ type HostFunctionResult<T> =
type QueryParams<T extends (...args: any) => any> = Parameters<T>[0];
type AlbumSearchDto = QueryParams<typeof getAllAlbums>;
type HttpRequestOptions = {
method?: string;
headers?: Record<string, string>;
body?: string;
};
type HttpResponse = {
ok: string;
status: number;
body: string;
};
export const availableFunctions = [
'searchAlbums',
'createAlbum',
'addAssetsToAlbum',
'addAssetsToAlbums',
'httpRequest',
] as const;
export const hostFunctions = (authToken: string) => {
@ -79,5 +90,11 @@ export const hostFunctions = (authToken: string) => {
),
addAssetsToAlbums: ({ assetIds, albumIds }: AlbumsToAssets) =>
call('addAssetsToAlbums', authToken, [{ albumIds, assetIds }]),
httpRequest: (url: string, options?: HttpRequestOptions) =>
call<[string, HttpRequestOptions | undefined], HttpResponse>(
'httpRequest',
authToken,
[url, options],
),
} satisfies Record<(typeof availableFunctions)[number], unknown>;
};