Skip to content

Commit

Permalink
create webhook endpoint (#536)
Browse files Browse the repository at this point in the history
* create webhook endpoint

* address comments
  • Loading branch information
etsai-stripe authored Feb 10, 2022
1 parent 94512a7 commit 41d209a
Show file tree
Hide file tree
Showing 12 changed files with 523 additions and 19 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"onView:stripeQuickLinksView",
"onView:stripeHelpView",
"onCommand:stripe.createStripeSample",
"onCommand:stripe.createWebhookEndpoint",
"onCommand:stripe.login",
"onCommand:stripe.openCLI",
"onCommand:stripe.openWebhooksListen",
Expand Down Expand Up @@ -152,6 +153,11 @@
"command": "stripe.openWebhooksDebugConfigure",
"title": "Configure webhooks debugging"
},
{
"category": "Stripe",
"command": "stripe.createWebhookEndpoint",
"title": "Create a new webhook endpoint"
},
{
"category": "Stripe",
"command": "stripe.startEventsStreaming",
Expand Down
55 changes: 49 additions & 6 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as grpc from '@grpc/grpc-js';
import * as querystring from 'querystring';
import * as vscode from 'vscode';
import {
Expand Down Expand Up @@ -29,10 +30,12 @@ import {StripeLogsViewProvider} from './stripeLogsView';
import {StripeSamples} from './stripeSamples';
import {StripeTerminal} from './stripeTerminal';
import {StripeTreeItem} from './stripeTreeItem';
import {StripeWebhooksViewProvider} from './stripeWebhooksView';
import {SurveyPrompt} from './surveyPrompt';
import {Telemetry} from './telemetry';
import {TriggerRequest} from './rpc/trigger_pb';
import {TriggersListRequest} from './rpc/triggers_list_pb';
import {WebhookEndpointCreateRequest} from './rpc/webhook_endpoint_create_pb';

export class Commands {
telemetry: Telemetry;
Expand Down Expand Up @@ -416,9 +419,7 @@ export class Commands {
fixtureRequest.setEvent(eventName);
daemonClient.fixture(fixtureRequest, (error, response) => {
if (error) {
if (error.code === 12) {
// https://grpc.github.io/grpc/core/md_doc_statuscodes.html
// 12: UNIMPLEMENTED
if (error.code === grpc.status.UNIMPLEMENTED) {
vscode.window.showErrorMessage(
'Please upgrade your Stripe CLI to the latest version to use this feature.',
);
Expand Down Expand Up @@ -494,9 +495,7 @@ export class Commands {

daemonClient.trigger(triggerRequest, (error, response) => {
if (error) {
if (error.code === 12) {
// https://grpc.github.io/grpc/core/md_doc_statuscodes.html
// 12: UNIMPLEMENTED
if (error.code === grpc.status.UNIMPLEMENTED) {
vscode.window.showErrorMessage(
'Please upgrade your Stripe CLI to the latest version to use this feature.',
);
Expand Down Expand Up @@ -628,4 +627,48 @@ export class Commands {
this.telemetry.sendEvent('createStripeSample');
await stripeSamples.selectAndCloneSample();
};

createWebhookEndpoint = async (
stripeDaemon: StripeDaemon,
stripeOutputChannel: vscode.OutputChannel,
stripeWebhooksViewProvider: StripeWebhooksViewProvider,
) => {
const url = await vscode.window.showInputBox({
prompt: 'URL of the webhook endpoint.',
value: 'https://',
});
const description = await vscode.window.showInputBox({
prompt: 'Optional description of what the webhook is used for.',
});
const connect = await vscode.window.showQuickPick(['Connected accounts', 'Your account only'], {
placeHolder: 'Should this endpoint receive events from connected accounts or from your account.',
});
const isConnect = connect === 'Connected accounts';

const createRequest = new WebhookEndpointCreateRequest();
createRequest.setUrl(url || '');
createRequest.setDescription(description || '');
createRequest.setConnect(isConnect);

const daemonClient = await stripeDaemon.setupClient();
daemonClient.webhookEndpointCreate(createRequest, (error, response) => {
if (error) {
if (error.code === grpc.status.UNIMPLEMENTED) {
vscode.window.showErrorMessage(
'Please upgrade your Stripe CLI to the latest version to use this feature.',
);
} else {
vscode.window.showErrorMessage(
`Failed to create webhook endpoint ${url}. ${error.details}`,
);
}
} else if (response) {
stripeOutputChannel.appendLine(`Webhook endpoint ${url} created. Please go to the developer dashboard to update the details of the endpoint.`);
this.telemetry.sendEvent('createWebhookEndpoint');

// refresh webhook endpoints tree
stripeWebhooksViewProvider.refreshEndpoints();
}
});
};
}
4 changes: 4 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ export function activate(this: any, context: ExtensionContext) {
],
['stripe.openWebhooksDebugConfigure', stripeCommands.openWebhooksDebugConfigure],
['stripe.openWebhooksListen', stripeCommands.openWebhooksListen],
[
'stripe.createWebhookEndpoint',
() => stripeCommands.createWebhookEndpoint(stripeDaemon, stripeOutputChannel, stripeWebhooksViewProvider),
],
[
'stripe.resendEvent',
(treeItem) => stripeCommands.resendEvent(treeItem, stripeDaemon, stripeOutputChannel),
Expand Down
6 changes: 6 additions & 0 deletions src/rpc/commands_grpc_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as samples_list_pb from "./samples_list_pb";
import * as trigger_pb from "./trigger_pb";
import * as triggers_list_pb from "./triggers_list_pb";
import * as version_pb from "./version_pb";
import * as webhook_endpoint_create_pb from "./webhook_endpoint_create_pb";
import * as webhook_endpoints_list_pb from "./webhook_endpoints_list_pb";
import * as grpc from "@grpc/grpc-js";

Expand All @@ -32,6 +33,7 @@ interface IStripeCLIService extends grpc.ServiceDefinition<grpc.UntypedServiceIm
trigger: grpc.MethodDefinition<trigger_pb.TriggerRequest, trigger_pb.TriggerResponse>;
triggersList: grpc.MethodDefinition<triggers_list_pb.TriggersListRequest, triggers_list_pb.TriggersListResponse>;
version: grpc.MethodDefinition<version_pb.VersionRequest, version_pb.VersionResponse>;
webhookEndpointCreate: grpc.MethodDefinition<webhook_endpoint_create_pb.WebhookEndpointCreateRequest, webhook_endpoint_create_pb.WebhookEndpointCreateResponse>;
webhookEndpointsList: grpc.MethodDefinition<webhook_endpoints_list_pb.WebhookEndpointsListRequest, webhook_endpoints_list_pb.WebhookEndpointsListResponse>;
}

Expand All @@ -50,6 +52,7 @@ export interface IStripeCLIServer extends grpc.UntypedServiceImplementation {
trigger: grpc.handleUnaryCall<trigger_pb.TriggerRequest, trigger_pb.TriggerResponse>;
triggersList: grpc.handleUnaryCall<triggers_list_pb.TriggersListRequest, triggers_list_pb.TriggersListResponse>;
version: grpc.handleUnaryCall<version_pb.VersionRequest, version_pb.VersionResponse>;
webhookEndpointCreate: grpc.handleUnaryCall<webhook_endpoint_create_pb.WebhookEndpointCreateRequest, webhook_endpoint_create_pb.WebhookEndpointCreateResponse>;
webhookEndpointsList: grpc.handleUnaryCall<webhook_endpoints_list_pb.WebhookEndpointsListRequest, webhook_endpoints_list_pb.WebhookEndpointsListResponse>;
}

Expand Down Expand Up @@ -89,6 +92,9 @@ export class StripeCLIClient extends grpc.Client {
version(argument: version_pb.VersionRequest, callback: grpc.requestCallback<version_pb.VersionResponse>): grpc.ClientUnaryCall;
version(argument: version_pb.VersionRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<version_pb.VersionResponse>): grpc.ClientUnaryCall;
version(argument: version_pb.VersionRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<version_pb.VersionResponse>): grpc.ClientUnaryCall;
webhookEndpointCreate(argument: webhook_endpoint_create_pb.WebhookEndpointCreateRequest, callback: grpc.requestCallback<webhook_endpoint_create_pb.WebhookEndpointCreateResponse>): grpc.ClientUnaryCall;
webhookEndpointCreate(argument: webhook_endpoint_create_pb.WebhookEndpointCreateRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<webhook_endpoint_create_pb.WebhookEndpointCreateResponse>): grpc.ClientUnaryCall;
webhookEndpointCreate(argument: webhook_endpoint_create_pb.WebhookEndpointCreateRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<webhook_endpoint_create_pb.WebhookEndpointCreateResponse>): grpc.ClientUnaryCall;
webhookEndpointsList(argument: webhook_endpoints_list_pb.WebhookEndpointsListRequest, callback: grpc.requestCallback<webhook_endpoints_list_pb.WebhookEndpointsListResponse>): grpc.ClientUnaryCall;
webhookEndpointsList(argument: webhook_endpoints_list_pb.WebhookEndpointsListRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<webhook_endpoints_list_pb.WebhookEndpointsListResponse>): grpc.ClientUnaryCall;
webhookEndpointsList(argument: webhook_endpoints_list_pb.WebhookEndpointsListRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<webhook_endpoints_list_pb.WebhookEndpointsListResponse>): grpc.ClientUnaryCall;
Expand Down
35 changes: 35 additions & 0 deletions src/rpc/commands_grpc_pb.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var samples_list_pb = require('./samples_list_pb.js');
var trigger_pb = require('./trigger_pb.js');
var triggers_list_pb = require('./triggers_list_pb.js');
var version_pb = require('./version_pb.js');
var webhook_endpoint_create_pb = require('./webhook_endpoint_create_pb.js');
var webhook_endpoints_list_pb = require('./webhook_endpoints_list_pb.js');

function serialize_rpc_EventsResendRequest(arg) {
Expand Down Expand Up @@ -280,6 +281,28 @@ function deserialize_rpc_VersionResponse(buffer_arg) {
return version_pb.VersionResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_rpc_WebhookEndpointCreateRequest(arg) {
if (!(arg instanceof webhook_endpoint_create_pb.WebhookEndpointCreateRequest)) {
throw new Error('Expected argument of type rpc.WebhookEndpointCreateRequest');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_rpc_WebhookEndpointCreateRequest(buffer_arg) {
return webhook_endpoint_create_pb.WebhookEndpointCreateRequest.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_rpc_WebhookEndpointCreateResponse(arg) {
if (!(arg instanceof webhook_endpoint_create_pb.WebhookEndpointCreateResponse)) {
throw new Error('Expected argument of type rpc.WebhookEndpointCreateResponse');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_rpc_WebhookEndpointCreateResponse(buffer_arg) {
return webhook_endpoint_create_pb.WebhookEndpointCreateResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_rpc_WebhookEndpointsListRequest(arg) {
if (!(arg instanceof webhook_endpoints_list_pb.WebhookEndpointsListRequest)) {
throw new Error('Expected argument of type rpc.WebhookEndpointsListRequest');
Expand Down Expand Up @@ -450,6 +473,18 @@ version: {
responseSerialize: serialize_rpc_VersionResponse,
responseDeserialize: deserialize_rpc_VersionResponse,
},
// Create a new webhook endpoint
webhookEndpointCreate: {
path: '/rpc.StripeCLI/WebhookEndpointCreate',
requestStream: false,
responseStream: false,
requestType: webhook_endpoint_create_pb.WebhookEndpointCreateRequest,
responseType: webhook_endpoint_create_pb.WebhookEndpointCreateResponse,
requestSerialize: serialize_rpc_WebhookEndpointCreateRequest,
requestDeserialize: deserialize_rpc_WebhookEndpointCreateRequest,
responseSerialize: serialize_rpc_WebhookEndpointCreateResponse,
responseDeserialize: deserialize_rpc_WebhookEndpointCreateResponse,
},
// Get the list of webhook endpoints.
webhookEndpointsList: {
path: '/rpc.StripeCLI/WebhookEndpointsList',
Expand Down
1 change: 1 addition & 0 deletions src/rpc/commands_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ import * as samples_list_pb from "./samples_list_pb";
import * as trigger_pb from "./trigger_pb";
import * as triggers_list_pb from "./triggers_list_pb";
import * as version_pb from "./version_pb";
import * as webhook_endpoint_create_pb from "./webhook_endpoint_create_pb";
import * as webhook_endpoints_list_pb from "./webhook_endpoints_list_pb";

2 changes: 2 additions & 0 deletions src/rpc/commands_pb.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ var triggers_list_pb = require('./triggers_list_pb.js');
goog.object.extend(proto, triggers_list_pb);
var version_pb = require('./version_pb.js');
goog.object.extend(proto, version_pb);
var webhook_endpoint_create_pb = require('./webhook_endpoint_create_pb.js');
goog.object.extend(proto, webhook_endpoint_create_pb);
var webhook_endpoints_list_pb = require('./webhook_endpoints_list_pb.js');
goog.object.extend(proto, webhook_endpoints_list_pb);
1 change: 1 addition & 0 deletions src/rpc/webhook_endpoint_create_grpc_pb.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// GENERATED CODE -- NO SERVICES IN PROTO
1 change: 1 addition & 0 deletions src/rpc/webhook_endpoint_create_grpc_pb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// GENERATED CODE -- NO SERVICES IN PROTO
49 changes: 49 additions & 0 deletions src/rpc/webhook_endpoint_create_pb.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// package: rpc
// file: webhook_endpoint_create.proto

import * as jspb from "google-protobuf";

export class WebhookEndpointCreateRequest extends jspb.Message {
getUrl(): string;
setUrl(value: string): void;

getDescription(): string;
setDescription(value: string): void;

getConnect(): boolean;
setConnect(value: boolean): void;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): WebhookEndpointCreateRequest.AsObject;
static toObject(includeInstance: boolean, msg: WebhookEndpointCreateRequest): WebhookEndpointCreateRequest.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: WebhookEndpointCreateRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): WebhookEndpointCreateRequest;
static deserializeBinaryFromReader(message: WebhookEndpointCreateRequest, reader: jspb.BinaryReader): WebhookEndpointCreateRequest;
}

export namespace WebhookEndpointCreateRequest {
export type AsObject = {
url: string,
description: string,
connect: boolean,
}
}

export class WebhookEndpointCreateResponse extends jspb.Message {
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): WebhookEndpointCreateResponse.AsObject;
static toObject(includeInstance: boolean, msg: WebhookEndpointCreateResponse): WebhookEndpointCreateResponse.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: WebhookEndpointCreateResponse, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): WebhookEndpointCreateResponse;
static deserializeBinaryFromReader(message: WebhookEndpointCreateResponse, reader: jspb.BinaryReader): WebhookEndpointCreateResponse;
}

export namespace WebhookEndpointCreateResponse {
export type AsObject = {
}
}

Loading

0 comments on commit 41d209a

Please sign in to comment.