From c52497f7edd0fea85640e49ac653e6f9fca0ff25 Mon Sep 17 00:00:00 2001 From: ndsboy Date: Tue, 4 Mar 2025 21:42:05 +0000 Subject: [PATCH] feat: add windmill operation --- .vscode/tasks.json | 16 +++++----- directus/data.db | Bin 299008 -> 335872 bytes package-lock.json | 15 ++++----- package.json | 19 +++++++++--- src/tasks/layout.vue | 4 +-- src/windmill/api.ts | 47 ++++++++++++++++++++++++++++ src/windmill/app.ts | 67 ++++++++++++++++++++++++++++++++++++++++ src/windmill/shims.d.ts | 5 +++ 8 files changed, 151 insertions(+), 22 deletions(-) create mode 100644 src/windmill/api.ts create mode 100644 src/windmill/app.ts create mode 100644 src/windmill/shims.d.ts diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b68d9ab..ef8bdf5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,11 +16,18 @@ { "label": "dev", "dependsOn": [ + "dev extension", "dev directus", - "dev extension" ], "problemMatcher": [] }, + { + "label": "dev extension", + "command": "npm run dev", + "type": "shell", + "hide": true, + "problemMatcher": [] + }, { "label": "dev directus", "command": "npx directus start", @@ -31,12 +38,5 @@ "hide": true, "problemMatcher": [] }, - { - "label": "dev extension", - "command": "npm run dev", - "type": "shell", - "hide": true, - "problemMatcher": [] - } ] } \ No newline at end of file diff --git a/directus/data.db b/directus/data.db index 48755292bd9b735c0a4d392aa164efed76871e25..1bf189817cec862ac2a7e3e8841a75ed5b30251a 100644 GIT binary patch delta 27473 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 Y;*Ba8BE<6gDiDDd-6%Z$n6~5p0W4tur2qf` delta 1456 zcmbu7Z%i9y9LJyM?h2E(_jF{yib6@ICT#pUpyePY+JBUm{<#)tDJ6EVUzw}8uyUigNn$zn8^EXKtIYSb4aCi8`oc`zan-$=a6J-OdK zPrl#Jee+#jKeN16f33M*q67d~#OL6GKdyH4ViM)Ym+oC}Ip3hgyI~-b4$fqA86P{7 zjpQTQg$`veK6r{>l*7id<3>eWCKS7<3?B>K7$k+eD)0lq*!|!&%UkJ5|zsLXD4V9uORMe6JKog`;KCQS#)^aam za`!oo7f8uf@!+>!egsJ>6(=N?Wf*$0r)5Teq9=laBDRrK9EZ+}i?Ok;45_E8+gd_# zlc3rJg2HxvW%$uk)qCrT+v`w)1M5iE@vVlI!FV%&2Y zc0|Xs4Dm8S^}f5x?>vMIpZWo7SXyablKo@B$rq+Fq22+%#hP76dg2rPz4JQ9V7eIB zm{@}*Wz7GJFBz)}%VSmu;EsXowIj?!rVK18d)c!y=GL>PR4*Td_ zB5H__F@eB@!Jzl+O+%J`KTD1>wq$>NWQ>|f=TgyUh=W7FUp+*00svc&GHQZ7mf0aD zAJsX>k}-`fl$gt#3$uklDx6NxGs*cmDl(F_hRlqys2_Lv{8V68yNB6;gBopgZV-c;6K_uaW$k12-O{4G8hv>5S-H!O_tN6{zBUna!StYSo*6GxW%{~r2)ge5nhzw5 zc)EpZ@3IlJaBGpc1Z$vt6UaBk Nt*_<6<`tqH`y0`=%dG$a diff --git a/package-lock.json b/package-lock.json index 25d6f20..8041c53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "@directus/extensions": "^3.0.1", "@directus/extensions-sdk": "13.0.1", "@directus/types": "^13.0.0", - "typescript": "^5.7.3", + "@types/node": "^22.13.9", + "typescript": "^5.8.2", "vue": "^3.5.13", "vue-router": "^4.5.0" } @@ -1383,9 +1384,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", - "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", + "version": "22.13.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", + "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", "dev": true, "license": "MIT", "dependencies": { @@ -4953,9 +4954,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index bb516aa..11ca516 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,15 @@ { "type": "layout", "name": "tasks", - "source": "src/tasks/index.js" + "source": "src/tasks/index.ts" + }, + { + "type": "operation", + "name": "windmill", + "source": { + "app": "src/windmill/app.ts", + "api": "src/windmill/api.ts" + } } ], "host": "^10.10.0" @@ -28,10 +36,11 @@ }, "devDependencies": { "@directus/types": "^13.0.0", - "@directus/extensions-sdk": "13.0.1", - "@directus/extensions": "^3.0.1", - "typescript": "^5.7.3", + "@directus/extensions-sdk": "13.0.3", + "@directus/extensions": "^3.0.3", + "typescript": "^5.8.2", "vue": "^3.5.13", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "@types/node": "^22.13.9" } } \ No newline at end of file diff --git a/src/tasks/layout.vue b/src/tasks/layout.vue index ced8a30..b083a9e 100644 --- a/src/tasks/layout.vue +++ b/src/tasks/layout.vue @@ -12,7 +12,7 @@ @click="router.push(`${collection}/${item.id}`)"> @@ -85,7 +85,7 @@ export default defineComponent({ type: Array as PropType, required: true, }, - me: Object, + me: String, } }) diff --git a/src/windmill/api.ts b/src/windmill/api.ts new file mode 100644 index 0000000..91f5647 --- /dev/null +++ b/src/windmill/api.ts @@ -0,0 +1,47 @@ +import { defineOperationApi } from '@directus/extensions-sdk'; + +type Options = { + token: string + instance: string + flow: string +} + +type Data = { + // create and update trigger + event?: string + collection?: string + + // create trigger + key: string + + // update trigger + keys?: string[] + + // manual trigger + body?: { + collection: string + keys: string[] + } +} + +export default defineOperationApi({ + id: 'windmill', + handler: async ({ token, instance, flow }, { data }) => { + const last = data.$last as Data + const body = JSON.stringify({ + event: last.event ?? "manual", + instance: instance, + collection: last.collection ?? last.body?.collection, + keys: last.keys ?? last.body?.keys ?? [last.key] + }) + + return await fetch(`https://windmill.swablab.de/api/r/${flow}`, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + }, + body + }) + }, +}); diff --git a/src/windmill/app.ts b/src/windmill/app.ts new file mode 100644 index 0000000..a81e50f --- /dev/null +++ b/src/windmill/app.ts @@ -0,0 +1,67 @@ +import { defineOperationApp } from "@directus/extensions-sdk"; + +export default defineOperationApp({ + id: "windmill", + name: "swablab windmill", + icon: "wind_power", + description: "trigger a windmill action", + overview: ({ instance, flow }) => [ + { + label: "Instance", + text: instance, + }, + { + label: "Flow", + text: flow, + }, + ], + options: [ + { + field: "token", + name: "Token", + type: "string", + meta: { + width: "full", + interface: "input", + required: true, + note: "See Vaultwarden", + options: { + masked: true + } + } + }, + { + field: "instance", + name: "Instance", + type: "string", + meta: { + width: "full", + interface: 'select-dropdown', + required: true, + options: { + choices: [ + { + text: 'Directus', + value: 'directus', + }, + { + text: 'Management', + value: 'management', + }, + ], + } + }, + }, + { + field: "flow", + name: "Flow", + type: "string", + meta: { + width: "full", + interface: "input", + required: true, + note: "https://windmill.swablab.de/api/r/..." + }, + }, + ], +}); diff --git a/src/windmill/shims.d.ts b/src/windmill/shims.d.ts new file mode 100644 index 0000000..9923fb6 --- /dev/null +++ b/src/windmill/shims.d.ts @@ -0,0 +1,5 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +}