Nodebase corsair - #80
Conversation
…omprehensive node-based workflow support
Add self-hosted Corsair foundation (KEK, multi-tenant client, Prisma tables, connect APIs) and migrate Gmail node ops behind a feature-flagged adapter with full unit coverage and legacy fallback.
Register @corsair-dev/googlesheets, map every Nodebase GoogleSheetsOp through a feature-flagged adapter with edge-case validation and unit tests; dual-path executor keeps the legacy REST path as fallback.
Add tenant_id on workflow/execution/node runs with backfill, stamp tenant and operation strings during Inngest execution, and introduce a code registry for Gmail/Sheets ops (aliases, no new Prisma op enums).
…, Google Drive - Add registry-driven runIntegration runner with tenant isolation, op validation, and dual-path safe tryRunIntegration for Gmail / Sheets / Drive executors - Expand Gmail adapter to full @corsair-dev/gmail endpoints (delete, batchModify, untrash, drafts CRUD, threads, labels CRUD) with alias-preserving dispatch - Complete Sheets Corsair ops (appendOrUpdate, delete sheet, spreadsheet CRUD) - Ship Google Drive vertical: package, client plugin, registry, adapter, matrix, dual-path executor, completeness + unit tests - Product TS enums for Drive/Gmail extras; do NOT grow Prisma op enums (Option C) - Completeness tests enforce registry ops cover Corsair public endpoints - Comment unknown JSON boundaries; no implicit any in new code
Type safety: - Unify NodeExecutor + node data types under executions/types/ (fix shadowing) - Add asString/asBoolean/asNumber helpers; no implicit any in migration paths - Fix Gmail/Sheets/Drive/Slack executors for Record JSON config narrowing - Executor registry variance cast; Prisma InputJsonValue for node data writes - Full project tsc --noEmit is clean (0 errors) Gmail + Sheets verification: - Gmail attachment MIME walk typed; upload opts require string path segments - Sheets tests for CREATE_SPREADSHEET, LIST_SPREADSHEETS, APPEND_OR_UPDATE, DELETE_SHEET Slack (next plugin after Drive): - @corsair-dev/slack package, client registration, registry + completeness - Full adapter for messages/channels/users/reactions/files/stars - Dual-path executor; webhook/schedule/lookupByEmail stay legacy-only - Unit tests for ops + legacy-only detection 93 integration/corsair unit tests passing.
Dialogs: - Gmail: full Corsair op selector (drafts/threads/labels/batch/delete), type-safe credential list, new fields (messageIds, labelId), output hints - Sheets: APPEND_OR_UPDATE, DELETE_SHEET, spreadsheet CRUD, list spreadsheets, conditional spreadsheetId, no implicit any - Slack: MESSAGE_SEARCH, history/rename/open, FILE_LIST, presence; default MESSAGE_SEND; type-safe prefill/save GitHub Corsair: - Install @corsair-dev/github; register plugin - Registry + adapter covering full package surface (issues, PRs, repos, releases, workflows, discussions, forks, comments, events, users) - Dual-path executor: Corsair when op mapped, else legacy REST modules - Completeness + unit tests (97 integration tests green) tsc --noEmit clean.
GitHub dialog: - Wire onSubmit/defaultValues from canvas node (was a no-op save) - Type-safe credential select; Corsair badges on mapped ops - Extra fields for username/commentId/releaseId; clearer output help Notion Corsair: - @corsair-dev/notion package + client registration - Full registry/adapter surface (databases, databasePages, pages, blocks, users) - Dual-path executor; unit + completeness tests Notion dialog: - Full op selector for Corsair surface (list/search databases, create page, …) - Type-safe prefill/save; variable name + output hints Rule: polish dialog with each plugin before moving on. 105 integration tests green; tsc clean.
… dialog Edge cases (tests): - GitHub: owner/repo required, issue/PR numbers, CLOSE/REOPEN state, CSV labels, comment/workflow/path/tag/username validation - Notion: invalid JSON filter/properties, empty parents/ids, JSON vs plain blocks, filter+sorts passthrough, blockId fallback to pageId HubSpot (@corsair-dev/hubspot): - Registry + adapter for ALL nested endpoints (contacts, companies, deals, tickets, engagements, contactLists) - Unit tests covering create/search/delete/lists/engagements + edge JSON - Dual-path executor (Corsair when mapped; legacy OAuth otherwise) - Dialog polish: Corsair badges, type-safe defaults, working save 147 integration tests green; tsc clean.
Registry, adapter, and completeness tests cover all @corsair-dev/telegram endpoints (messages, media, chat, callback, file, me, updates, webhook). Dual-path executor tries Corsair first and falls back to legacy sendMessage. Dialog polished with operation groups and conditional fields. Plugin registers with bot_token auth (no permissions mode on TelegramPluginOptions).
Registry, adapter, and tests cover all @corsair-dev/discord endpoints (messages, threads, reactions, guilds, channels, members). Dual-path executor uses Corsair bot API when channel ops are configured; legacy inbound webhook URL path remains. Dialog groups ops with conditional fields.
Covers all @corsair-dev/twitter endpoints (tweets.create, createReply). Dual-path prefers Corsair OAuth unless legacy OAuth1 keys are on the node. Dialog supports post/reply fields and optional legacy keys.
Registry and adapter cover all @corsair-dev/razorpay endpoints (orders, payments, refunds, customers, payouts, settlements, subscriptions). Dual-path executor prefers Corsair for package ops; invoices/payment links/signature verify stay on legacy credential REST. Dialog lists new Corsair ops. Amounts remain in paise. Completeness + unit tests included.
|
Important Review skippedToo many files! This PR contains 287 files, which is 187 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (314)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Stripe: all 20 @corsair-dev/stripe endpoints (balance, charges, coupons, customers, paymentIntents, prices, sources, tokens) with validation edges and dual-path-ready executor/dialog. OpenAI: all 129 @corsair-dev/openai nested endpoints via registry + generic path invoker; convenience ops CHAT/EMBED/IMAGE/MODERATE/TTS; dual-path openAiExecutor (Corsair then legacy aiExecutor); polished dialog. Completeness tests assert registry ⊇ package trees. 233 integration tests green.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b82bac6e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ) | ||
|
|
||
| const handleSave = () => { | ||
| const upsertMutation = { isPending: false, mutate: (args?: any) => {}, mutateAsync: async (args?: any) => {} } as any; |
There was a problem hiding this comment.
Persist If/Else settings instead of no-oping saves
When configuring an IF/ELSE node, handleSave now only calls this stubbed mutation and there is no parent onSubmit/setNodes path for the dialog, while the executor was changed to read conditions from node.data. In practice, new or edited IF/ELSE nodes never store field, operator, value, or conditionsJson, so branching remains unconfigured and workflow control flow takes the default/false path.
Useful? React with 👍 / 👎.
| } | ||
| } | ||
| }, [deleteCode, deleteGmail, deleteGoogleDrive, deleteGoogleSheets, deleteIfElse, deleteLoop, deleteNotion, deleteRazorpay, deleteSetVariable, deleteSlack, deleteSwitch, deleteWhatsapp, deleteWait, deleteMerge, deleteErrorTrigger, deleteRazorpayTrigger, deleteWhatsappTrigger, deleteMsg91, deleteShiprocket, deleteZohoCrm, deleteHubspot, deleteFreshdesk, deleteFilter, deleteCashfree]) | ||
| }, [deleteErrorTrigger]); |
There was a problem hiding this comment.
Remove webhook trigger records when deleting nodes
After this change, deleting nodes from the canvas only retains the Error Trigger cleanup; the Razorpay/WhatsApp trigger delete mutations and switch cases were removed, but those trigger rows are keyed by nodeId and only cascade when the whole workflow is deleted. Since the public webhook routes look up RazorpayTrigger/WhatsAppTrigger by webhookId and execute when isActive, deleting one of these trigger nodes leaves its old webhook URL active and able to run the workflow.
Useful? React with 👍 / 👎.
| { enabled: open && !!nodeId } | ||
| ) | ||
| ) | ||
| const config = undefined as any; |
There was a problem hiding this comment.
Hydrate Code node data before resetting the dialog
Because config is hard-coded to undefined, opening an existing Code node always runs the reset-to-starter-template path instead of loading the node's saved data; the save path only sends code through onSubmit(code) and the mutation below is a no-op, while the executor now reads timeout, allowed domains, variable name, and continue-on-fail from data. Reopening and saving a configured Code node can therefore wipe the code/settings back to defaults and make executions use the wrong configuration.
Useful? React with 👍 / 👎.
| const safeReturnUrl = (stateData.returnUrl ?? "/credentials").startsWith("/") | ||
| ? stateData.returnUrl | ||
| : "/credentials" |
There was a problem hiding this comment.
Reject protocol-relative GitHub return URLs
For an authenticated user who starts GitHub OAuth with returnUrl=//evil.example, this check accepts the value as “relative”; the callback then builds new URL(safeReturnUrl, baseUrl), which treats //evil.example as an external URL and redirects there with the OAuth success query parameters. Require a single-slash path or enforce same-origin parsing so the OAuth flow cannot be used as an open redirect.
Useful? React with 👍 / 👎.
Gemini (@corsair-dev/gemini): all 8 endpoints — generateContent, countTokens, embedContent, generateImage, generateVideos, getVideosOperation, waitForVideo, listModels — with validation edges and dual-path geminiExecutor. DeepSeek (@corsair-dev/deepseek): all 4 endpoints — chat.createCompletion, anthropic.createMessage, user.getBalance, models.list — with dual-path deepseekExecutor and polished dialogs. Completeness + unit tests cover every package op. 257 integration tests green.
…ypesafety @corsair-dev/perplexityai exposes chat.completions only — registry, adapter, and completeness cover that endpoint with product aliases CHAT/SEARCH_CHAT. Edge validation: messages shape, roles, JSON, temperature/top_p/max_tokens ranges, stream=true rejected. Dual-path executor (Corsair then legacy AI), polished dialog, tenant-scoped runner path, no implicit any.
…/DeepSeek Extract shared llm-edges helpers (messages roles/content, empty arrays, params JSON, temperature/top_p/max_tokens ranges, stream=true reject, missing client surface). Wire into OpenAI, Gemini, DeepSeek, and Perplexity operations with expanded unit tests. 301 integration tests green.
…sair ops OpenAI/DeepSeek chat now use openai-chat/deepseek-chat modes: roles include tool/function, tool_calls preserved, multimodal content arrays allowed, tools via paramsJson. Strict-chat kept for Perplexity package schema. Edges remain: empty messages, bad JSON, sampling ranges, stream=true reject, client surface. All package endpoints still registered (OpenAI 129). 305 tests green.
No description provided.