Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ramya/merge node beta #2209

Merged
merged 4 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 17.2.0 - 2024-10-09
* [#2201](https://github.com/stripe/stripe-node/pull/2201) Add fetchRelatedObject to V2 Events if needed
* `fetchRelatedObject` is added to events retrieved using `stripe.v2.core.events` and can be used to easily fetch the Stripe object related to a retrieved event

## 17.2.0-beta.2 - 2024-10-08
* [#2180](https://github.com/stripe/stripe-node/pull/2180) Update generated code for beta
* Add support for `submit_card` test helper method on resource `Issuing.Card`
Expand Down
21 changes: 21 additions & 0 deletions examples/snippets/example_template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* example_template.py - This is a template for defining new examples. It is not intended to be used directly.

* <describe what this example does>

* In this example, we:
* - <key step 1>
* - <key step 2
* - ...

* <describe assumptions about the user's stripe account, environment, or configuration;
* or things to watch out for when running>
*/

import {Stripe} from 'stripe';

const apiKey = '{{API_KEY}}';

console.log('Hello World');
// const client = new Stripe(apiKey);
// client.v2....
12 changes: 12 additions & 0 deletions examples/snippets/meter_event_stream.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/**
* meter_event_stream.ts - Use the high-throughput meter event stream to report create billing meter events.
*
* In this example, we:
* - create a meter event session and store the session's authentication token
* - define an event with a payload
* - use the meterEventStream service to create an event stream that reports this event
*
* This example expects a billing meter with an event_name of 'alpaca_ai_tokens'. If you have
* a different meter event name, you can change it before running this example.
*/

import {Stripe} from 'stripe';

const apiKey = '{{API_KEY}}';
Expand Down
7 changes: 0 additions & 7 deletions examples/snippets/new_example.ts

This file was deleted.

2 changes: 1 addition & 1 deletion examples/snippets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"license": "ISC",
"dependencies": {
"express": "^4.21.0",
"stripe": "file:../../",
"stripe": "file:../..",
"ts-node": "^10.9.2",
"typescript": "^5.6.2"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/**
* thinevent_webhook_handler.js - receive and process thin events like the
* v1.billing.meter.error_report_triggered event.
* In this example, we:
* - create a Stripe client object called client
* - use client.parseThinEvent to parse the received thin event webhook body
* - call client.v2.core.events.retrieve to retrieve the full event object
* - if it is a v1.billing.meter.error_report_triggered event type, call
* event.fetchRelatedObject to retrieve the Billing Meter object associated
* with the event.
*/

const express = require('express');
const {Stripe} = require('stripe');

Expand All @@ -20,11 +32,10 @@ app.post(
// Fetch the event data to understand the failure
const event = await client.v2.core.events.retrieve(thinEvent.id);
if (event.type == 'v1.billing.meter.error_report_triggered') {
const meter = await client.billing.meters.retrieve(
event.related_object.id
);
const meter = await event.fetchRelatedObject();
const meterId = meter.id;
console.log(`Success! ${meterId}`);

// Record the failures and alert your team
// Add your logic here
}
Expand Down
8 changes: 4 additions & 4 deletions examples/snippets/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==

"@types/node@>=8.1.0":
version "22.6.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.6.1.tgz#e531a45f4d78f14a8468cb9cdc29dc9602afc7ac"
integrity sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==
version "22.7.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b"
integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==
dependencies:
undici-types "~6.19.2"

Expand Down Expand Up @@ -524,7 +524,7 @@ [email protected]:
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==

"stripe@file:../..":
version "16.12.0"
version "17.0.0"
dependencies:
"@types/node" ">=8.1.0"
qs "^6.11.0"
Expand Down
68 changes: 60 additions & 8 deletions src/resources/V2/Core/Events.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
// File generated from our OpenAPI spec

// This file is manually maintained
import {StripeResource} from '../../../StripeResource.js';

const stripeMethod = StripeResource.method;

export const Events = StripeResource.extend({
retrieve: stripeMethod({method: 'GET', fullPath: '/v2/core/events/{id}'}),
list: stripeMethod({
method: 'GET',
fullPath: '/v2/core/events',
methodType: 'list',
}),
retrieve(...args: any[]) {
const transformResponseData = (response: any): any => {
return this.addFetchRelatedObjectIfNeeded(response);
};
return stripeMethod({
method: 'GET',
fullPath: '/v2/core/events/{id}',
transformResponseData,
}).apply(this, args);
},

list(...args: any[]) {
const transformResponseData = (response: any): any => {
return {
...response,
data: response.data.map(this.addFetchRelatedObjectIfNeeded.bind(this)),
};
};
return stripeMethod({
method: 'GET',
fullPath: '/v2/core/events',
methodType: 'list',
transformResponseData,
}).apply(this, args);
},

/**
* @private
*
* For internal use in stripe-node.
*
* @param pulledEvent The retrieved event object
* @returns The retrieved event object with a fetchRelatedObject method,
* if pulledEvent.related_object is valid (non-null and has a url)
*/
addFetchRelatedObjectIfNeeded(pulledEvent: any) {
if (!pulledEvent.related_object || !pulledEvent.related_object.url) {
return pulledEvent;
}
return {
...pulledEvent,
fetchRelatedObject: (): Promise<null | any> =>
// call stripeMethod with 'this' resource to fetch
// the related object. 'this' is needed to construct
// and send the request, but the method spec controls
// the url endpoint and method, so it doesn't matter
// that 'this' is an Events resource object here
stripeMethod({
method: 'GET',
fullPath: pulledEvent.related_object.url,
}).apply(this, [
{
stripeAccount: pulledEvent.context,
},
]),
};
},
});
209 changes: 209 additions & 0 deletions test/resources/V2/Core/Events.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
'use strict';

const testUtils = require('../../../testUtils.js');
const expect = require('chai').expect;

const stripe = testUtils.getSpyableStripe();

const v2EventPayloadWithoutRelatedObject = `
{
"context": "context",
"created": "1970-01-12T21:42:34.472Z",
"id": "obj_123",
"livemode": true,
"object":"v2.core.event",
"reason":
{
"type": "request",
"request":
{
"id": "obj_123",
"idempotency_key": "idempotency_key"
}
},
"type": "type"
}
`;

const v2EventPayloadWithRelatedObject = `
{
"context": "context",
"created": "1970-01-12T21:42:34.472Z",
"id": "obj_123",
"livemode": true,
"object":"v2.core.event",
"reason":
{
"type": "request",
"request":
{
"id": "obj_123",
"idempotency_key": "idempotency_key"
}
},
"type": "type",
"related_object":
{
"id": "obj_123",
"type": "thing",
"url": "/v1/things/obj_123"
}
}
`;

describe('V2 Core Events Resource', () => {
describe('retrieve', () => {
it('Sends the correct request', () => {
stripe.v2.core.events.retrieve('eventIdBaz');
expect(stripe.LAST_REQUEST).to.deep.equal({
method: 'GET',
url: '/v2/core/events/eventIdBaz',
headers: {},
data: null,
settings: {},
});
});

it('Does not have fetchRelatedObject if not needed', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events/ll_123',
response: v2EventPayloadWithoutRelatedObject,
},
]);
const event = await mockStripe.v2.core.events.retrieve('ll_123');
expect(event).ok;
expect(event.fetchRelatedObject).to.be.undefined;
});

it('Has fetchRelatedObject if needed', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events/ll_123',
response: v2EventPayloadWithRelatedObject,
},
]);
const event = await mockStripe.v2.core.events.retrieve('ll_123');
expect(event).ok;
expect(event.fetchRelatedObject).ok;
});

it('Can call fetchRelatedObject', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events/ll_123',
response: v2EventPayloadWithRelatedObject,
},
{
method: 'GET',
path: '/v1/things/obj_123',
response: '{"id": "obj_123"}',
},
]);
const event = await mockStripe.v2.core.events.retrieve('ll_123');
expect(event).ok;
expect(event.fetchRelatedObject).ok;
const obj = await event.fetchRelatedObject();
expect(obj.id).to.equal('obj_123');
});
});

describe('list', () => {
it('Sends the correct request', () => {
stripe.v2.core.events.list({object_id: 'foo'});
expect(stripe.LAST_REQUEST).to.deep.equal({
method: 'GET',
url: '/v2/core/events?object_id=foo',
headers: {},
data: null,
settings: {},
});
});

it('Does not have fetchRelatedObject if not needed', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events?object_id=foo',
response: `{
"data": [
${v2EventPayloadWithoutRelatedObject},
${v2EventPayloadWithoutRelatedObject},
${v2EventPayloadWithoutRelatedObject}
],
"next_page_url": null
}`,
},
]);
const resp = await mockStripe.v2.core.events.list({object_id: 'foo'});
expect(resp).ok;
expect(resp.data.length).is.equal(3);
for (const event of resp.data) {
expect(event.fetchRelatedObject).not.ok;
}
});

it('Has fetchRelatedObject if needed', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events?object_id=foo',
response: `{
"data": [
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject}
],
"next_page_url": null
}`,
},
]);
const resp = await mockStripe.v2.core.events.list({object_id: 'foo'});
expect(resp).ok;
expect(resp.data.length).is.equal(3);
for (const event of resp.data) {
expect(event.fetchRelatedObject).ok;
}
});

it('Has fetchRelatedObject added to autoPaginate results', async () => {
const mockStripe = testUtils.createMockClient([
{
method: 'GET',
path: '/v2/core/events?object_id=foo',
response: `{
"data": [
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject}
],
"next_page_url": "/next_page"
}`,
},
{
method: 'GET',
path: '/next_page',
response: `{
"data": [
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject},
${v2EventPayloadWithRelatedObject}
],
"next_page_url": null
}`,
},
]);
const respProm = mockStripe.v2.core.events.list({object_id: 'foo'});
expect(respProm).ok;
let totalEvents = 0;
await respProm.autoPagingEach(function(event) {
totalEvents += 1;
expect(event.fetchRelatedObject).ok;
});
expect(totalEvents).is.equal(6);
});
});
});
Loading
Loading