Feat/auto create products#85
Conversation
Update dev
…ser for product IDs
Greptile SummaryThis PR removes the manual Dodo product-ID fields from the onboarding flow and replaces them with automatic product creation at setup time, using
Confidence Score: 3/5Safe to merge if the orphan-on-retry behavior is acceptable, but the failure window between Promise.all and retrieveSecret now silently pollutes Dodo with double the resources compared to before. The onboarding handler gains product-creation calls inside an atomic-looking try/catch that is actually not atomic: Promise.all can partially succeed before retrieveSecret throws, leaving 2 webhooks and 2 products orphaned in Dodo with no cleanup path. Repeated failed attempts accumulate dangling objects. Additionally, the companion documentation in scrawndotdev/documentation still tells users to manually supply Product IDs that no longer exist in the form, making the setup guide actively wrong. src/routes/http/api/onboarding.ts — the resource-cleanup gap between the Promise.all block and the retrieveSecret calls warrants a closer look; src/zod/internals.ts is straightforward. Important Files Changed
|
| liveSecret = (await liveClient.webhooks.retrieveSecret(liveWebhook.id)) | ||
| .secret; | ||
|
|
||
| const testWebhook = await testClient.webhooks.create({ | ||
| url: `${appUrl}/webhooks/payment/createdCheckout?mode=test`, | ||
| description: "Scrawn test payment webhook", | ||
| filter_types: ["payment.succeeded", "payment.failed"], | ||
| }); | ||
| testSecret = (await testClient.webhooks.retrieveSecret(testWebhook.id)) | ||
| .secret; | ||
| liveProductId = liveProduct.product_id; | ||
| testProductId = testProduct.product_id; |
There was a problem hiding this comment.
Orphaned Dodo resources on
retrieveSecret failure
If Promise.all completes successfully (creating 2 webhooks + 2 products) but either retrieveSecret call then throws, the error handler returns a 400 with no cleanup — leaving all four resources orphaned in Dodo. A subsequent retry will create a fresh set of four resources without removing the previous ones. Previously, only webhook objects were at risk; this PR doubles the surface area by adding product creation inside the same unguarded transaction boundary.
Consider using separate try/catch scopes for the retrieveSecret calls, or deleting already-created resources in the catch block, so at least partial-failure retries don't accumulate dangling objects in Dodo.
| liveClient.products.create({ | ||
| name: "Scrawn Billing", | ||
| price: { | ||
| type: "one_time_price", | ||
| currency: validated.currency, | ||
| price: 0, | ||
| pay_what_you_want: true, | ||
| purchasing_power_parity: false, | ||
| discount: 0, | ||
| }, | ||
| tax_category: "saas", | ||
| }), | ||
| testClient.products.create({ | ||
| name: "Scrawn Billing", | ||
| price: { | ||
| type: "one_time_price", | ||
| currency: validated.currency, | ||
| price: 0, | ||
| pay_what_you_want: true, | ||
| purchasing_power_parity: false, | ||
| discount: 0, | ||
| }, | ||
| tax_category: "saas", | ||
| }), |
There was a problem hiding this comment.
Documentation in related repo is now stale
The scrawndotdev/documentation repo's dashboard-setup.mdx still walks users through manually creating Dodo products and pasting their Product IDs into the onboarding form. With this PR, product creation is automatic and the dodoLiveProductId/dodoTestProductId fields have been removed from the schema. Any user following the current documentation will look for input fields that no longer exist, making the setup guide actively misleading.
No description provided.