I’m attempting to set up a dynamic provider for St...
# typescript
p
I’m attempting to set up a dynamic provider for Stripe webhook endpoints but requests are failing with this error:
Invalid Stripe API version: [object Object]
. This is due a serialization issue. Here’s a snippet with the dynamic provider’s source. Any ideas how to avoid this?
h
My guess is
new Stripe
doesn't call JSON.stringify on the apiVersion argument you passed, or it expects a string.
[object Object]
tells me something is converting
{ apiVersion: '...' }
to a string directly.
p
Well, the issue is deeper than that, because if I change the create call to this:
Copy code
const webhookEndpoint = await stripe.webhookEndpoints.create(inputs, {
      apiVersion: '2020-03-02',
    })
Then it just changes the error to this:
Copy code
Stripe: Unknown arguments ([object Object]). Did you mean to pass an options object? See <https://github.com/stripe/stripe-node/wiki/Passing-Options>. (on API request to POST `/webhook_endpoints`)
Is there a way to debug issues for serialized Pulumi code like this?
@gorgeous-egg-16927, is this something you know how to work around?
w
I don’t know the Stripe API - but it definitely looks like you are passing an object where the Stripe API expects a string. It’s not clear to me this is a serialization issue with dynamic providers. Can you
console.log
to see the value of the params?
p
I’m sure I’m calling the API correctly. It’s not a problem outside Pulumi. Here’s what
inputs
shows when printed to the console:
I’ve further simplified the provider to this. As you can see, I pass the api version in a different argument and the error is now this:
Copy code
Stripe: Unknown arguments ([object Object]). Did you mean to pass an options object? See <https://github.com/stripe/stripe-node/wiki/Passing-Options>. (on API request to POST `/webhook_endpoints`)
The object passed in lines 14-16 (
{ apiVersion: '2020-03-02', apiKey }
) is the options object. It’s as if Pulumi is calling
toString
on this object and passing that to Stripe instead. Stripe does expect an object here.
@white-balloon-205, would using an outdated version of
@pulumi/pulumi
cause this? I just updated Pulumi itself to the latest version but
@pulumi/pulumi
is still at
2.5.0
Also, for reference, here’s what
inputs
logs now with this slimmed down provider.
Also, I did try to pass a string, even though Stripe expects an object there and the error simply changes to:
Received unknown parameter: __provider
(no stack)
Ok, so there was a ghost dependency in node_modules with an older version of Stripe… I upgraded but now I’m just getting the
Received unknown parameter: __provider
.
Ok, I got it! 🙂
Copy code
async create({
    __provider,
    ...inputs
  }: Stripe.WebhookEndpointCreateParams & { __provider: unknown }): Promise<CreateResult> {
    const stripe = new Stripe(apiKey, { apiVersion: '2020-03-02' })
    const webhookEndpoint = await stripe.webhookEndpoints.create(inputs)

    return { id: webhookEndpoint.id, outs: webhookEndpoint }
  },
Just had to fix the ghost dependency and exclude the
__provider
field.
w
Not sure what the "ghost dependency" part was about (is that Pulumi related or just an npm/yarn issue?) - but the
__provider
part makes sense - we should document that that will always be included in the inputs bag.
p
Nah, It’s just an old dependency that’s on disk in node_modules even though it’s not in package.json so it’s a Yarn issue
I made a
omitProvider
helper and it’s all working great now! 🙂
Here’s what it’s looking like now.
Now just trying to figure out how to clean up the properties a bit while still being able to access them for Pulumi outputs
Here’s the final version.
@white-balloon-205, don’t know if y’all are looking for feedback on dynamic providers… so here’s some unsolicited feedback haha I think the API is great! I really like how it enables extension of Pulumi’s programming model. The only rough edge I’m seeing is having the declare all the output arguments as
undefined
in the constructor.
I’m also trying to find a way to remove the need to declare all those outputs in the resource and spread them from Stripe’s TypeScript types somehow. But that’s a TypeScript problem, not Pulumi’s
Also, setting all to
undefined
makes Pulumi show the preview as
output<string>
is there a way to give a hint for the type of these outputs?
w
The only rough edge I’m seeing is having the declare all the output arguments as 
undefined
 in the constructor.
Agreed - this is an unintuitive part of the API design - and I expect is something we could improve. Would you mind opening an issue to track this suggestion?
setting all to 
undefined
 makes Pulumi show the preview as 
output<string>
 is there a way to give a hint for the type of these outputs?
Not sure I follow this one - could you give an example of this?
p
For example, the
livemode
field is a boolean, but because I set it to
undefined
in the call to
super
, when running
pulumi up
, the preview shows an object with
output<string>
for all the values. I was wondering if there was some way to make it say
output<boolean>
or
output<number>
depending on what the field type is
And yeah, I can open an issue
One more thing, when running
pulumi up
, the preview shows all existing values as changing to
output<string>
in the preview. I would’ve expected that having those fields in the
stables
return of the
diff
provider function to be enough for Pulumi to know that those fields won’t change on subsequent updates. Here’s a screenshot. In this update, all that should be changing is
metadata
and
enabled_events
, but because the other fields aren’t part of the resource arguments (they’re just outputs from the API), then Pulumi shows them as
=> output<string>
. All these fields are returned in the
stables
array in
diff
.
Here was the result after accepting the preview and running the update: